summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/builtin.txt8
-rw-r--r--src/gui.c5
-rw-r--r--src/gui.h1
-rw-r--r--src/gui_gtk_x11.c185
-rw-r--r--src/os_unix.c5
-rw-r--r--src/testdir/check.vim8
-rw-r--r--src/testdir/test_clientserver.vim2
-rw-r--r--src/testdir/test_gui.vim4
-rw-r--r--src/testdir/test_quotestar.vim4
-rw-r--r--src/testdir/test_startup.vim12
-rw-r--r--src/testdir/test_vim9_builtin.vim2
-rw-r--r--src/version.c2
12 files changed, 180 insertions, 58 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 88cf642ca4..5001205ea6 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt* For Vim version 9.1. Last change: 2024 Jan 25
+*builtin.txt* For Vim version 9.1. Last change: 2024 Jan 29
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -4424,14 +4424,16 @@ getwinpos([{timeout}]) *getwinpos()*
getwinposx() The result is a Number, which is the X coordinate in pixels of
the left hand side of the GUI Vim window. Also works for an
xterm (uses a timeout of 100 msec).
- The result will be -1 if the information is not available.
+ The result will be -1 if the information is not available
+ (e.g. on the Wayland backend).
The value can be used with `:winpos`.
*getwinposy()*
getwinposy() The result is a Number, which is the Y coordinate in pixels of
the top of the GUI Vim window. Also works for an xterm (uses
a timeout of 100 msec).
- The result will be -1 if the information is not available.
+ The result will be -1 if the information is not available
+ (e.g. on the Wayland backend).
The value can be used with `:winpos`.
getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*
diff --git a/src/gui.c b/src/gui.c
index 223ede2828..29e462380c 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -1589,8 +1589,11 @@ again:
// Only comparing Rows and Columns may be sufficient, but let's stay on
// the safe side.
if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns
- || gui.num_rows != Rows || gui.num_cols != Columns)
+ || gui.num_rows != Rows || gui.num_cols != Columns || gui.force_redraw)
+ {
shell_resized();
+ gui.force_redraw = 0;
+ }
#ifdef FEAT_GUI_HAIKU
vim_unlock_screen();
diff --git a/src/gui.h b/src/gui.h
index 1882000f6b..c677ba1fe4 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -259,6 +259,7 @@ typedef struct Gui
int scrollbar_height; // Height of horizontal scrollbar
int left_sbar_x; // Calculated x coord for left scrollbar
int right_sbar_x; // Calculated x coord for right scrollbar
+ int force_redraw; // Force a redraw even e.g. not resized
#ifdef FEAT_MENU
# ifndef FEAT_GUI_GTK
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c
index 4d2a6ae710..187123739e 100644
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -793,6 +793,36 @@ draw_event(GtkWidget *widget UNUSED,
return FALSE;
}
+
+# if GTK_CHECK_VERSION(3,10,0)
+ static gboolean
+scale_factor_event(GtkWidget *widget,
+ GParamSpec* pspec UNUSED,
+ gpointer user_data UNUSED)
+{
+ if (gui.surface != NULL)
+ cairo_surface_destroy(gui.surface);
+
+ int w, h;
+ gtk_window_get_size(GTK_WINDOW(gui.mainwin), &w, &h);
+ gui.surface = gdk_window_create_similar_surface(
+ gtk_widget_get_window(widget),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ w, h);
+
+ int usable_height = h;
+ if (gtk_socket_id != 0)
+ usable_height -= (gui.char_height - (gui.char_height/2)); // sic.
+
+ gui_gtk_form_freeze(GTK_FORM(gui.formwin));
+ gui.force_redraw = 1;
+ gui_resize_shell(w, usable_height);
+ gui_gtk_form_thaw(GTK_FORM(gui.formwin));
+
+ return TRUE;
+}
+# endif // GTK_CHECK_VERSION(3,10,0)
+
#else // !GTK_CHECK_VERSION(3,0,0)
static gint
expose_event(GtkWidget *widget UNUSED,
@@ -1667,11 +1697,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
int
gui_mch_early_init_check(int give_message)
{
- char_u *p;
+ char_u *p, *q;
// Guess that when $DISPLAY isn't set the GUI can't start.
p = mch_getenv((char_u *)"DISPLAY");
- if (p == NULL || *p == NUL)
+ q = mch_getenv((char_u *)"WAYLAND_DISPLAY");
+ if ((p == NULL || *p == NUL) && (q == NULL || *q == NUL))
{
gui.dying = TRUE;
if (give_message)
@@ -1704,7 +1735,10 @@ gui_mch_init_check(void)
#if GTK_CHECK_VERSION(3,10,0)
// Vim currently assumes that Gtk means X11, so it cannot use native Gtk
// support for other backends such as Wayland.
- gdk_set_allowed_backends ("x11");
+ //
+ // Use an environment variable to enable unfinished Wayland support.
+ if (getenv("GVIM_ENABLE_WAYLAND") == NULL)
+ gdk_set_allowed_backends ("x11");
#endif
#ifdef FEAT_GUI_GNOME
@@ -2024,6 +2058,10 @@ scroll_event(GtkWidget *widget,
{
int button;
int_u vim_modifiers;
+#if GTK_CHECK_VERSION(3,4,0)
+ static double acc_x, acc_y;
+ static guint32 last_smooth_event_time;
+#endif
if (gtk_socket_id != 0 && !gtk_widget_has_focus(widget))
gtk_widget_grab_focus(widget);
@@ -2042,6 +2080,16 @@ scroll_event(GtkWidget *widget,
case GDK_SCROLL_RIGHT:
button = MOUSE_6;
break;
+#if GTK_CHECK_VERSION(3,4,0)
+ case GDK_SCROLL_SMOOTH:
+ if (event->time - last_smooth_event_time > 50)
+ // reset our accumulations after 50ms of silence
+ acc_x = acc_y = 0;
+ acc_x += event->delta_x;
+ acc_y += event->delta_y;
+ last_smooth_event_time = event->time;
+ break;
+#endif
default: // This shouldn't happen
return FALSE;
}
@@ -2054,8 +2102,38 @@ scroll_event(GtkWidget *widget,
vim_modifiers = modifiers_gdk2mouse(event->state);
- gui_send_mouse_event(button, (int)event->x, (int)event->y,
- FALSE, vim_modifiers);
+#if GTK_CHECK_VERSION(3,4,0)
+ if (event->direction == GDK_SCROLL_SMOOTH)
+ {
+ while (acc_x > 1.0)
+ { // right
+ acc_x = MAX(0.0, acc_x - 1.0);
+ gui_send_mouse_event(MOUSE_6, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_x < -1.0)
+ { // left
+ acc_x = MIN(0.0, acc_x + 1.0);
+ gui_send_mouse_event(MOUSE_7, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_y > 1.0)
+ { // down
+ acc_y = MAX(0.0, acc_y - 1.0);
+ gui_send_mouse_event(MOUSE_5, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ while (acc_y < -1.0)
+ { // up
+ acc_y = MIN(0.0, acc_y + 1.0);
+ gui_send_mouse_event(MOUSE_4, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
+ }
+ }
+ else
+#endif
+ gui_send_mouse_event(button, (int)event->x, (int)event->y,
+ FALSE, vim_modifiers);
return TRUE;
}
@@ -2509,10 +2587,12 @@ setup_save_yourself(void)
// Fall back to old method
// first get the existing value
- GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+ Display * dpy = gui_mch_get_display();
+ if (!dpy)
+ return;
- if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(mainwin_win),
- GDK_WINDOW_XID(mainwin_win),
+ GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+ if (XGetWMProtocols(dpy, GDK_WINDOW_XID(mainwin_win),
&existing_atoms, &count))
{
Atom *new_atoms;
@@ -2620,7 +2700,10 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
// When started with "--echo-wid" argument, write window ID on stdout.
if (echo_wid_arg)
{
- printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
+ if (gui_mch_get_display())
+ printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
+ else
+ printf("WID: 0\n");
fflush(stdout);
}
@@ -2655,27 +2738,30 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
setup_save_yourself();
#ifdef FEAT_CLIENTSERVER
- if (serverName == NULL && serverDelayedStartName != NULL)
+ if (gui_mch_get_display())
{
- // This is a :gui command in a plain vim with no previous server
- commWindow = GDK_WINDOW_XID(mainwin_win);
+ if (serverName == NULL && serverDelayedStartName != NULL)
+ {
+ // This is a :gui command in a plain vim with no previous server
+ commWindow = GDK_WINDOW_XID(mainwin_win);
- (void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
- serverDelayedStartName);
- }
- else
- {
- /*
- * Cannot handle "XLib-only" windows with gtk event routines, we'll
- * have to change the "server" registration to that of the main window
- * If we have not registered a name yet, remember the window.
- */
- serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
- GDK_WINDOW_XID(mainwin_win));
+ (void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
+ serverDelayedStartName);
+ }
+ else
+ {
+ /*
+ * Cannot handle "XLib-only" windows with gtk event routines, we'll
+ * have to change the "server" registration to that of the main window
+ * If we have not registered a name yet, remember the window.
+ */
+ serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
+ GDK_WINDOW_XID(mainwin_win));
+ }
+ gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
+ g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
+ G_CALLBACK(property_event), NULL);
}
- gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
- g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
- G_CALLBACK(property_event), NULL);
#endif
}
@@ -3919,6 +4005,9 @@ gui_mch_init(void)
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_SCROLL_MASK |
+#if GTK_CHECK_VERSION(3,4,0)
+ GDK_SMOOTH_SCROLL_MASK |
+#endif
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_POINTER_MOTION_MASK |
@@ -4520,6 +4609,10 @@ gui_mch_open(void)
#endif
g_signal_connect(G_OBJECT(gui.formwin), "configure-event",
G_CALLBACK(form_configure_event), NULL);
+#if GTK_CHECK_VERSION(3,10,0)
+ g_signal_connect(G_OBJECT(gui.formwin), "notify::scale-factor",
+ G_CALLBACK(scale_factor_event), NULL);
+#endif
#ifdef FEAT_DND
// Set up for receiving DND items.
@@ -4603,8 +4696,12 @@ gui_mch_exit(int rc UNUSED)
int
gui_mch_get_winpos(int *x, int *y)
{
- gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
- return OK;
+ if (gui_mch_get_display())
+ {
+ gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
+ return OK;
+ }
+ return FAIL;
}
/*
@@ -6229,9 +6326,10 @@ gui_mch_haskey(char_u *name)
int
gui_get_x11_windis(Window *win, Display **dis)
{
- if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+ Display * dpy = gui_mch_get_display();
+ if (dpy)
{
- *dis = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
+ *dis = dpy;
*win = GDK_WINDOW_XID(gtk_widget_get_window(gui.mainwin));
return OK;
}
@@ -6242,18 +6340,18 @@ gui_get_x11_windis(Window *win, Display **dis)
}
#endif
-#if defined(FEAT_CLIENTSERVER) \
- || (defined(FEAT_X11) && defined(FEAT_CLIPBOARD)) || defined(PROTO)
-
Display *
gui_mch_get_display(void)
{
- if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+ if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL
+#if GTK_CHECK_VERSION(3,0,0)
+ && GDK_IS_X11_DISPLAY(gtk_widget_get_display(gui.mainwin))
+#endif
+ )
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
else
return NULL;
}
-#endif
void
gui_mch_beep(void)
@@ -6915,9 +7013,10 @@ clip_mch_request_selection(Clipboard_T *cbd)
return;
}
- // Final fallback position - use the X CUT_BUFFER0 store
- yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
- cbd);
+ if (gui_mch_get_display())
+ // Final fallback position - use the X CUT_BUFFER0 store
+ yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
+ cbd);
}
/*
@@ -7083,9 +7182,11 @@ gui_mch_setmouse(int x, int y)
// Sorry for the Xlib call, but we can't avoid it, since there is no
// internal GDK mechanism present to accomplish this. (and for good
// reason...)
- XWarpPointer(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.drawarea)),
- (Window)0, GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
- 0, 0, 0U, 0U, x, y);
+ Display * dpy = gui_mch_get_display();
+ if (dpy)
+ XWarpPointer(dpy, (Window)0,
+ GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
+ 0, 0, 0U, 0U, x, y);
}
diff --git a/src/os_unix.c b/src/os_unix.c
index af8f00604c..dae5bbe827 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -2320,12 +2320,11 @@ mch_settitle(char_u *title, char_u *icon)
#ifdef FEAT_X11
if (get_x11_windis() == OK)
type = 1;
-#else
-# if defined(FEAT_GUI_PHOTON) \
+#endif
+#if defined(FEAT_GUI_PHOTON) \
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
if (gui.in_use)
type = 1;
-# endif
#endif
/*
diff --git a/src/testdir/check.vim b/src/testdir/check.vim
index 82abb64673..e67d39ad22 100644
--- a/src/testdir/check.vim
+++ b/src/testdir/check.vim
@@ -160,6 +160,14 @@ func CheckEnv(name)
endif
endfunc
+" Command to Check for pure X11 (no Wayland)
+command -nargs=0 CheckX11 call CheckX11()
+func CheckX11()
+ if !empty($WAYLAND_DISPLAY) || empty($DISPLAY)
+ throw 'Skipped: not pure X11 environment'
+ endif
+endfunc
+
" Command to check that we are using the GUI
command CheckGui call CheckGui()
func CheckGui()
diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim
index 53947f410b..8be521b9f7 100644
--- a/src/testdir/test_clientserver.vim
+++ b/src/testdir/test_clientserver.vim
@@ -13,7 +13,7 @@ source shared.vim
func Check_X11_Connection()
if has('x11')
- CheckEnv DISPLAY
+ CheckX11
try
call remote_send('xxx', '')
catch
diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim
index e13f4c3dc5..dbf1d3b310 100644
--- a/src/testdir/test_gui.vim
+++ b/src/testdir/test_gui.vim
@@ -111,6 +111,8 @@ func Test_getfontname_without_arg()
endfunc
func Test_getwinpos()
+ CheckX11
+
call assert_match('Window position: X \d\+, Y \d\+', execute('winpos'))
call assert_true(getwinposx() >= 0)
call assert_true(getwinposy() >= 0)
@@ -897,7 +899,7 @@ func Test_set_term()
endfunc
func Test_windowid_variable()
- if g:x11_based_gui || has('win32')
+ if (g:x11_based_gui && empty($WAYLAND_DISPLAY)) || has('win32')
call assert_true(v:windowid > 0)
else
call assert_equal(0, v:windowid)
diff --git a/src/testdir/test_quotestar.vim b/src/testdir/test_quotestar.vim
index 1d26942547..322ce6260b 100644
--- a/src/testdir/test_quotestar.vim
+++ b/src/testdir/test_quotestar.vim
@@ -139,8 +139,8 @@ func Test_quotestar()
if has('macunix')
let skipped = Do_test_quotestar_for_macunix()
elseif has('x11')
- if empty($DISPLAY)
- let skipped = "Test can only run when $DISPLAY is set."
+ if empty($DISPLAY) || !empty($WAYLAND_DISPLAY)
+ let skipped = "Test can only run when $DISPLAY is set and $WAYLAND_DISPLAY is not set."
else
let skipped = Do_test_quotestar_for_x11()
endif
diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim
index 7bf5a41162..7c70391604 100644
--- a/src/testdir/test_startup.vim
+++ b/src/testdir/test_startup.vim
@@ -518,9 +518,10 @@ func Test_geometry()
call writefile([&columns, &lines, getwinposx(), getwinposy(), string(getwinpos())], "Xtest_geometry")
qall
[CODE]
+ " Hide menu because gtk insists to make the window wide enough to show it completely
" Some window managers have a bar at the top that pushes windows down,
" need to use at least 130, let's do 150
- if RunVim([], after, '-f -g -geometry 31x13+41+150')
+ if RunVim(['set guioptions-=m'], after, '-f -g -geometry 31x13+41+150')
let lines = readfile('Xtest_geometry')
" Depending on the GUI library and the windowing system the final size
" might be a bit different, allow for some tolerance. Tuned based on
@@ -529,9 +530,12 @@ func Test_geometry()
" for some reason, the window may contain fewer lines than requested
" for GTK, so allow some tolerance
call assert_inrange(8, 13, str2nr(lines[1]))
- call assert_equal('41', lines[2])
- call assert_equal('150', lines[3])
- call assert_equal('[41, 150]', lines[4])
+ " on Wayland there is no way to set or retrieve window positions
+ if empty($WAYLAND_DISPLAY)
+ call assert_equal('41', lines[2])
+ call assert_equal('150', lines[3])
+ call assert_equal('[41, 150]', lines[4])
+ endif
endif
endif
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index 9af0d07090..aa819811cc 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3409,7 +3409,7 @@ def Test_remote_foreground()
CheckFeature clientserver
# remote_foreground() doesn't fail on MS-Windows
CheckNotMSWindows
- CheckEnv DISPLAY
+ CheckX11
v9.CheckDefAndScriptFailure(['remote_foreground(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'])
assert_fails('remote_foreground("NonExistingServer")', 'E241:')
diff --git a/src/version.c b/src/version.c
index 6dd48d1be8..cf123b5b2a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 64,
+/**/
63,
/**/
62,