xwayland: Send synthetic ConfigureNotify per ICCCM 4.1.5

X11 clients expect a ConfigureNotify after a ConfigureRequest. If
the compositor/window manager chooses not to honor the request
(e.g. due to the window being maximized), XWayland will not send a
"real" ConfigureNotify event and the window manager is expected to
send a synthetic event instead. Otherwise, the X11 client is left
waiting and may not repaint its window properly.

For comparison, see Openbox's client_configure() or Weston's
weston_wm_window_send_configure_notify().

v2: Move logic to wlr_xwayland_surface_configure()
This commit is contained in:
John Lindgren 2023-02-17 08:25:39 -05:00 committed by Isaac Freund
parent 3ef9f91283
commit 7d90cd055d
1 changed files with 25 additions and 0 deletions

View File

@ -1760,6 +1760,9 @@ void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *xsurface,
void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
int16_t x, int16_t y, uint16_t width, uint16_t height) {
int old_w = xsurface->width;
int old_h = xsurface->height;
xsurface->x = x;
xsurface->y = y;
xsurface->width = width;
@ -1771,6 +1774,28 @@ void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *xsurface,
XCB_CONFIG_WINDOW_BORDER_WIDTH;
uint32_t values[] = {x, y, width, height, 0};
xcb_configure_window(xwm->xcb_conn, xsurface->window_id, mask, values);
// If the window size did not change, then we cannot rely on
// the X server to generate a ConfigureNotify event. Instead,
// we are supposed to send a synthetic event. See ICCCM part
// 4.1.5. But we ignore override-redirect windows as ICCCM does
// not apply to them.
if (width == old_w && height == old_h && !xsurface->override_redirect) {
xcb_configure_notify_event_t configure_notify = {
.response_type = XCB_CONFIGURE_NOTIFY,
.event = xsurface->window_id,
.window = xsurface->window_id,
.x = x,
.y = y,
.width = width,
.height = height,
};
xcb_send_event(xwm->xcb_conn, 0, xsurface->window_id,
XCB_EVENT_MASK_STRUCTURE_NOTIFY,
(const char *)&configure_notify);
}
xcb_flush(xwm->xcb_conn);
}