]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0875: GTK4: GUI does not support command-line arguments v9.2.0875
authorFoxe Chen <chen.foxe@gmail.com>
Wed, 29 Jul 2026 19:34:29 +0000 (19:34 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 29 Jul 2026 19:39:39 +0000 (19:39 +0000)
Problem:  The GTK4 GUI does not support command-line arguments
Solution: Parse the supported GUI arguments in gui_mch_prepare()
          and add the GTK4-specific --prg-name argument (Foxe Chen).

closes: #20847

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/gui.txt
runtime/doc/gui_x11.txt
runtime/doc/vim.1
runtime/doc/vim.man
src/globals.h
src/gui_gtk4.c
src/main.c
src/po/vim.pot
src/version.c

index 5edf1abcb170a2c736242a9a10db14ed0d1386f1..89fdb0137f4c8e7bb864d73f5507e7791907e897 100644 (file)
@@ -25,7 +25,7 @@ Other GUI documentation:
 
 First you must make sure you actually have a version of Vim with the GUI code
 included.  You can check this with the ":version" command, it says "with xxx
-GUI", where "xxx" is X11-Motif, Photon, GTK2, GTK3, etc., or
+GUI", where "xxx" is X11-Motif, Photon, GTK2, GTK3, GTK4, etc., or
 "MS-Windows 32 bit GUI version".
 
 How to start the GUI depends on the system used.  Mostly you can run the
index 8f37a154c00088481a88927885149953d0f153ac..3bb469cecda234f4f2e9bdf10e6e6aae9524c6ef 100644 (file)
@@ -321,11 +321,24 @@ stuff like -bg, -fg, etc).  The ones that are supported are:
     -fg -foreground {color}                    foreground color
     -bg -background {color}                    background color
 
+If using the GTK4 GUI, then only the following are supported:
+    -fn  or  -font
+    -geom  or  -geometry    (window positioning is NOT supported)
+    -fg -foreground {color}
+    -bg -background {color}
+
+Command line arguments specific to GTK4:
+    command line argument   meaning ~
+    --prg-name {name}      Argument passed to g_set_prgname(), otherwise
+                           "gvim" is used.  On Wayland this will set the app
+                           id, which is equivalent to the X11 WM_CLASS
+
 To set the font, see 'guifont'.  For GTK, there's also a menu option that does
 this.
 
 Additionally, there are these command line arguments, which are handled by GTK
-internally.  Look in the GTK documentation for how they are used:
+internally (except GTK4, see below).  Look in the GTK documentation for how
+they are used:
        --sync
        --gdk-debug
        --gdk-no-debug
@@ -343,6 +356,10 @@ These arguments are ignored when the |+netbeans_intg| feature is used:
        -xrm
        -mf
 
+If using the GTK4 GUI, then no GTK specific command line arguments are
+supported. Instead configure GTK via environment variables:
+https://docs.gtk.org/gtk4/running.html
+
 As for colors, Vim's color settings (for syntax highlighting) is still
 done the traditional Vim way.  See |:highlight| for more help.
 
index 93c28d6ace8f3bece009c704221f1b10610e125d..c6d6527c06513e8caba8f9a3867e9b8092799b60 100644 (file)
@@ -485,6 +485,9 @@ that the user knows that the input and/or output is not connected to a
 terminal.  This will avoid the warning and the two second delay that would
 happen.
 .TP
+\--prg-name {name}
+Set GTK program name. Only for GTK4 GUI.
+.TP
 \-\-remote
 Connect to a Vim server and make it edit the files given in the rest of the
 arguments.  If no server is found a warning is given and the files are edited
index 583d9d28fde04006fc79a58908eb7b7e5db9bb10..2bcd8d6b59904acc4936124647337bb633d0dcef 100644 (file)
@@ -355,6 +355,9 @@ OPTIONS
                    is not connected to a terminal.  This will avoid the  warn‐
                    ing and the two second delay that would happen.
 
+       --prg-name {name}
+                   Set GTK program name. Only for GTK4 GUI.
+
        --remote    Connect to a Vim server and make it edit the files given in
                    the rest of the arguments.  If no server is found a warning
                    is given and the files are edited in the current Vim.
index 8550725235cbe0aa4e35e9c0a00aab5c3b8286e4..8e0a37494e2fb297e5e7d67d2fd8bc8d937b5331 100644 (file)
@@ -1885,7 +1885,7 @@ EXTERN Display    *xterm_dpy INIT(= NULL);
 EXTERN XtAppContext app_context INIT(= (XtAppContext)NULL);
 #endif
 
-#ifdef FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) && !defined(USE_GTK4)
 EXTERN guint32 gtk_socket_id INIT(= 0);
 EXTERN int     echo_wid_arg INIT(= FALSE);     // --echo-wid argument
 #endif
index 93851af7c2fe89ead2855e1e43786e3b4b9fe806..45ee9f505d5995b8223eb9a6de42130bb3ca743f 100644 (file)
  * Format: [WIDTHxHEIGHT][{+-}XOFF{+-}YOFF]
  */
 #define NoValue                0x0000
