Skip to content

Commit 6e0a18f

Browse files
lilydjwgchrisbra
authored andcommitted
patch 9.1.0064: No Wayland support
Problem: No Wayland support Solution: Add Wayland UI support (lilydjwg) closes: #9639 Signed-off-by: lilydjwg <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 94ff09a commit 6e0a18f

File tree

12 files changed

+180
-58
lines changed

12 files changed

+180
-58
lines changed

runtime/doc/builtin.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*builtin.txt* For Vim version 9.1. Last change: 2024 Jan 25
1+
*builtin.txt* For Vim version 9.1. Last change: 2024 Jan 29
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -4424,14 +4424,16 @@ getwinpos([{timeout}]) *getwinpos()*
44244424
getwinposx() The result is a Number, which is the X coordinate in pixels of
44254425
the left hand side of the GUI Vim window. Also works for an
44264426
xterm (uses a timeout of 100 msec).
4427-
The result will be -1 if the information is not available.
4427+
The result will be -1 if the information is not available
4428+
(e.g. on the Wayland backend).
44284429
The value can be used with `:winpos`.
44294430

44304431
*getwinposy()*
44314432
getwinposy() The result is a Number, which is the Y coordinate in pixels of
44324433
the top of the GUI Vim window. Also works for an xterm (uses
44334434
a timeout of 100 msec).
4434-
The result will be -1 if the information is not available.
4435+
The result will be -1 if the information is not available
4436+
(e.g. on the Wayland backend).
44354437
The value can be used with `:winpos`.
44364438

44374439
getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*

src/gui.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1589,8 +1589,11 @@ gui_resize_shell(int pixel_width, int pixel_height)
15891589
// Only comparing Rows and Columns may be sufficient, but let's stay on
15901590
// the safe side.
15911591
if (gui.num_rows != screen_Rows || gui.num_cols != screen_Columns
1592-
|| gui.num_rows != Rows || gui.num_cols != Columns)
1592+
|| gui.num_rows != Rows || gui.num_cols != Columns || gui.force_redraw)
1593+
{
15931594
shell_resized();
1595+
gui.force_redraw = 0;
1596+
}
15941597

15951598
#ifdef FEAT_GUI_HAIKU
15961599
vim_unlock_screen();

src/gui.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ typedef struct Gui
259259
int scrollbar_height; // Height of horizontal scrollbar
260260
int left_sbar_x; // Calculated x coord for left scrollbar
261261
int right_sbar_x; // Calculated x coord for right scrollbar
262+
int force_redraw; // Force a redraw even e.g. not resized
262263

263264
#ifdef FEAT_MENU
264265
# ifndef FEAT_GUI_GTK

src/gui_gtk_x11.c

