Wayland: Fix incorrect window size calculation when transitioning from fullscreen to non-fullscreen with client side decorations

Fixes #8826
This commit is contained in:
Kovid Goyal 2025-07-17 20:36:38 +05:30
parent c16e2aad05
commit 7738c55c4b
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 16 additions and 7 deletions

View file

@ -112,6 +112,9 @@ Detailed list of changes
- A new :opt:`cursor_trail_color` setting to independently control the color of - A new :opt:`cursor_trail_color` setting to independently control the color of
cursor trails (:pull:`8830`) cursor trails (:pull:`8830`)
- Wayland: Fix incorrect window size calculation when transitioning from
fullscreen to non-fullscreen with client side decorations (:iss:`8826`)
0.42.2 [2025-07-16] 0.42.2 [2025-07-16]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -570,6 +570,11 @@ window_is_csd_capable(_GLFWwindow *window) {
return window->decorated && !decs.serverSide && window->wl.xdg.toplevel; return window->decorated && !decs.serverSide && window->wl.xdg.toplevel;
} }
bool
csd_should_window_be_decorated(_GLFWwindow *window) {
return window_is_csd_capable(window) && window->monitor == NULL && (window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN) == 0;
}
static bool static bool
ensure_csd_resources(_GLFWwindow *window) { ensure_csd_resources(_GLFWwindow *window) {
if (!window_is_csd_capable(window)) return false; if (!window_is_csd_capable(window)) return false;
@ -653,18 +658,18 @@ csd_change_title(_GLFWwindow *window) {
void void
csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height) { csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height) {
bool has_csd = window_is_csd_capable(window) && decs.titlebar.surface && !(window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN); const bool include_space_for_csd = csd_should_window_be_decorated(window);
bool size_specified_by_compositor = *width > 0 && *height > 0; bool size_specified_by_compositor = *width > 0 && *height > 0;
if (!size_specified_by_compositor) { if (!size_specified_by_compositor) {
*width = window->wl.user_requested_content_size.width; *width = window->wl.user_requested_content_size.width;
*height = window->wl.user_requested_content_size.height; *height = window->wl.user_requested_content_size.height;
if (window->wl.xdg.top_level_bounds.width > 0) *width = MIN(*width, window->wl.xdg.top_level_bounds.width); if (window->wl.xdg.top_level_bounds.width > 0) *width = MIN(*width, window->wl.xdg.top_level_bounds.width);
if (window->wl.xdg.top_level_bounds.height > 0) *height = MIN(*height, window->wl.xdg.top_level_bounds.height); if (window->wl.xdg.top_level_bounds.height > 0) *height = MIN(*height, window->wl.xdg.top_level_bounds.height);
if (has_csd) *height += decs.metrics.visible_titlebar_height; if (include_space_for_csd) *height += decs.metrics.visible_titlebar_height;
} }
decs.geometry.x = 0; decs.geometry.y = 0; decs.geometry.x = 0; decs.geometry.y = 0;
decs.geometry.width = *width; decs.geometry.height = *height; decs.geometry.width = *width; decs.geometry.height = *height;
if (has_csd) { if (include_space_for_csd) {
decs.geometry.y = -decs.metrics.visible_titlebar_height; decs.geometry.y = -decs.metrics.visible_titlebar_height;
*height -= decs.metrics.visible_titlebar_height; *height -= decs.metrics.visible_titlebar_height;
} }

View file

@ -13,5 +13,6 @@ void csd_free_all_resources(_GLFWwindow *window);
bool csd_change_title(_GLFWwindow *window); bool csd_change_title(_GLFWwindow *window);
void csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height); void csd_set_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height);
bool csd_set_titlebar_color(_GLFWwindow *window, uint32_t color, bool use_system_color); bool csd_set_titlebar_color(_GLFWwindow *window, uint32_t color, bool use_system_color);
bool csd_should_window_be_decorated(_GLFWwindow *window);
void csd_set_visible(_GLFWwindow *window, bool visible); void csd_set_visible(_GLFWwindow *window, bool visible);
void csd_handle_pointer_event(_GLFWwindow *window, int button, int state, struct wl_surface* surface); void csd_handle_pointer_event(_GLFWwindow *window, int button, int state, struct wl_surface* surface);

8
glfw/wl_window.c vendored
View file

@ -424,7 +424,7 @@ apply_scale_changes(_GLFWwindow *window, bool resize_framebuffer, bool update_cs
double scale = _glfwWaylandWindowScale(window); double scale = _glfwWaylandWindowScale(window);
if (resize_framebuffer) resizeFramebuffer(window); if (resize_framebuffer) resizeFramebuffer(window);
_glfwInputWindowContentScale(window, (float)scale, (float)scale); _glfwInputWindowContentScale(window, (float)scale, (float)scale);
if (update_csd) csd_set_visible(window, true); // resize the csd iff the window currently has CSD if (update_csd) csd_set_visible(window, csd_should_window_be_decorated(window)); // resize the csd iff the window currently has CSD
int buffer_scale = window->wl.fractional_scale ? 1 : (int)scale; int buffer_scale = window->wl.fractional_scale ? 1 : (int)scale;
wl_surface_set_buffer_scale(window->wl.surface, buffer_scale); wl_surface_set_buffer_scale(window->wl.surface, buffer_scale);
} }
@ -824,7 +824,7 @@ apply_xdg_configure_changes(_GLFWwindow *window) {
int width = window->wl.pending.width, height = window->wl.pending.height; int width = window->wl.pending.width, height = window->wl.pending.height;
csd_set_window_geometry(window, &width, &height); csd_set_window_geometry(window, &width, &height);
bool resized = dispatchChangesAfterConfigure(window, width, height); bool resized = dispatchChangesAfterConfigure(window, width, height);
csd_set_visible(window, !(window->wl.decorations.serverSide || window->monitor || window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN)); csd_set_visible(window, csd_should_window_be_decorated(window));
debug("Final window %llu content size: %dx%d resized: %d\n", window->id, width, height, resized); debug("Final window %llu content size: %dx%d resized: %d\n", window->id, width, height, resized);
} }
@ -967,7 +967,7 @@ setXdgDecorations(_GLFWwindow* window)
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, window->decorated ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, window->decorated ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE: ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
} else { } else {
window->wl.decorations.serverSide = false; window->wl.decorations.serverSide = false;
csd_set_visible(window, window->decorated); csd_set_visible(window, csd_should_window_be_decorated(window));
} }
} }
@ -1632,7 +1632,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
csd_set_window_geometry(window, &w, &h); csd_set_window_geometry(window, &w, &h);
window->wl.width = w; window->wl.height = h; window->wl.width = w; window->wl.height = h;
resizeFramebuffer(window); resizeFramebuffer(window);
csd_set_visible(window, true); // resizes the csd iff the window currently has csd csd_set_visible(window, csd_should_window_be_decorated(window)); // resizes the csd iff the window currently has csd
commit_window_surface_if_safe(window); commit_window_surface_if_safe(window);
inform_compositor_of_window_geometry(window, "SetWindowSize"); inform_compositor_of_window_geometry(window, "SetWindowSize");
} }