From: Christoffer Aasted Date: Sun, 2 Aug 2026 18:01:14 +0000 (+0000) Subject: patch 9.2.0897: GTK3 X11 redraws are not coalesced X-Git-Tag: v9.2.0897^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cd29d79dde5a076a859009b97287e6357933efe3;p=thirdparty%2Fvim.git patch 9.2.0897: GTK3 X11 redraws are not coalesced Problem: GTK3 X11 redraws are not coalesced Solution: Improve redrawing logic, unify Wayland with X11 redraw code (Christoffer Aasted) closes: #20909 Signed-off-by: Christoffer Aasted Signed-off-by: Christian Brabandt --- diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 0647d9b16b..f2db6d1da8 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -778,25 +778,7 @@ draw_event(GtkWidget *widget UNUSED, // for GTK+ 3, may induce other draw events. cairo_set_source_surface(cr, gui.surface, 0, 0); - - { - cairo_rectangle_list_t *list = NULL; - - list = cairo_copy_clip_rectangle_list(cr); - if (list->status != CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) - { - int i; - - for (i = 0; i < list->num_rectangles; i++) - { - const cairo_rectangle_t *rect = &list->rectangles[i]; - cairo_rectangle(cr, rect->x, rect->y, - rect->width, rect->height); - cairo_fill(cr); - } - } - cairo_rectangle_list_destroy(list); - } + cairo_paint(cr); return FALSE; } @@ -3758,54 +3740,6 @@ gui_gtk_set_dnd_targets(void) GDK_ACTION_COPY | GDK_ACTION_MOVE); } -#ifdef GDK_WINDOWING_WAYLAND -static struct { - int left; - int top; - int right; - int bottom; - bool active; -} wl_dirty_rect = {0, 0, 0, 0, false}; - - static void -wl_queue_dirty_area(int x, int y, int width, int height) -{ - if (!wl_dirty_rect.active) - { - wl_dirty_rect.left = x; - wl_dirty_rect.top = y; - wl_dirty_rect.right = x + width; - wl_dirty_rect.bottom = y + height; - wl_dirty_rect.active = true; - } - else - { - // Expand to append further changes - if (x < wl_dirty_rect.left) wl_dirty_rect.left = x; - if (y < wl_dirty_rect.top) wl_dirty_rect.top = y; - if (x + width > wl_dirty_rect.right) wl_dirty_rect.right = x + width; - if (y + height > wl_dirty_rect.bottom) wl_dirty_rect.bottom = y + height; - } -} - - static void -wl_flush(void) -{ - if (!wl_dirty_rect.active) - return; - int draw_x = wl_dirty_rect.left; - int draw_y = wl_dirty_rect.top; - int draw_w = wl_dirty_rect.right - wl_dirty_rect.left; - int draw_h = wl_dirty_rect.bottom - wl_dirty_rect.top; - - if (draw_w > 0 && draw_h > 0) - { - gtk_widget_queue_draw_area(gui.drawarea, draw_x, draw_y, draw_w, draw_h); - } - wl_dirty_rect.active = false; -} -#endif - /* * Initialize the GUI. Create all the windows, set up all the callbacks etc. * Returns OK for success, FAIL when the GUI can't be started. @@ -6287,20 +6221,28 @@ gui_gtk_draw_string(int row, int col, char_u *s, int len, int flags) return len_sum; } +#if GTK_CHECK_VERSION(3,0,0) +static cairo_region_t *dirty_region = NULL; + static void -queue_draw_area( - int x, - int y, - int width, - int height) +queue_draw_area(int x, int y, int width, int height) { -#ifdef GDK_WINDOWING_WAYLAND - if (gui.is_wayland) - wl_queue_dirty_area(x, y, width, height); + cairo_rectangle_int_t rect; + + if (width <= 0 || height <= 0 || gui.drawarea == NULL) + return; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + if (dirty_region == NULL) + dirty_region = cairo_region_create_rectangle(&rect); else -#endif - gtk_widget_queue_draw_area(gui.drawarea, x, y, width, height); + cairo_region_union_rectangle(dirty_region, &rect); } +#endif int gui_gtk_draw_string_ext( @@ -6554,8 +6496,8 @@ skipitall: #if GTK_CHECK_VERSION(3,0,0) cairo_destroy(cr); - queue_draw_area(area.x, area.y, - area.width, area.height); + queue_draw_area(FILL_X(col), FILL_Y(row), + column_offset * gui.char_width + 1, gui.char_height); #else gdk_gc_set_clip_rectangle(gui.text_gc, NULL); #endif @@ -6698,8 +6640,7 @@ gui_mch_invert_rectangle(int r, int c, int nr, int nc) cairo_destroy(cr); - queue_draw_area(rect.x, rect.y, - rect.width, rect.height); + queue_draw_area(rect.x, rect.y, rect.width, rect.height); #else GdkGCValues values; GdkGC *invert_gc; @@ -6852,17 +6793,14 @@ gui_mch_update(void) { int cnt = 0; // prevent endless loop while (g_main_context_pending(NULL) && !vim_is_input_buf_full() - && ++cnt < 100) + && ++cnt < 100) { -#ifdef GDK_WINDOWING_WAYLAND - if (gui.is_wayland) - { - int prio = 0; - g_main_context_prepare(NULL, &prio); - // peek internal scheduling of redraw - if (prio == GDK_PRIORITY_REDRAW) - gui_may_flush(); // prepares redraw: g_main_context_iteration - } +#if GTK_CHECK_VERSION(3,0,0) + int prio = 0; + g_main_context_prepare(NULL, &prio); + // peek internal scheduling of redraw + if (prio == GDK_PRIORITY_REDRAW) + gui_may_flush(); // prepares redraw: g_main_context_iteration #endif g_main_context_iteration(NULL, TRUE); } @@ -6997,18 +6935,19 @@ theend: void gui_mch_flush(void) { - if (gui.mainwin != NULL && gtk_widget_get_realized(gui.mainwin)) + if (gui.mainwin == NULL || !gtk_widget_get_realized(gui.mainwin)) + return; +#if GTK_CHECK_VERSION(3,0,0) + if (dirty_region != NULL && gui.drawarea != NULL) { -#ifdef GDK_WINDOWING_WAYLAND - if (gui.is_wayland) - return wl_flush(); -#endif -#if GTK_CHECK_VERSION(2,4,0) - gdk_display_flush(gtk_widget_get_display(gui.mainwin)); + gtk_widget_queue_draw_region(gui.drawarea, dirty_region); + cairo_region_destroy(dirty_region); + dirty_region = NULL; + } #else - gdk_display_sync(gtk_widget_get_display(gui.mainwin)); + gdk_display_flush(gtk_widget_get_display(gui.mainwin)); + return; #endif - } } /* @@ -7060,8 +6999,7 @@ gui_mch_clear_block(int row1arg, int col1arg, int row2arg, int col2arg) cairo_fill(cr); cairo_destroy(cr); - queue_draw_area( - rect.x, rect.y, rect.width, rect.height); + queue_draw_area(rect.x, rect.y, rect.width, rect.height); } #else // !GTK_CHECK_VERSION(3,0,0) gdk_gc_set_foreground(gui.text_gc, &color); @@ -7097,8 +7035,7 @@ gui_gtk_window_clear(GdkWindow *win) cairo_fill(cr); cairo_destroy(cr); - queue_draw_area( - rect.x, rect.y, rect.width, rect.height); + queue_draw_area(rect.x, rect.y, rect.width, rect.height); } #else # define gui_gtk_window_clear(win) gdk_window_clear(win) @@ -7156,8 +7093,7 @@ gui_mch_draw_popup_image( # if GTK_CHECK_VERSION(3,0,0) cairo_popup_image_paint(wp, gui.surface, x, y, src_x, src_y, draw_w, draw_h); - if (gui.drawarea != NULL) - queue_draw_area(x, y, draw_w, draw_h); + queue_draw_area(x, y, draw_w, draw_h); # else cairo_popup_image_paint(wp, gui.drawarea->window, x, y, src_x, src_y, draw_w, draw_h); diff --git a/src/version.c b/src/version.c index 30b9a310be..7c831d2ae2 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 */ +/**/ + 897, /**/ 896, /**/