Lines changed: 143 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,36 @@ draw_event(GtkWidget *widget UNUSED,
793793

794794
return FALSE;
795795
}
796+
797+
# if GTK_CHECK_VERSION(3,10,0)
798+
static gboolean
799+
scale_factor_event(GtkWidget *widget,
800+
GParamSpec* pspec UNUSED,
801+
gpointer user_data UNUSED)
802+
{
803+
if (gui.surface != NULL)
804+
cairo_surface_destroy(gui.surface);
805+
806+
int w, h;
807+
gtk_window_get_size(GTK_WINDOW(gui.mainwin), &w, &h);
808+
gui.surface = gdk_window_create_similar_surface(
809+
gtk_widget_get_window(widget),
810+
CAIRO_CONTENT_COLOR_ALPHA,
811+
w, h);
812+
813+
int usable_height = h;
814+
if (gtk_socket_id != 0)
815+
usable_height -= (gui.char_height - (gui.char_height/2)); // sic.
816+
817+
gui_gtk_form_freeze(GTK_FORM(gui.formwin));
818+
gui.force_redraw = 1;
819+
gui_resize_shell(w, usable_height);
820+
gui_gtk_form_thaw(GTK_FORM(gui.formwin));
821+
822+
return TRUE;
823+
}
824+
# endif // GTK_CHECK_VERSION(3,10,0)
825+
796826
#else // !GTK_CHECK_VERSION(3,0,0)
797827
static gint
798828
expose_event(GtkWidget *widget UNUSED,
@@ -1667,11 +1697,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
16671697
int
16681698
gui_mch_early_init_check(int give_message)
16691699
{
1670-
char_u *p;
1700+
char_u *p, *q;
16711701

16721702
// Guess that when $DISPLAY isn't set the GUI can't start.
16731703
p = mch_getenv((char_u *)"DISPLAY");
1674-
if (p == NULL || *p == NUL)
1704+
q = mch_getenv((char_u *)"WAYLAND_DISPLAY");
1705+
if ((p == NULL || *p == NUL) && (q == NULL || *q == NUL))
16751706
{
16761707
gui.dying = TRUE;
16771708
if (give_message)
@@ -1704,7 +1735,10 @@ gui_mch_init_check(void)
17041735
#if GTK_CHECK_VERSION(3,10,0)
17051736
// Vim currently assumes that Gtk means X11, so it cannot use native Gtk
17061737
// support for other backends such as Wayland.
1707-
gdk_set_allowed_backends ("x11");
1738+
//
1739+
// Use an environment variable to enable unfinished Wayland support.
1740+
if (getenv("GVIM_ENABLE_WAYLAND") == NULL)
1741+
gdk_set_allowed_backends ("x11");
17081742
#endif
17091743

17101744
#ifdef FEAT_GUI_GNOME
@@ -2024,6 +2058,10 @@ scroll_event(GtkWidget *widget,
20242058
{
20252059
int button;
20262060
int_u vim_modifiers;
2061+
#if GTK_CHECK_VERSION(3,4,0)
2062+
static double acc_x, acc_y;
2063+
static guint32 last_smooth_event_time;
2064+
#endif
20272065

20282066
if (gtk_socket_id != 0 && !gtk_widget_has_focus(widget))
20292067
gtk_widget_grab_focus(widget);
@@ -2042,6 +2080,16 @@ scroll_event(GtkWidget *widget,
20422080
case GDK_SCROLL_RIGHT:
20432081
button = MOUSE_6;
20442082
break;
2083+
#if GTK_CHECK_VERSION(3,4,0)
2084+
case GDK_SCROLL_SMOOTH:
2085+
if (event->time - last_smooth_event_time > 50)
2086+
// reset our accumulations after 50ms of silence
2087+
acc_x = acc_y = 0;
2088+
acc_x += event->delta_x;
2089+
acc_y += event->delta_y;
2090+
last_smooth_event_time = event->time;
2091+
break;
2092+
#endif
20452093
default: // This shouldn't happen
20462094
return FALSE;
20472095
}
@@ -2054,8 +2102,38 @@ scroll_event(GtkWidget *widget,
20542102

20552103
vim_modifiers = modifiers_gdk2mouse(event->state);
20562104

2057-
gui_send_mouse_event(button, (int)event->x, (int)event->y,
2058-
FALSE, vim_modifiers);
2105+
#if GTK_CHECK_VERSION(3,4,0)
2106+
if (event->direction == GDK_SCROLL_SMOOTH)
2107+
{
2108+
while (acc_x > 1.0)
2109+
{ // right
2110+
acc_x = MAX(0.0, acc_x - 1.0);
2111+
gui_send_mouse_event(MOUSE_6, (int)event->x, (int)event->y,
2112+
FALSE, vim_modifiers);
2113+
}
2114+
while (acc_x < -1.0)
2115+
{ // left
2116+
acc_x = MIN(0.0, acc_x + 1.0);
2117+
gui_send_mouse_event(MOUSE_7, (int)event->x, (int)event->y,
2118+
FALSE, vim_modifiers);
2119+
}
2120+
while (acc_y > 1.0)
2121+
{ // down
2122+
acc_y = MAX(0.0, acc_y - 1.0);
2123+
gui_send_mouse_event(MOUSE_5, (int)event->x, (int)event->y,
2124+
FALSE, vim_modifiers);
2125+
}
2126+
while (acc_y < -1.0)
2127+
{ // up
2128+
acc_y = MIN(0.0, acc_y + 1.0);
2129+
gui_send_mouse_event(MOUSE_4, (int)event->x, (int)event->y,
2130+
FALSE, vim_modifiers);
2131+
}
2132+
}
2133+
else
2134+
#endif
2135+
gui_send_mouse_event(button, (int)event->x, (int)event->y,
2136+
FALSE, vim_modifiers);
20592137

20602138
return TRUE;
20612139
}
@@ -2509,10 +2587,12 @@ setup_save_yourself(void)
25092587
// Fall back to old method
25102588

25112589
// first get the existing value
2512-
GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
2590+
Display * dpy = gui_mch_get_display();
2591+
if (!dpy)
2592+
return;
25132593

2514-
if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(mainwin_win),
2515-
GDK_WINDOW_XID(mainwin_win),
2594+
GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
2595+
if (XGetWMProtocols(dpy, GDK_WINDOW_XID(mainwin_win),
25162596
&existing_atoms, &count))
25172597
{
25182598
Atom *new_atoms;
@@ -2620,7 +2700,10 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
26202700
// When started with "--echo-wid" argument, write window ID on stdout.
26212701
if (echo_wid_arg)
26222702
{
2623-
printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
2703+
if (gui_mch_get_display())
2704+
printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
2705+
else
2706+
printf("WID: 0\n");
26242707
fflush(stdout);
26252708
}
26262709

@@ -2655,27 +2738,30 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
26552738
setup_save_yourself();
26562739

26572740
#ifdef FEAT_CLIENTSERVER
2658-
if (serverName == NULL && serverDelayedStartName != NULL)
2741+
if (gui_mch_get_display())
26592742
{
2660-
// This is a :gui command in a plain vim with no previous server
2661-
commWindow = GDK_WINDOW_XID(mainwin_win);
2743+
if (serverName == NULL && serverDelayedStartName != NULL)
2744+
{
2745+
// This is a :gui command in a plain vim with no previous server
2746+
commWindow = GDK_WINDOW_XID(mainwin_win);
26622747

2663-
(void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
2664-
serverDelayedStartName);
2665-
}
2666-
else
2667-
{
2668-
/*
2669-
* Cannot handle "XLib-only" windows with gtk event routines, we'll
2670-
* have to change the "server" registration to that of the main window
2671-
* If we have not registered a name yet, remember the window.
2672-
*/
2673-
serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
2674-
GDK_WINDOW_XID(mainwin_win));
2748+
(void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
2749+
serverDelayedStartName);
2750+
}
2751+
else
2752+
{
2753+
/*
2754+
* Cannot handle "XLib-only" windows with gtk event routines, we'll
2755+
* have to change the "server" registration to that of the main window
2756+
* If we have not registered a name yet, remember the window.
2757+
*/
2758+
serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
2759+
GDK_WINDOW_XID(mainwin_win));
2760+
}
2761+
gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
2762+
g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
2763+
G_CALLBACK(property_event), NULL);
26752764
}
2676-
gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
2677-
g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
2678-
G_CALLBACK(property_event), NULL);
26792765
#endif
26802766
}
26812767

@@ -3919,6 +4005,9 @@ gui_mch_init(void)
39194005
GDK_BUTTON_PRESS_MASK |
39204006
GDK_BUTTON_RELEASE_MASK |
39214007
GDK_SCROLL_MASK |
4008+
#if GTK_CHECK_VERSION(3,4,0)
4009+
GDK_SMOOTH_SCROLL_MASK |
4010+
#endif
39224011
GDK_KEY_PRESS_MASK |
39234012
GDK_KEY_RELEASE_MASK |
39244013
GDK_POINTER_MOTION_MASK |
@@ -4520,6 +4609,10 @@ gui_mch_open(void)
45204609
#endif
45214610
g_signal_connect(G_OBJECT(gui.formwin), "configure-event",
45224611
G_CALLBACK(form_configure_event), NULL);
4612+
#if GTK_CHECK_VERSION(3,10,0)
4613+
g_signal_connect(G_OBJECT(gui.formwin), "notify::scale-factor",
4614+
G_CALLBACK(scale_factor_event), NULL);
4615+
#endif
45234616

45244617
#ifdef FEAT_DND
45254618
// Set up for receiving DND items.
@@ -4603,8 +4696,12 @@ gui_mch_exit(int rc UNUSED)
46034696
int
46044697
gui_mch_get_winpos(int *x, int *y)
46054698
{
4606-
gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
4607-
return OK;
4699+
if (gui_mch_get_display())
4700+
{
4701+
gtk_window_get_position(GTK_WINDOW(gui.mainwin), x, y);
4702+
return OK;
4703+
}
4704+
return FAIL;
46084705
}
46094706

46104707
/*
@@ -6229,9 +6326,10 @@ gui_mch_haskey(char_u *name)
62296326
int
62306327
gui_get_x11_windis(Window *win, Display **dis)
62316328
{
6232-
if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
6329+
Display * dpy = gui_mch_get_display();
6330+
if (dpy)
62336331
{
6234-
*dis = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
6332+
*dis = dpy;
62356333
*win = GDK_WINDOW_XID(gtk_widget_get_window(gui.mainwin));
62366334
return OK;
62376335
}
@@ -6242,18 +6340,18 @@ gui_get_x11_windis(Window *win, Display **dis)
62426340
}
62436341
#endif
62446342

6245-
#if defined(FEAT_CLIENTSERVER) \
6246-
|| (defined(FEAT_X11) && defined(FEAT_CLIPBOARD)) || defined(PROTO)
6247-
62486343
Display *
62496344
gui_mch_get_display(void)
62506345
{
6251-
if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
6346+
if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL
6347+
#if GTK_CHECK_VERSION(3,0,0)
6348+
&& GDK_IS_X11_DISPLAY(gtk_widget_get_display(gui.mainwin))
6349+
#endif
6350+
)
62526351
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
62536352
else
62546353
return NULL;
62556354
}
6256-
#endif
62576355

62586356
void
62596357
gui_mch_beep(void)
@@ -6915,9 +7013,10 @@ clip_mch_request_selection(Clipboard_T *cbd)
69157013
return;
69167014
}
69177015

6918-
// Final fallback position - use the X CUT_BUFFER0 store
6919-
yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
6920-
cbd);
7016+
if (gui_mch_get_display())
7017+
// Final fallback position - use the X CUT_BUFFER0 store
7018+
yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
7019+
cbd);
69217020
}
69227021

69237022
/*
@@ -7083,9 +7182,11 @@ gui_mch_setmouse(int x, int y)
70837182
// Sorry for the Xlib call, but we can't avoid it, since there is no
70847183
// internal GDK mechanism present to accomplish this. (and for good
70857184
// reason...)
7086-
XWarpPointer(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.drawarea)),
7087-
(Window)0, GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
7088-
0, 0, 0U, 0U, x, y);
7185+
Display * dpy = gui_mch_get_display();
7186+
if (dpy)
7187+
XWarpPointer(dpy, (Window)0,
7188+
GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
7189+
0, 0, 0U, 0U, x, y);
70897190
}
70907191

70917192

src/os_unix.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2320,12 +2320,11 @@ mch_settitle(char_u *title, char_u *icon)
23202320
#ifdef FEAT_X11
23212321
if (get_x11_windis() == OK)
23222322
type = 1;
2323-
#else
2324-
# if defined(FEAT_GUI_PHOTON) \
2323+
#endif
2324+
#if defined(FEAT_GUI_PHOTON) \
23252325
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU)
23262326
if (gui.in_use)
23272327
type = 1;
2328-
# endif
23292328
#endif
23302329

23312330
/*

src/testdir/check.vim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ func CheckEnv(name)
160160
endif
161161
endfunc
162162

163+
" Command to Check for pure X11 (no Wayland)
164+
command -nargs=0 CheckX11 call CheckX11()
165+
func CheckX11()
166+
if !empty($WAYLAND_DISPLAY) || empty($DISPLAY)
167+
throw 'Skipped: not pure X11 environment'
168+
endif
169+
endfunc
170+
163171
" Command to check that we are using the GUI
164172
command CheckGui call CheckGui()
165173
func CheckGui()

src/testdir/test_clientserver.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ source shared.vim
1313

1414
func Check_X11_Connection()
1515
if has('x11')
16-
CheckEnv DISPLAY
16+
CheckX11
1717
try
1818
call remote_send('xxx', '')
1919
catch

0 commit comments

Comments
 (0)