Commit: patch 9.2.0875: GTK4: GUI does not support command-line arguments

Christian Brabandt <[email protected]> Wed, 29 Jul 2026 21:45:05 +0200
Newsgroups gmane.editors.vim.devel
Message-ID <[email protected]>
patch 9.2.0875: GTK4: GUI does not support command-line arguments

Commit: https://github.com/vim/vim/commit/7556f1cba5b76cbf69ccf68068d3156ca164029c
Author: Foxe Chen <[email protected]>
Date:   Wed Jul 29 19:34:29 2026 +0000

    patch 9.2.0875: GTK4: GUI does not support command-line arguments
    
    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 <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index 5edf1abcb..89fdb0137 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -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
diff --git a/runtime/doc/gui_x11.txt b/runtime/doc/gui_x11.txt
index 8f37a154c..3bb469cec 100644
--- a/runtime/doc/gui_x11.txt
+++ b/runtime/doc/gui_x11.txt
@@ -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.
 
diff --git a/runtime/doc/vim.1 b/runtime/doc/vim.1
index 93c28d6ac..c6d6527c0 100644
--- a/runtime/doc/vim.1
+++ b/runtime/doc/vim.1
@@ -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
diff --git a/runtime/doc/vim.man b/runtime/doc/vim.man
index 583d9d28f..2bcd8d6b5 100644
--- a/runtime/doc/vim.man
+++ b/runtime/doc/vim.man
@@ -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.
diff --git a/src/globals.h b/src/globals.h
index 855072523..8e0a37494 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -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
diff --git a/src/gui_gtk4.c b/src/gui_gtk4.c
index 93851af7c..45ee9f505 100644
--- a/src/gui_gtk4.c
+++ b/src/gui_gtk4.c
@@ -43,16 +43,11 @@
  * 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.
diff --git a/src/main.c b/src/main.c
index 53a292325..95d0494a1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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>	Set the specified resource"));
 # endif // FEAT_GUI_X11
 # ifdef FEAT_GUI_GTK
+#  ifdef USE_GTK4
+    mch_msg(_("
Arguments recognised by gvim (GTK4 version):
"));
+#  else
     mch_msg(_("
Arguments recognised by gvim (GTK+ version):
"));
+#  endif
     main_msg(_("-background <color>	Use <color> for the background (also: -bg)"));
     main_msg(_("-foreground <color>	Use <color> for normal text (also: -fg)"));
     main_msg(_("-font <font>		Use <font> for normal text (also: -fn)"));
     main_msg(_("-geometry <geom>	Use <geom> for initial geometry (also: -geom)"));
+#  ifdef USE_GTK4
+    main_msg("--prg-name <name>	Set GTK program name");
+#  else
     main_msg(_("-iconic		Start Vim iconified"));
     main_msg(_("-reverse		Use reverse video (also: -rv)"));
     main_msg(_("-display <display>	Run Vim on <display> (also: --display)"));
     main_msg(_("--role <role>	Set a unique role to identify the main window"));
     main_msg(_("--socketid <xid>	Open Vim inside another GTK widget"));
     main_msg(_("--echo-wid		Make gvim echo the Window ID on stdout"));
+#  endif
 # endif
 # ifdef FEAT_GUI_MSWIN
 #  ifdef VIMDLL
diff --git a/src/po/vim.pot b/src/po/vim.pot
index b6ded2132..8f7f2e070 100644
--- a/src/po/vim.pot
+++ b/src/po/vim.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Vim
"
 "Report-Msgid-Bugs-To: [email protected]
"
-"POT-Creation-Date: 2026-07-27 20:48+0000
"
+"POT-Creation-Date: 2026-07-29 19:37+0000
"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>
"
 "Language-Team: LANGUAGE <[email protected]>
"
@@ -1821,6 +1821,11 @@ msgstr ""
 msgid "-xrm <resource>	Set the specified resource"
 msgstr ""
 
+msgid ""
+"
"
+"Arguments recognised by gvim (GTK4 version):
"
+msgstr ""
+
 msgid ""
 "
"
 "Arguments recognised by gvim (GTK+ version):
"
diff --git a/src/version.c b/src/version.c
index 9d2474d68..0f6a47422 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    875,
 /**/
     874,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups "vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1wpADB-002wx4-Mm%40256bit.org.