From 630f13db785ce40ac1eef9bb89f635667d863a4a Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 17 Aug 2023 12:13:47 +0200 Subject: [PATCH] x11: Handle ConfigureRequest events in frames Under strange timings, the GTK frames client may implicitly queue relayouts that end up disagreeing with the latest frame size as given by Mutter, this results in GTK calling XResizeWindow, and Mutter plain out ignoring the resulting XConfigureRequestEvent received. This however makes GTK think there's pending resize operations, so at the next resize it will freeze the window, until enough resizes happened to thaw it again. This is seen as temporary loss of frame-sync ness (e.g. frozen frame, and other weird behavior). In order to make GTK happy and balanced, reply to this XConfigureRequest, even if just to ignore it in a more polite way (we simply re-apply the size Mutter thinks the frame should have, not GTK), this results in the right amount of ConfigureNotify received on the frames client side, and the surface to be thawed more timely, while enforcing the size as managed by Mutter. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2837 Part-of: --- src/core/frame.c | 34 ++++++++++++++++++++++++++++++++++ src/x11/events.c | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/src/core/frame.c b/src/core/frame.c index 694a870d3..3d6e7ab78 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -440,6 +440,34 @@ meta_frame_get_xwindow (MetaFrame *frame) return frame->xwindow; } +static void +send_configure_notify (MetaFrame *frame) +{ + MetaX11Display *x11_display = frame->window->display->x11_display; + XEvent event = { 0 }; + + /* We never get told by the frames client, just reassert the + * current frame size. + */ + event.type = ConfigureNotify; + event.xconfigure.display = x11_display->xdisplay; + event.xconfigure.event = frame->xwindow; + event.xconfigure.window = frame->xwindow; + event.xconfigure.x = frame->rect.x; + event.xconfigure.y = frame->rect.y; + event.xconfigure.width = frame->rect.width; + event.xconfigure.height = frame->rect.height; + event.xconfigure.border_width = 0; + event.xconfigure.above = None; + event.xconfigure.override_redirect = False; + + meta_x11_error_trap_push (x11_display); + XSendEvent (x11_display->xdisplay, + frame->xwindow, + False, StructureNotifyMask, &event); + meta_x11_error_trap_pop (x11_display); +} + gboolean meta_frame_handle_xevent (MetaFrame *frame, XEvent *xevent) @@ -465,6 +493,12 @@ meta_frame_handle_xevent (MetaFrame *frame, xevent->xproperty.atom, FALSE); return TRUE; } + else if (xevent->xany.type == ConfigureRequest && + xevent->xconfigurerequest.window == frame->xwindow) + { + send_configure_notify (frame); + return TRUE; + } return FALSE; } diff --git a/src/x11/events.c b/src/x11/events.c index d65ea08a6..5e749deed 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -1601,6 +1601,10 @@ handle_other_xevent (MetaX11Display *x11_display, { meta_window_x11_configure_request (window, event); } + else if (frame_was_receiver && window->frame) + { + meta_frame_handle_xevent (window->frame, event); + } break; case GravityNotify: break;