diff --git a/glfw/wl_client_side_decorations.c b/glfw/wl_client_side_decorations.c index 3fc79a194..9d09ce3ae 100644 --- a/glfw/wl_client_side_decorations.c +++ b/glfw/wl_client_side_decorations.c @@ -263,11 +263,11 @@ static bool create_shm_buffers(_GLFWwindow* window) { const unsigned scale = window->wl.scale >= 1 ? window->wl.scale : 1; - const size_t vertical_width = decs.metrics.width, vertical_height = window->wl.height + decs.metrics.top; - const size_t horizontal_height = decs.metrics.width, horizontal_width = window->wl.width + 2 * decs.metrics.width; + const size_t vertical_width = decs.metrics.width, vertical_height = window->wl.current.height + decs.metrics.top; + const size_t horizontal_height = decs.metrics.width, horizontal_width = window->wl.current.width + 2 * decs.metrics.width; decs.mapping.size = 0; - decs.mapping.size += init_buffer_pair(&decs.top.buffer, window->wl.width, decs.metrics.top, scale); + decs.mapping.size += init_buffer_pair(&decs.top.buffer, window->wl.current.width, decs.metrics.top, scale); decs.mapping.size += init_buffer_pair(&decs.left.buffer, vertical_width, vertical_height, scale); decs.mapping.size += init_buffer_pair(&decs.bottom.buffer, horizontal_width, horizontal_height, scale); decs.mapping.size += init_buffer_pair(&decs.right.buffer, vertical_width, vertical_height, scale); @@ -347,8 +347,8 @@ ensure_csd_resources(_GLFWwindow *window) { const bool is_focused = window->id == _glfw.focusedWindowId; const bool focus_changed = is_focused != decs.for_window_state.focused; const bool size_changed = ( - decs.for_window_state.width != window->wl.width || - decs.for_window_state.height != window->wl.height || + decs.for_window_state.width != window->wl.current.width || + decs.for_window_state.height != window->wl.current.height || decs.for_window_state.scale != window->wl.scale || !decs.mapping.data ); @@ -368,11 +368,11 @@ ensure_csd_resources(_GLFWwindow *window) { if (!decs.left.surface) create_csd_surfaces(window, &decs.left); position_csd_surface(&decs.left, x, y, scale); - x = -decs.metrics.width; y = window->wl.height; + x = -decs.metrics.width; y = window->wl.current.height; if (!decs.bottom.surface) create_csd_surfaces(window, &decs.bottom); position_csd_surface(&decs.bottom, x, y, scale); - x = window->wl.width; y = -decs.metrics.top; + x = window->wl.current.width; y = -decs.metrics.top; if (!decs.right.surface) create_csd_surfaces(window, &decs.right); position_csd_surface(&decs.right, x, y, scale); @@ -382,8 +382,8 @@ ensure_csd_resources(_GLFWwindow *window) { damage_csd(bottom, is_focused ? decs.bottom.buffer.front : decs.bottom.buffer.back); damage_csd(right, is_focused ? decs.right.buffer.front : decs.right.buffer.back); - decs.for_window_state.width = window->wl.width; - decs.for_window_state.height = window->wl.height; + decs.for_window_state.width = window->wl.current.width; + decs.for_window_state.height = window->wl.current.height; decs.for_window_state.scale = window->wl.scale; decs.for_window_state.focused = is_focused; return true; @@ -409,7 +409,7 @@ change_csd_title(_GLFWwindow *window) { void set_csd_window_geometry(_GLFWwindow *window, int32_t *width, int32_t *height) { - bool has_csd = window->decorated && !window->wl.decorations.serverSide && window->wl.decorations.left.surface && !(window->wl.toplevel_states & TOPLEVEL_STATE_FULLSCREEN); + bool has_csd = window->decorated && !window->wl.decorations.serverSide && window->wl.decorations.left.surface && !(window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN); bool size_specified_by_compositor = *width > 0 && *height > 0; if (!size_specified_by_compositor) { *width = window->wl.user_requested_content_size.width; diff --git a/glfw/wl_init.c b/glfw/wl_init.c index d9826670c..1fa6207f5 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -206,7 +206,7 @@ static void pointerHandleMotion(void* data UNUSED, case BOTTOM_DECORATION: if (x < window->wl.decorations.metrics.width) cursorShape = GLFW_SW_RESIZE_CURSOR; - else if (x > window->wl.width + window->wl.decorations.metrics.width) + else if (x > window->wl.current.width + window->wl.decorations.metrics.width) cursorShape = GLFW_SE_RESIZE_CURSOR; else cursorShape = GLFW_VRESIZE_CURSOR; @@ -243,7 +243,7 @@ static void pointerHandleButton(void* data UNUSED, window->wl.decorations.last_click_on_top_decoration_at = monotonic(); if (window->wl.decorations.last_click_on_top_decoration_at - last_click_at <= _glfwPlatformGetDoubleClickInterval(window)) { window->wl.decorations.last_click_on_top_decoration_at = 0; - if (window->wl.toplevel_states & TOPLEVEL_STATE_MAXIMIZED) + if (window->wl.current.toplevel_states & TOPLEVEL_STATE_MAXIMIZED) xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); else xdg_toplevel_set_maximized(window->wl.xdg.toplevel); @@ -274,7 +274,7 @@ static void pointerHandleButton(void* data UNUSED, case BOTTOM_DECORATION: if (x < window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; - else if (x > window->wl.width + window->wl.decorations.metrics.width) + else if (x > window->wl.current.width + window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; else edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 164d9d0ce..399a17f68 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -128,11 +128,15 @@ typedef enum WaylandWindowState { static const WaylandWindowState TOPLEVEL_STATE_DOCKED = TOPLEVEL_STATE_MAXIMIZED | TOPLEVEL_STATE_FULLSCREEN | TOPLEVEL_STATE_TILED_TOP | TOPLEVEL_STATE_TILED_LEFT | TOPLEVEL_STATE_TILED_RIGHT | TOPLEVEL_STATE_TILED_BOTTOM; +typedef struct _GLFWwindowWaylandState { + int width, height; + uint32_t toplevel_states; +} _GLFWwindowWaylandState; + // Wayland-specific per-window data // typedef struct _GLFWwindowWayland { - int width, height; bool visible; bool hovered; bool transparent; @@ -210,7 +214,6 @@ typedef struct _GLFWwindowWayland int32_t width, height; } user_requested_content_size; - uint32_t toplevel_states; bool maximize_on_first_show; // counters for ignoring axis events following axis_discrete events in the // same frame along the same axis @@ -218,6 +221,7 @@ typedef struct _GLFWwindowWayland unsigned int x, y; } axis_discrete_count; + _GLFWwindowWaylandState current, pending; } _GLFWwindowWayland; typedef enum _GLFWWaylandOfferType diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 7f713c400..17081eb40 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -206,7 +206,7 @@ static void setOpaqueRegion(_GLFWwindow* window) if (!region) return; - wl_region_add(region, 0, 0, window->wl.width, window->wl.height); + wl_region_add(region, 0, 0, window->wl.current.width, window->wl.current.height); wl_surface_set_opaque_region(window->wl.surface, region); wl_surface_commit(window->wl.surface); wl_region_destroy(region); @@ -216,9 +216,9 @@ static void setOpaqueRegion(_GLFWwindow* window) static void resizeFramebuffer(_GLFWwindow* window) { int scale = window->wl.scale; - int scaledWidth = window->wl.width * scale; - int scaledHeight = window->wl.height * scale; - debug("Resizing framebuffer to: %dx%d at scale: %d\n", window->wl.width, window->wl.height, scale); + int scaledWidth = window->wl.current.width * scale; + int scaledHeight = window->wl.current.height * scale; + debug("Resizing framebuffer to: %dx%d at scale: %d\n", window->wl.current.width, window->wl.current.height, scale); wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0); if (!window->wl.transparent) setOpaqueRegion(window); _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); @@ -236,12 +236,12 @@ clipboard_mime(void) { static void dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, int32_t height) { - bool size_changed = width != window->wl.width || height != window->wl.height; + bool size_changed = width != window->wl.current.width || height != window->wl.current.height; bool scale_changed = checkScaleChange(window); if (size_changed) { _glfwInputWindowSize(window, width, height); - window->wl.width = width; window->wl.height = height; + window->wl.current.width = width; window->wl.current.height = height; resizeFramebuffer(window); } @@ -274,7 +274,7 @@ xdgDecorationHandleConfigure(void* data, debug("XDG decoration configure event received: has_server_side_decorations: %d\n", has_server_side_decorations); if (has_server_side_decorations == window->wl.decorations.serverSide) return; window->wl.decorations.serverSide = has_server_side_decorations; - int width = window->wl.width, height = window->wl.height; + int width = window->wl.current.width, height = window->wl.current.height; if (window->wl.decorations.serverSide) { free_csd_surfaces(window); height += window->wl.decorations.metrics.visible_titlebar_height; @@ -285,7 +285,7 @@ xdgDecorationHandleConfigure(void* data, dispatchChangesAfterConfigure(window, width, height); ensure_csd_resources(window); wl_surface_commit(window->wl.surface); - debug("final window content size: %dx%d\n", window->wl.width, window->wl.height); + debug("final window content size: %dx%d\n", window->wl.current.width, window->wl.current.height); inform_compositor_of_window_geometry(window, "configure-decorations"); } @@ -384,8 +384,8 @@ static bool createSurface(_GLFWwindow* window, if (!window->wl.native) return false; - window->wl.width = wndconfig->width; - window->wl.height = wndconfig->height; + window->wl.current.width = wndconfig->width; + window->wl.current.height = wndconfig->height; window->wl.user_requested_content_size.width = wndconfig->width; window->wl.user_requested_content_size.height = wndconfig->height; window->wl.scale = 1; @@ -416,7 +416,7 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, bool on) bool _glfwPlatformIsFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) { - return window->wl.toplevel_states & TOPLEVEL_STATE_FULLSCREEN; + return window->wl.current.toplevel_states & TOPLEVEL_STATE_FULLSCREEN; } bool @@ -458,7 +458,7 @@ xdgToplevelHandleConfigure(void* data, if (new_states & TOPLEVEL_STATE_RESIZING) { if (width) window->wl.user_requested_content_size.width = width; if (height) window->wl.user_requested_content_size.height = height; - if (!(window->wl.toplevel_states & TOPLEVEL_STATE_RESIZING)) _glfwInputLiveResize(window, true); + if (!(window->wl.current.toplevel_states & TOPLEVEL_STATE_RESIZING)) _glfwInputLiveResize(window, true); } if (width != 0 && height != 0) { @@ -475,16 +475,10 @@ xdgToplevelHandleConfigure(void* data, } } } - bool live_resize_done = !(new_states & TOPLEVEL_STATE_RESIZING) && (window->wl.toplevel_states & TOPLEVEL_STATE_RESIZING); - window->wl.toplevel_states = new_states; - set_csd_window_geometry(window, &width, &height); - dispatchChangesAfterConfigure(window, width, height); - debug("final window content size: %dx%d\n", window->wl.width, window->wl.height); - _glfwInputWindowFocus(window, window->wl.toplevel_states & TOPLEVEL_STATE_ACTIVATED); - ensure_csd_resources(window); - wl_surface_commit(window->wl.surface); - inform_compositor_of_window_geometry(window, "configure"); - if (live_resize_done) _glfwInputLiveResize(window, false); + + window->wl.pending.toplevel_states = new_states; + window->wl.pending.width = width; + window->wl.pending.height = height; } static void xdgToplevelHandleClose(void* data, @@ -499,11 +493,33 @@ static const struct xdg_toplevel_listener xdgToplevelListener = { xdgToplevelHandleClose }; -static void xdgSurfaceHandleConfigure(void* data UNUSED, +static void xdgSurfaceHandleConfigure(void* data, struct xdg_surface* surface, uint32_t serial) { + _GLFWwindow* window = data; xdg_surface_ack_configure(surface, serial); + + + uint32_t new_states = window->wl.pending.toplevel_states; + int width = window->wl.pending.width; + int height = window->wl.pending.height; + + if (new_states != window->wl.current.toplevel_states || + width != window->wl.current.width || + height != window->wl.current.height) { + + bool live_resize_done = !(new_states & TOPLEVEL_STATE_RESIZING) && (window->wl.current.toplevel_states & TOPLEVEL_STATE_RESIZING); + window->wl.current.toplevel_states = new_states; + set_csd_window_geometry(window, &width, &height); + dispatchChangesAfterConfigure(window, width, height); + debug("final window content size: %dx%d\n", window->wl.current.width, window->wl.current.height); + _glfwInputWindowFocus(window, window->wl.current.toplevel_states & TOPLEVEL_STATE_ACTIVATED); + ensure_csd_resources(window); + wl_surface_commit(window->wl.surface); + inform_compositor_of_window_geometry(window, "configure"); + if (live_resize_done) _glfwInputLiveResize(window, false); + } } static const struct xdg_surface_listener xdgSurfaceListener = { @@ -886,19 +902,19 @@ void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) { if (width) - *width = window->wl.width; + *width = window->wl.current.width; if (height) - *height = window->wl.height; + *height = window->wl.current.height; } void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { - if (width != window->wl.width || height != window->wl.height) { + if (width != window->wl.current.width || height != window->wl.current.height) { window->wl.user_requested_content_size.width = width; window->wl.user_requested_content_size.height = height; int32_t w = 0, h = 0; set_csd_window_geometry(window, &w, &h); - window->wl.width = w; window->wl.height = h; + window->wl.current.width = w; window->wl.current.height = h; resizeFramebuffer(window); ensure_csd_resources(window); wl_surface_commit(window->wl.surface); @@ -991,7 +1007,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) { if (window->monitor) xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); - if (window->wl.toplevel_states & TOPLEVEL_STATE_MAXIMIZED) + if (window->wl.current.toplevel_states & TOPLEVEL_STATE_MAXIMIZED) xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); // There is no way to unset minimized, or even to know if we are // minimized, so there is nothing to do in this case. @@ -1092,7 +1108,7 @@ int _glfwPlatformWindowVisible(_GLFWwindow* window) int _glfwPlatformWindowMaximized(_GLFWwindow* window) { - return window->wl.toplevel_states & TOPLEVEL_STATE_MAXIMIZED; + return window->wl.current.toplevel_states & TOPLEVEL_STATE_MAXIMIZED; } int _glfwPlatformWindowHovered(_GLFWwindow* window)