From 395b52cf9f55e075581a14f5cbe3e3379da1843e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=8A?= =?UTF-8?q?=D1=80=20=D0=9A=D1=83=D1=80=D1=82=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Wed, 7 Oct 2026 11:34:28 +0300 Subject: [PATCH] [GTK4] Draw plain Composite backgrounds as color nodes Redrawing a control runs the snapshot of all its ancestors again, and Composite.snapshotBackground() appended a new Cairo node of its full size for each of them, the Shell included. Cairo nodes are not diffed, so every redraw damaged the whole window, and the renderer rasterized and uploaded all of it again. This made scrolling in StyledText slow. Append a color node for a background color, which is diffed by value. Background images still use Cairo. See https://github.com/eclipse-platform/eclipse.platform.swt/issues/3583 Assisted-by: Anthropic Claude Code (claude-opus-5-5) --- .../org/eclipse/swt/widgets/Composite.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java index 16dd1e00540..54938584846 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java @@ -540,9 +540,9 @@ void snapshotBackground (long handle, long snapshot) { /* * Draw the effective background before children are snapshotted. * - * SWTFixed widget has no CSS background rule, thus obtain a Cairo - * context from the snapshot and delegate to drawBackground(), which - * paints the background image or color directly via Cairo. + * SWTFixed widget has no CSS background rule, thus append a color node + * for a background color, or obtain a Cairo context from the snapshot + * and delegate to drawBackground() for a background image. * * Skip when an explicit background color has been set (state & BACKGROUND): * GTK4 renders the CSS provider background automatically before calling @@ -562,10 +562,23 @@ void snapshotBackground (long handle, long snapshot) { int height = (state & ZERO_HEIGHT) != 0 ? 0 : allocation.height; long rect = Graphene.graphene_rect_alloc(); Graphene.graphene_rect_init(rect, 0, 0, width, height); - long cairo = GTK4.gtk_snapshot_append_cairo(snapshot, rect); - if (cairo != 0) { - drawBackground(control, 0, cairo, 0, 0, width, height); - Cairo.cairo_destroy(cairo); + if (control.backgroundImage == null) { + /* + * The snapshot of every ancestor runs again when a child is redrawn. A Cairo + * node cannot be diffed, so a new one damages its whole area and makes the + * renderer rasterize and upload it again in every frame. A color node is + * diffed by value, so an unchanged background damages nothing. + */ + boolean noBackgroundRegion = drawRegion && hooks(SWT.Paint) && cachedNoBackground; + if (!noBackgroundRegion) { + GTK4.gtk_snapshot_append_color(snapshot, control.getBackgroundGdkRGBA(), rect); + } + } else { + long cairo = GTK4.gtk_snapshot_append_cairo(snapshot, rect); + if (cairo != 0) { + drawBackground(control, 0, cairo, 0, 0, width, height); + Cairo.cairo_destroy(cairo); + } } Graphene.graphene_rect_free(rect); }