-#define XValue         0x0001
-#define YValue         0x0002
 #define WidthValue     0x0004
 #define HeightValue    0x0008
-#define XNegative      0x0010
-#define YNegative      0x0020
 
     static int
-vim_parse_geometry(const char *str, int *x, int *y,
-       unsigned int *width, unsigned int *height)
+vim_parse_geometry(const char *str, unsigned int *width, unsigned int *height)
 {
     int mask = NoValue;
     char *end;
@@ -86,37 +81,6 @@ vim_parse_geometry(const char *str, int *x, int *y,
        }
     }
 
-    // Parse x offset
-    if (*str == '+' || *str == '-')
-    {
-       int negative = (*str == '-');
-       str++;
-       val = strtol(str, &end, 10);
-       if (end != str)
-       {
-           *x = negative ? -(int)val : (int)val;
-           mask |= XValue;
-           if (negative)
-               mask |= XNegative;
-           str = end;
-       }
-    }
-
-    // Parse y offset
-    if (*str == '+' || *str == '-')
-    {
-       int negative = (*str == '-');
-       str++;
-       val = strtol(str, &end, 10);
-       if (end != str)
-       {
-           *y = negative ? -(int)val : (int)val;
-           mask |= YValue;
-           if (negative)
-               mask |= YNegative;
-       }
-    }
-
     return mask;
 }
 
@@ -300,6 +264,28 @@ static void clipboard_changed_cb(GdkClipboard *clipboard, gpointer user_data);
 static void show_menubar_popover(void);
 #endif
 
