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 ba82af938a
"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 <alexandros.frantzis@collabora.com>
Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Co-authored-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
Alexandros Frantzis 2023-02-27 22:30:24 -03:00 committed by Marius Vlad
parent 12a7e4e163
commit 2acd2c7489

View File

@ -2809,6 +2809,8 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height)
struct theme *t; struct theme *t;
int new_width, new_height; int new_width, new_height;
int vborder, hborder; int vborder, hborder;
bool use_saved_dimensions = false;
bool use_current_dimensions = false;
if (!window || !window->wm) if (!window || !window->wm)
return; return;
@ -2823,20 +2825,46 @@ send_configure(struct weston_surface *surface, int32_t width, int32_t height)
vborder = 0; vborder = 0;
} }
if (width > hborder) /* A config event with width == 0 or height == 0 is a hint to the client
new_width = width - hborder; * to choose its own dimensions. Since X11 clients don't support such
else * hints we make a best guess here by trying to use the last saved
new_width = 1; * 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;
}
if (height > vborder) /* The saved or current dimensions are the plain window content
new_height = height - vborder; * dimensions without the borders, so we can use them directly for
else * new_width and new_height below. */
new_height = 1; 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) { if (window->width != new_width || window->height != new_height) {
window->width = new_width; window->width = new_width;
window->height = new_height; 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 (window->frame) {
if (weston_wm_window_is_maximized(window)) if (weston_wm_window_is_maximized(window))
frame_set_flag(window->frame, FRAME_FLAG_MAXIMIZED); frame_set_flag(window->frame, FRAME_FLAG_MAXIMIZED);