Conversation
2a841df to
565b319
Compare
|
I think the GTK4 port of GVim should focus more on Wayland instead of X11, which is already deprecated and will be removed in GTK5. I suppose there are issues with keyboard layout detection, but there a much more users that have it working fine. Having a 2800 line file called "gui_gtk4_x11.c" does not feel right... |
|
Currently the only X11 dependency in the GTK4 backend is |
|
This also means we could rename |
3c84d69 to
cb39dfa
Compare
|
The GTK4 port now has zero direct X11 dependency 💪 The X11 libraries shown by |
|
I am getting build errors when trying to compile this PR. It seems that multiple functions in gui_gtk4.c are not exposed in the .pro file |
|
Sorry, the proto file was broken when gui_gtk4_x11.c was merged into gui_gtk4.c. It should be fixed now. |
|
Here are some compilation errors I am getting on Linux: |
|
I build w/ gtk4 overtime, but may it makes no sense until this gets merge. Thx for your work @mattn |
|
Thank @mattn this looks very interesting! :) (GNU/Linux dwm x11) This is a screenshot with the black version menu with set guioptions+=d if somebody want to see it.
I understand that this still in beta phase, For now I was able to build it without problems, but I can only start it using gvim --nofork (without --nofork, does not start). Thanks again and good job! |
|
Since I'm developing this on WSL2, I haven't been able to test the Broadway backend yet. If you have a native Linux environment, you should be able to run gvim in a browser:
You should see gvim running inside the browser. I'd appreciate it if someone could give it a try! |
|
Hello, Thanks for the information about broadway, I will take a look when possible. I still can't really test it properly, but following the recent GTK4 updates, the --nofork issue is now resolved and it's not needed anymore, starts well by default without problems. Small things that I quickly detect when I used it: 1. Empty WM_CLASS (X11) When running in an X11 environment, the WM_CLASS attribute is empty. This prevents window managers (I use dwm) from correctly identifying the application, applying window rules etc.. 2. Crash when setting guioptions=k Setting the k flag (Keep window size) in guioptions causes an immediate crash. 3. Ligatures are not rendering (works with gtk2, gktk3) Even with a supported font and the guiligatures option set, symbols are not displayed as expected. 4. X11 Feature missing in :version (maybe it's correct) The :version output shows -X11. While this is a GTK4 build, it is unclear if certain X11-specific integrations (like clipboard) are intentionally disabled or if this is an expecting setting in the build as you said before (no X11 deps). Thank you, this looks promising! |
|
@gonzaru Thank you for the detailed report! The three issues you reported have been fixed:
Regarding |
I can confirm that 2. and 3 are resolved. The crash is fixed and the ligatures work! About 1. the WM_CLASS now reports: WM_CLASS(STRING) = "gvim", "gvim" Needs to be: WM_CLASS(STRING) = "gvim", "Gvim" This is how gtk2 and gkt3 also report it, as the class name (the second field) the standard is to capitalize it. The spec states that WM_CLASS must contain two consecutive null-terminated strings: (4.1.2.5. WM_CLASS Property) I will try to check more things this weekend and report it if necessary. Regards |
Fix ASCII text not visible: - Add missing cairo_set_source_rgba and pango_cairo_show_glyph_string calls in the ASCII fast path of gui_gtk_draw_string. Fix CJK/wide character rendering: - Process each PangoItem separately in gui_gtk_draw_string to use the correct font for each script segment (fixes tofu for Japanese). - Calculate glyph width based on utf_ptr2cells() so fullwidth characters get char_width * 2. Fix hollow cursor on startup: - Call gui_focus_change(TRUE) in gui_mch_open to ensure Vim knows the window has focus, so a solid block cursor is drawn instead of a hollow one. Co-authored-by: Claude <noreply@anthropic.com>
Regenerate proto/gui_gtk4.pro after gui_gtk4_x11.c was merged into gui_gtk4.c. Also add gui_gtk4.pro to ALL_GUI_PRO and the dependency rules in the Makefile so `make proto` picks it up.
The GTK_MENU_SHELL() stub was defined with no parameters, but callers in getchar.c pass a widget pointer (matching the original GTK macro signature). This caused a compilation error.
gui_get_x11_windis() was declared as void but gui.c expects an int return value (compared against OK). Return FAIL since X11 window/ display are not applicable in GTK4.
GTK4 does not have GtkMenuShell. Instead of providing stub functions for GTK_MENU_SHELL() and gtk_menu_shell_select_first(), guard the F10 menu activation code in getchar.c with !defined(USE_GTK4) and remove the stubs from gui_gtk4.c.
gtk_widget_show() is deprecated in GTK4. Use gtk_widget_set_visible() with TRUE instead.
- Replace gtk_widget_show/hide() with gtk_widget_set_visible() - Replace gtk_style_context_add_provider() with gtk_style_context_add_provider_for_display() - Guard gtk_widget_get_style_context() with #ifndef USE_GTK4
GTK4 does not ship gdkkeysyms-compat.h, so legacy symbols like GDK_Shift_L and GDK_MOD1_MASK are not available. Use GDK_KEY_Shift_L and GDK_ALT_MASK under USE_GTK4.
GTK4's GtkIMContext does not support synthesizing key events for IM activation, so 'imactivatekey' cannot work. Return FALSE for non-empty values so that invalid settings are rejected instead of silently ignored.
Calling gtk_init() before fork() breaks the display connection in the child process, making gvim fail to start without --nofork. Move the call to gui_mch_init_check() which is called after fork(), matching the GTK3 pattern of deferring gtk_init_check() until after fork.
gui_mch_newfont() was calling gui_set_shellsize() which called gui_mch_newfont() back, causing infinite recursion and a crash. Use gui_resize_shell() instead to recalculate Rows/Columns from the current window size without re-entering gui_set_shellsize(). Also add a FIXME comment to gui.c where gui_mch_newfont() is called even when the font hasn't changed (e.g. just setting guioptions=k).
Without this, WM_CLASS is empty on X11, which prevents window managers like dwm from identifying gvim windows for placement rules.
Port the ligature rendering logic from gui_gtk_x11.c (GTK3) to GTK4. Previously ligature characters were rendered individually through the fast ASCII glyph cache path, ignoring the ligatures_map entirely. Split gui_gtk_draw_string into a wrapper that segments the string into ASCII and ligature/UTF-8 parts, and gui_gtk_draw_string_ext that does the actual drawing with proper Pango shaping via pango_shape_full(). Also port helper functions for cluster-based glyph width calculation, combining character handling, and guifontwide support.
Two issues prevented mouse events from reaching Vim: 1. gui.formwin (GtkForm overlay for scrollbars) was layered on top of gui.drawarea via GtkOverlay, intercepting all mouse events. Fix: set can_target=FALSE on formwin so events pass through. 2. Drag detection used `if (mouse_pressed_button)` but MOUSE_LEFT is 0x00, so left-button drags were never detected. Fix: use -1 as "no button pressed" sentinel and check >= 0.
gui_mch_flush() only called gdk_display_flush() which flushes the display buffer but does not notify GTK that the offscreen surface content has changed. Add gtk_widget_queue_draw() so the draw_event callback is triggered to paint the updated surface to the widget.
When focus moved to another widget (e.g. menubar, toolbar), the drawing area did not regain focus on mouse re-enter, leaving the cursor in its unfocused (hollow) shape. Add gtk_widget_grab_focus() in enter_notify_event, matching the GTK3 behavior.
When the drawing area was resized (e.g. after :vsp), the old surface content was copied to the new surface. If Vim's redraw didn't cover all areas, stale content like the intro screen text remained as ghost artifacts. Fix by filling the new surface with the background color instead of copying old content, since gui_resize_shell() triggers a full redraw anyway. Also remove duplicate surface resizing logic from draw_event, centralizing it in drawarea_resize_cb.
WM_CLASS is an X11 property that GTK4 no longer sets directly. The correct way to associate windows with the application in GTK4 is through the StartupWMClass field in the desktop entry file.
When 'guioptions' includes "c" and 'confirm' is set, :q on a modified buffer sets exiting=TRUE before calling do_dialog(). The GTK4-specific check for "exiting" in gui_mch_wait_for_chars() caused it to bail out immediately without waiting for key input, resulting in an infinite loop. Remove the "exiting" check to match the GTK3 implementation.
The button label strings parsed from the "&Yes\n&No\n&Cancel" format were stored as pointers into a buffer that was freed before gtk_alert_dialog_set_buttons() copied them. Defer vim_free(buf) and CONVERT_TO_UTF8_FREE() until after the dialog is done.
Implement gui_mch_menu_grey() for GTK4 using g_simple_action_set_enabled() to grey out disabled menu items (e.g. Copy/Paste when unavailable). Store the GAction name in menu->label for later lookup. Also fix the popover menu not closing after selecting an item. GTK4's GtkPopoverMenuBar marks popovers as not-visible but Vim's custom main loop does not process the rendering update. Use gtk_widget_unrealize() to force the popover surface to close.
GTK4 does not provide a window position API (removed by design for Wayland compatibility). Return FAIL instead of reporting 0,0 which is misleading.
List monospace font families from Pango context for :set guifont=<TAB> completion, matching the GTK3 implementation.
Use GtkPrintOperation with Pango/Cairo rendering instead of PostScript + lpr. Guarded by FEAT_GUI_GTK_PRINT ifdef.









Add GTK4 GUI backend using separate source files instead of adding conditional branches to the existing GTK2/GTK3 code. GTK4's API changes are too fundamental for
#ifbranching to be maintainable.This PR was developed with the assistance of Claude Code (Anthropic).
Build
Requires GTK 4.10+ (for
GtkFontDialog,GtkFileDialog,GtkAlertDialog).New files
gui_gtk4.c— Main GUI implementation (window, events, drawing, fonts, colors, menus, scrollbars, dialogs, toolbar)gui_gtk4_f.c/h— GtkForm widget (extends GtkWidget, uses GskTransform)No direct X11 dependency
The GTK4 backend does not use any X11 API directly. All X11 libraries shown by
lddare indirect dependencies from libgtk-4.so.Features
:set guifont=*) via GtkFontDialog:browse) via GtkFileDialogconfirm()) via GtkAlertDialog:promptfind/:promptrepl)has("gui_gtk4")feature flag:q!exitKnown limitations
GSK_RENDERER=cairobecause GL/Vulkan renderers may not be available in all environments. Can be overridden via environment variable.EGL_LOG_LEVEL=fatal) when GL is unavailable.This is a work in progress.