+static const char *prgname = NULL;
+
+/*
+ * Check if "s" is the option "name" (which includes the leading dash(es)).
+ * "value" is set to the value if the option uses 'opt=val' format.
+ */
+    static gboolean
+arg_match(const char *s, const char *name, char **value)
+{
+    size_t  len = strlen(name);
+
+    if (strncmp(s, name, len) != 0)
+       return FALSE;
+    if (s[len] == '=')
+       *value = (char *)s + len + 1;
+    else if (s[len] != NUL)
+       // Something follows the option name that isn't "=": this is a
+       // different, longer option (e.g. "-fnord" while matching "-fn").
+       return FALSE;
+    return TRUE;
+}
+
 /*
  * Parse the GUI related command-line arguments.  Any arguments used are
  * deleted from argv, and *argc is decremented accordingly.  This is called
@@ -312,6 +298,86 @@ gui_mch_prepare(int *argc, char **argv)
     // gui_mch_init_check() after the fork.  Calling it before fork
     // breaks the display connection in the child process, causing gvim
     // to fail to start without --nofork.
+
+    int        i = 0;
+
+    while (i < *argc)
+    {
+       char    *s = argv[i];
+       char    *value = NULL;
+       int     has_inline_value = FALSE;
+       int     n_strip;
+
+       if (s[0] != '-' && s[0] != '+')
+       {
+           ++i;
+           continue;
+       }
+
+       if (strchr(s, '=') != NULL)
+           has_inline_value = TRUE;
+
+       // If the value was not given inline (no "="), it would come from the
+       // next argv element.  Do not treat that next element as this option's
+       // value if it is "--" (end-of-options marker) or is another option.
+       if (!has_inline_value)
+       {
+           if (i + 1 < *argc
+                   && strcmp(argv[i + 1], "--") != 0
+                   && !((argv[i + 1][0] == '-' || argv[i + 1][0] == '+')
+                       && !vim_isdigit(argv[i + 1][1])))
+               value = argv[i + 1];
+           else
+               value = NULL;
+       }
+
+       if (arg_match(s, "-fn", &value) || arg_match(s, "-font", &value))
+           font_argument = value;
+       else if (arg_match(s, "-geom", &value)
+               || arg_match(s, "-geometry", &value))
+       {
+           if (value != NULL)
+               gui.geom = vim_strsave((char_u *)value);
+       }
+       else if (arg_match(s, "-bg", &value)
+               || arg_match(s, "-background", &value))
+           background_argument = value;
+       else if (arg_match(s, "-fg", &value)
+               || arg_match(s, "-foreground", &value))
+           foreground_argument = value;
+       else if (strncmp(s, "-nb", 3) == 0)
+       {
+           gui.dofork = false; // don't fork() when starting GUI
+           netbeansArg = argv[i];
+           has_inline_value = TRUE; // -nb uses non standard syntax, just
+                                    // remove the flag.
+       }
+       else if (arg_match(s, "--prg-name", &value))
+           // GTK4 specific
+           prgname = value;
+       else
+       {
+           i++;
+           continue;
+       }
+
+       // Remove the flag from the argument vector.
+       n_strip = 1;
+       // Move the argument's value as well, but only if it was consumed
+       // from a separate argv element (the "-opt=value" form lives inside
+       // the flag's own element and is stripped along with it already).
+       if (value != NULL && !has_inline_value)
+           n_strip = 2;
+
+       if (*argc - n_strip >= i)
+       {
+           *argc -= n_strip;
+           if (*argc > i)
+               mch_memmove(&argv[i], &argv[i + n_strip],
+                       (*argc - i) * sizeof(char *));
+           argv[*argc] = NULL;
+       }
+    }
 }
 
 /*
@@ -417,8 +483,9 @@ gui_mch_init_check(void)
 {
     // This defaults to argv[0], but we want it to match the name of the
     // shipped gvim.desktop so that Vim's windows can be associated with this
-    // file.  Also sets WM_CLASS on X11.
-    g_set_prgname("gvim");
+    // file.  Also sets WM_CLASS on X11. If "--prg-name" is specified, then use
+    // that.
+    g_set_prgname(prgname == NULL ? "gvim" : prgname);
 
     // Suppress noisy EGL warnings when GL is not available.  Only set
     // this when actually starting the GUI, so non-GUI invocations are
@@ -668,10 +735,8 @@ gui_mch_open(void)
     {
        int             mask;
        unsigned int    w, h;
-       int             x = 0;
-       int             y = 0;
 
-       mask = vim_parse_geometry((char *)gui.geom, &x, &y, &w, &h);
+       mask = vim_parse_geometry((char *)gui.geom, &w, &h);
 
        if (mask & WidthValue)
            Columns = w;
@@ -685,12 +750,15 @@ gui_mch_open(void)
 
        VIM_CLEAR(gui.geom);
     }
+    else
+    {
+       // Use 80x24 as the default GUI size, unless geometry was specified.
+       if (Columns > 80)
+           Columns = 80;
+       if (Rows > 24)
+           Rows = 24;
+    }
 
-    // Use 80x24 as the default GUI size, unless geometry was specified.
-    if (Columns > 80 && gui.geom == NULL)
-       Columns = 80;
-    if (Rows > 24 && gui.geom == NULL)
-       Rows = 24;
     pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width);
     pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height);
     gtk_window_set_default_size(GTK_WINDOW(gui.mainwin),
@@ -725,6 +793,7 @@ gui_mch_open(void)
                     G_CALLBACK(mainwin_destroy_cb), NULL);
     // Resize is handled by GtkForm's size_allocate callback.
 
+    // Not sure if this needed but still do it I guess?
     gtk_widget_set_visible(gui.mainwin, TRUE);
 
     // Make sure the drawing area gets keyboard focus.
index 53a292325633268d929a8334b42af9e9f8703d4c..95d0494a151304e171dfc277611b693cfe878bbc 100644 (file)
@@ -1965,13 +1965,13 @@ early_arg_scan(mparm_T *parmp UNUSED)
            else
 #  ifdef FEAT_GUI_MSWIN
                win_socket_id = id;
-#  else
+#  elif !defined(USE_GTK4)
                gtk_socket_id = id;
 #  endif
            i++;
        }
 # endif
-# ifdef FEAT_GUI_GTK
+# if defined(FEAT_GUI_GTK) && !defined(USE_GTK4)
        else if (STRICMP(argv[i], "--echo-wid") == 0)
            echo_wid_arg = TRUE;
 # endif
@@ -3812,17 +3812,25 @@ usage(void)
     main_msg(_("-xrm <resource>\tSet the specified resource"));
 # endif // FEAT_GUI_X11
 # ifdef FEAT_GUI_GTK
+#  ifdef USE_GTK4
+    mch_msg(_("\nArguments recognised by gvim (GTK4 version):\n"));
+#  else
     mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
+#  endif
     main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
     main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
     main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
     main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
+#  ifdef USE_GTK4
+    main_msg("--prg-name <name>\tSet GTK program name");
+#  else
     main_msg(_("-iconic\t\tStart Vim iconified"));
     main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
     main_msg(_("-display <display>\tRun Vim on <display> (also: --display)"));
     main_msg(_("--role <role>\tSet a unique role to identify the main window"));
     main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget"));
     main_msg(_("--echo-wid\t\tMake gvim echo the Window ID on stdout"));
+#  endif
 # endif
 # ifdef FEAT_GUI_MSWIN
 #  ifdef VIMDLL
index b6ded21320a4d67466d587913d5a2c08707d70e7..8f7f2e070f21e245b721da1afd2349444a69421a 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Vim\n"
 "Report-Msgid-Bugs-To: vim-dev@vim.org\n"
-"POT-Creation-Date: 2026-07-27 20:48+0000\n"
+"POT-Creation-Date: 2026-07-29 19:37+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -1821,6 +1821,11 @@ msgstr ""
 msgid "-xrm <resource>\tSet the specified resource"
 msgstr ""
 
+msgid ""
+"\n"
+"Arguments recognised by gvim (GTK4 version):\n"
+msgstr ""
+
 msgid ""
 "\n"
 "Arguments recognised by gvim (GTK+ version):\n"
index 9d2474d6874acd12bac6716ea8e6b4a88f581007..0f6a4742277a28602fdc24332d012cad80c7682f 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    875,
 /**/
     874,
 /**/