From 2d66d01cf58b0b079dc70f28e144aac020710d35 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Mon, 27 Feb 2023 22:30:24 -0300 Subject: [PATCH] xwayland: Handle shell hint for client to choose dimensions A config event with width == 0 or height == 0 from the shell is a hint to the client to choose its own dimensions. Since X11 clients don't support such hints we make a best guess by trying to use the last saved dimensions or, as a fallback, the current dimensions. This hint is mainly used by libweston/desktop shells when transitioning to a normal state from maximized, fullscreen or after a resize [1]. Without support for this hint the aforementioned transition causes xwayland surfaces to be configured to a 1x1 size. To be able to use the last saved dimensions with xwayland surface, the shell needs to first set the maximized/fullscreen state and only then set the new size, which is currently the case for desktop-shell. Otherwise, if the new size is set first, then the last saved dimensions will be set to the fullscreen/maximized values and won't be useful when restoring to a normal window size. [1] Recently we've introduced ba82af938a87ff088b4aacff3b8ac1b6bb461be2 "desktop-shell: do not forget to reset pending config size after resizes". As we were not handling the 0x0 size hint, resizing X applications started to fail. This patch fixes that. Signed-off-by: Alexandros Frantzis Signed-off-by: Leandro Ribeiro Co-authored-by: Leandro Ribeiro (cherry picked from commit 2acd2c74891cd0548c1ff410ccfe81952bed27b3) --- xwayland/window-manager.c | 46 +++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index 9dc30e1c..71c63caf 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -2795,6 +2795,8 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height) struct theme *t; int new_width, new_height; int vborder, hborder; + bool use_saved_dimensions = false; + bool use_current_dimensions = false; if (!window || !window->wm) return; @@ -2809,20 +2811,46 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height) vborder = 0; } - if (width > hborder) - new_width = width - hborder; - else - new_width = 1; - - if (height > vborder) - new_height = height - vborder; - else - new_height = 1; + /* A config event with width == 0 or height == 0 is a hint to the client + * to choose its own dimensions. Since X11 clients don't support such + * hints we make a best guess here by trying to use the last saved + * dimensions or, as a fallback, the current dimensions. */ + if (width == 0 || height == 0) { + use_saved_dimensions = window->saved_width > 0 && + window->saved_height > 0; + use_current_dimensions = !use_saved_dimensions && + window->width > 0 && + window->height > 0; + } + + /* The saved or current dimensions are the plain window content + * dimensions without the borders, so we can use them directly for + * new_width and new_height below. */ + if (use_current_dimensions) { + new_width = window->width; + new_height = window->height; + } else if (use_saved_dimensions) { + new_width = window->saved_width; + new_height = window->saved_height; + } else { + new_width = (width > hborder) ? (width - hborder) : 1; + new_height = (height > vborder) ? (height - vborder) : 1; + } if (window->width != new_width || window->height != new_height) { window->width = new_width; window->height = new_height; + /* Save the toplevel size so that we can pick up a reasonable + * value when the compositor tell us to choose a size. We are + * already saving the size before going fullscreen/maximized, + * but this covers the case in which our size is changed but we + * continue on a normal state. */ + if (!weston_wm_window_is_maximized(window) && !window->fullscreen) { + window->saved_width = new_width; + window->saved_height = new_height; + } + if (window->frame) { if (weston_wm_window_is_maximized(window)) frame_set_flag(window->frame, FRAME_FLAG_MAXIMIZED);