diff --git a/docs/changelog.rst b/docs/changelog.rst index 0889556a9..5e348338f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -112,6 +112,9 @@ Detailed list of changes - A new :opt:`cursor_trail_color` setting to independently control the color of 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] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/wl_client_side_decorations.c b/glfw/wl_client_side_decorations.c index a5cf896a2..05fb44e87 100644 --- a/glfw/wl_client_side_decorations.c +++ b/glfw/wl_client_side_decorations.c @@ -570,6 +570,11 @@ window_is_csd_capable(_GLFWwindow *window) { 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 ensure_csd_resources(_GLFWwindow *window) { if (!window_is_csd_capable(window)) return false; @@ -653,18 +658,18 @@ csd_change_title(_GLFWwindow *window) { void 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; if (!size_specified_by_compositor) { *width = window->wl.user_requested_content_size.width; *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.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.width = *width; decs.geometry.height = *height; - if (has_csd) { + if (include_space_for_csd) { decs.geometry.y = -decs.metrics.visible_titlebar_height; *height -= decs.metrics.visible_titlebar_height; } diff --git a/glfw/wl_client_side_decorations.h b/glfw/wl_client_side_decorations.h index 938fb53b7..915564c8c 100644 --- a/glfw/wl_client_side_decorations.h +++ b/glfw/wl_client_side_decorations.h @@ -13,5 +13,6 @@ void csd_free_all_resources(_GLFWwindow *window); bool csd_change_title(_GLFWwindow *window); 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_should_window_be_decorated(_GLFWwindow *window); void csd_set_visible(_GLFWwindow *window, bool visible); void csd_handle_pointer_event(_GLFWwindow *window, int button, int state, struct wl_surface* surface); diff --git a/glfw/wl_window.c b/glfw/wl_window.c index ec9dbb032..85a6475b7 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -424,7 +424,7 @@ apply_scale_changes(_GLFWwindow *window, bool resize_framebuffer, bool update_cs double scale = _glfwWaylandWindowScale(window); if (resize_framebuffer) resizeFramebuffer(window); _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; 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; csd_set_window_geometry(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); } @@ -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); } else { 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); window->wl.width = w; window->wl.height = h; 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); inform_compositor_of_window_geometry(window, "SetWindowSize"); }