From aeb82e7fb0e8961a66ac7c54c1aecabcae86f533 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 26 Mar 2021 13:10:54 +0530 Subject: [PATCH] Refactor the rendering of CSD on Wayland --- glfw/source-info.json | 2 + glfw/wl_client_side_decorations.c | 200 ++++++++++++++++++++++++++++++ glfw/wl_client_side_decorations.h | 14 +++ glfw/wl_init.c | 87 ++++++------- glfw/wl_platform.h | 58 +++++---- glfw/wl_window.c | 135 ++++---------------- 6 files changed, 311 insertions(+), 185 deletions(-) create mode 100644 glfw/wl_client_side_decorations.c create mode 100644 glfw/wl_client_side_decorations.h diff --git a/glfw/source-info.json b/glfw/source-info.json index b08c77154..cc2fb7ee8 100644 --- a/glfw/source-info.json +++ b/glfw/source-info.json @@ -66,6 +66,7 @@ "null_joystick.h", "linux_notify.h", "linux_desktop_settings.h", + "wl_client_side_decorations.h", "main_loop.h" ], "protocols": [ @@ -84,6 +85,7 @@ "wl_window.c", "wl_cursors.c", "wl_text_input.c", + "wl_client_side_decorations.c", "posix_thread.c", "xkb_glfw.c", "dbus_glfw.c", diff --git a/glfw/wl_client_side_decorations.c b/glfw/wl_client_side_decorations.c new file mode 100644 index 000000000..97bb4fd96 --- /dev/null +++ b/glfw/wl_client_side_decorations.c @@ -0,0 +1,200 @@ +/* + * wl_client_side_decorations.c + * Copyright (C) 2021 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include "wl_client_side_decorations.h" + +#include "backend_utils.h" +#include +#include +#include + +#define decs window->wl.decorations +#define tb decs.title_bar +#define eb decs.edges + +#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +static const uint32_t bg_color = 0xfffefefe; + +static void +free_title_bar_resources(_GLFWwindow *window) { + if (tb.front_buffer) { + wl_buffer_destroy(tb.front_buffer); + tb.front_buffer = NULL; + } + if (tb.back_buffer) { + wl_buffer_destroy(tb.back_buffer); + tb.back_buffer = NULL; + } + if (tb.data) { + munmap(tb.data, tb.buffer_sz * 2); + tb.data = NULL; + } +} + +static void +free_edge_resources(_GLFWwindow *window) { + if (eb.left) { wl_buffer_destroy(eb.left); eb.left = NULL; } + if (eb.right) { wl_buffer_destroy(eb.right); eb.right = NULL; } + if (eb.bottom) { wl_buffer_destroy(eb.bottom); eb.bottom = NULL; } +} + +static bool +create_shm_buffers_for_title_bar(_GLFWwindow* window) { + free_title_bar_resources(window); + const size_t stride = 4 * window->wl.width; + tb.buffer_sz = stride * window->wl.decorations.metrics.top; + const size_t mapping_sz = tb.buffer_sz * 2; + + int fd = createAnonymousFile(mapping_sz); + if (fd < 0) { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Creating a buffer file for %zu B failed: %s", + mapping_sz, strerror(errno)); + return false; + } + tb.data = mmap(NULL, mapping_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (tb.data == MAP_FAILED) { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: mmap failed: %s", strerror(errno)); + close(fd); + return false; + } + for (uint32_t *px = (uint32_t*)tb.data, *end = (uint32_t*)(tb.data + tb.buffer_sz); px < end; px++) *px = bg_color; + struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, mapping_sz); + close(fd); +#define c(offset) wl_shm_pool_create_buffer( \ + pool, offset, window->wl.width, window->wl.decorations.metrics.top, stride, WL_SHM_FORMAT_ARGB8888); + tb.front_buffer = c(0); tb.back_buffer = c(tb.buffer_sz); +#undef c + wl_shm_pool_destroy(pool); + return true; +} + +static void +render_left_edge(uint8_t *data, size_t width, size_t height) { + for (uint32_t *px = (uint32_t*)data, *end = (uint32_t*)(data + 4 * width * height); px < end; px++) *px = bg_color; +} +#define render_right_edge render_left_edge +#define render_bottom_edge render_left_edge + +static bool +create_shm_buffers_for_edges(_GLFWwindow* window) { + free_edge_resources(window); + + const size_t vertical_width = window->wl.decorations.metrics.width, vertical_height = window->wl.height; + const size_t horizontal_height = window->wl.decorations.metrics.width, horizontal_width = window->wl.width; + const size_t mapping_sz = 4 * (2 * vertical_width * vertical_height + horizontal_height * horizontal_width); + + int fd = createAnonymousFile(mapping_sz); + if (fd < 0) { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Creating a buffer file for %zu B failed: %s", + mapping_sz, strerror(errno)); + return false; + } + uint8_t *data = mmap(NULL, mapping_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: mmap failed: %s", strerror(errno)); + close(fd); + return false; + } + render_left_edge(data, vertical_width, vertical_height); + render_right_edge(data + 4 * vertical_width * vertical_height, vertical_width, vertical_height); + render_bottom_edge(data + 8 * vertical_width * vertical_height, horizontal_width, horizontal_height); + struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, mapping_sz); + close(fd); + eb.left = wl_shm_pool_create_buffer( + pool, 0, vertical_width, vertical_height, vertical_width * 4, WL_SHM_FORMAT_ARGB8888); + eb.right = wl_shm_pool_create_buffer( + pool, 4 * vertical_width * vertical_height, vertical_width, vertical_height, vertical_width * 4, WL_SHM_FORMAT_ARGB8888); + eb.bottom = wl_shm_pool_create_buffer( + pool, 8 * vertical_width * vertical_height, horizontal_width, horizontal_height, horizontal_width * 4, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + return true; +} + +void +free_csd_surfaces(_GLFWwindow *window) { +#define d(which) {\ + if (decs.subsurfaces.which) wl_subsurface_destroy(decs.subsurfaces.which); decs.subsurfaces.which = NULL; \ + if (decs.surfaces.which) wl_surface_destroy(decs.surfaces.which); decs.surfaces.which = NULL; \ + if (decs.viewports.which) wp_viewport_destroy(decs.viewports.which); \ +} + d(left); d(top); d(right); d(bottom); +#undef d +} + +#define position_decoration_surfaces(which, x, y, width, height) { \ + wl_subsurface_set_position(decs.subsurfaces.which, x, y); \ + wp_viewport_set_destination(decs.viewports.which, width, height); \ + wl_surface_commit(decs.surfaces.which); \ +} + +#define create_decoration_surfaces(which, buffer) { \ + decs.surfaces.which = wl_compositor_create_surface(_glfw.wl.compositor); \ + decs.subsurfaces.which = wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, decs.surfaces.which, window->wl.surface); \ + decs.viewports.which = wp_viewporter_get_viewport(_glfw.wl.viewporter, decs.surfaces.which); \ + wl_surface_attach(decs.surfaces.which, buffer, 0, 0); \ +} + +bool +ensure_csd_resources(_GLFWwindow *window) { + const bool size_changed = ( + decs.for_window_size.width != window->wl.width || + decs.for_window_size.height != window->wl.height || + decs.for_window_size.scale != window->wl.scale + ); + if (size_changed) { + free_title_bar_resources(window); + free_edge_resources(window); + } + if (!decs.edges.left) { + if (!create_shm_buffers_for_edges(window)) return false; + } + if (!decs.title_bar.front_buffer) { + if (!create_shm_buffers_for_title_bar(window)) return false; + } + int x, y, width, height; + + x = 0; y = -decs.metrics.top; + width = window->wl.width; height = decs.metrics.top; + if (!decs.surfaces.top) create_decoration_surfaces(top, decs.title_bar.front_buffer); + position_decoration_surfaces(top, x, y, width, height); + + x = -decs.metrics.width; y = -decs.metrics.top; + width = decs.metrics.width; height = decs.metrics.top + window->wl.height; + if (!decs.surfaces.left) create_decoration_surfaces(left, decs.edges.left); + position_decoration_surfaces(left, x, y, width, height); + + x = window->wl.width; y = -decs.metrics.top; + if (!decs.surfaces.right) create_decoration_surfaces(right, decs.edges.right); + position_decoration_surfaces(right, x, y, width, height); + + x = -decs.metrics.width; y = window->wl.height; + width = decs.metrics.horizontal + window->wl.width; height = decs.metrics.width; + if (!decs.surfaces.bottom) create_decoration_surfaces(bottom, decs.edges.bottom); + position_decoration_surfaces(bottom, x, y, width, height); + + decs.for_window_size.width = window->wl.width; + decs.for_window_size.height = window->wl.height; + decs.for_window_size.scale = window->wl.scale; + return true; +} + +void +free_all_csd_resources(_GLFWwindow *window) { + free_csd_surfaces(window); + free_title_bar_resources(window); + free_edge_resources(window); +} + +void +resize_csd(_GLFWwindow *window) { + ensure_csd_resources(window); +} diff --git a/glfw/wl_client_side_decorations.h b/glfw/wl_client_side_decorations.h new file mode 100644 index 000000000..b999f6e01 --- /dev/null +++ b/glfw/wl_client_side_decorations.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2021 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#pragma once + +#include "internal.h" + +void free_all_csd_resources(_GLFWwindow *window); +void free_csd_surfaces(_GLFWwindow *window); +void resize_csd(_GLFWwindow *window); +bool ensure_csd_resources(_GLFWwindow *window); diff --git a/glfw/wl_init.c b/glfw/wl_init.c index 62f59a396..f9230729e 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -29,6 +29,7 @@ #define _GNU_SOURCE #include "internal.h" #include "backend_utils.h" +#include "wl_client_side_decorations.h" #include "linux_desktop_settings.h" #include "../kitty/monotonic.h" @@ -59,37 +60,21 @@ static inline int min(int n1, int n2) return n1 < n2 ? n1 : n2; } -static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, - int* which) +static _GLFWwindow* +findWindowFromDecorationSurface(struct wl_surface* surface, _GLFWdecorationSideWayland* which) { - int focus; + _GLFWdecorationSideWayland focus; + if (!which) which = &focus; _GLFWwindow* window = _glfw.windowListHead; - if (!which) - which = &focus; - while (window) - { - if (surface == window->wl.decorations.top.surface) - { - *which = topDecoration; - break; - } - if (surface == window->wl.decorations.left.surface) - { - *which = leftDecoration; - break; - } - if (surface == window->wl.decorations.right.surface) - { - *which = rightDecoration; - break; - } - if (surface == window->wl.decorations.bottom.surface) - { - *which = bottomDecoration; - break; - } +#define q(edge, result) if (surface == window->wl.decorations.surfaces.edge) { *which = result; break; } + while (window) { + q(top, TOP_DECORATION); + q(left, LEFT_DECORATION); + q(right, RIGHT_DECORATION); + q(bottom, BOTTOM_DECORATION); window = window->next; } +#undef q return window; } @@ -104,7 +89,7 @@ static void pointerHandleEnter(void* data UNUSED, if (!surface) return; - int focus = 0; + _GLFWdecorationSideWayland focus = CENTRAL_WINDOW; _GLFWwindow* window = wl_surface_get_user_data(surface); if (!window) { @@ -195,34 +180,34 @@ static void pointerHandleMotion(void* data UNUSED, switch (window->wl.decorations.focus) { - case mainWindow: + case CENTRAL_WINDOW: window->wl.cursorPosX = x; window->wl.cursorPosY = y; _glfwInputCursorPos(window, x, y); _glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR; return; - case topDecoration: - if (y < window->wl.decoration_metrics.width) + case TOP_DECORATION: + if (y < window->wl.decorations.metrics.width) cursorShape = GLFW_VRESIZE_CURSOR; else cursorShape = GLFW_ARROW_CURSOR; break; - case leftDecoration: - if (y < window->wl.decoration_metrics.width) + case LEFT_DECORATION: + if (y < window->wl.decorations.metrics.width) cursorShape = GLFW_NW_RESIZE_CURSOR; else cursorShape = GLFW_HRESIZE_CURSOR; break; - case rightDecoration: - if (y < window->wl.decoration_metrics.width) + case RIGHT_DECORATION: + if (y < window->wl.decorations.metrics.width) cursorShape = GLFW_NE_RESIZE_CURSOR; else cursorShape = GLFW_HRESIZE_CURSOR; break; - case bottomDecoration: - if (x < window->wl.decoration_metrics.width) + case BOTTOM_DECORATION: + if (x < window->wl.decorations.metrics.width) cursorShape = GLFW_SW_RESIZE_CURSOR; - else if (x > window->wl.width + window->wl.decoration_metrics.width) + else if (x > window->wl.width + window->wl.decorations.metrics.width) cursorShape = GLFW_SE_RESIZE_CURSOR; else cursorShape = GLFW_VRESIZE_CURSOR; @@ -251,10 +236,10 @@ static void pointerHandleButton(void* data UNUSED, { switch (window->wl.decorations.focus) { - case mainWindow: + case CENTRAL_WINDOW: break; - case topDecoration: - if (y < window->wl.decoration_metrics.width) + case TOP_DECORATION: + if (y < window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; else { @@ -262,22 +247,22 @@ static void pointerHandleButton(void* data UNUSED, xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); } break; - case leftDecoration: - if (y < window->wl.decoration_metrics.width) + case LEFT_DECORATION: + if (y < window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; else edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT; break; - case rightDecoration: - if (y < window->wl.decoration_metrics.width) + case RIGHT_DECORATION: + if (y < window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; else edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; break; - case bottomDecoration: - if (x < window->wl.decoration_metrics.width) + 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.decoration_metrics.width) + else if (x > window->wl.width + window->wl.decorations.metrics.width) edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; else edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; @@ -293,15 +278,15 @@ static void pointerHandleButton(void* data UNUSED, } else if (button == BTN_RIGHT) { - if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel) + if (window->wl.decorations.focus != CENTRAL_WINDOW && window->wl.xdg.toplevel) { - xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial, (int32_t)x, (int32_t)y - window->wl.decoration_metrics.top); + xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial, (int32_t)x, (int32_t)y - window->wl.decorations.metrics.top); return; } } // Don’t pass the button to the user if it was related to a decoration. - if (window->wl.decorations.focus != mainWindow) + if (window->wl.decorations.focus != CENTRAL_WINDOW) return; _glfw.wl.serial = serial; diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 04cb49466..f093d69da 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -91,21 +91,13 @@ typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, typedef enum _GLFWdecorationSideWayland { - mainWindow, - topDecoration, - leftDecoration, - rightDecoration, - bottomDecoration, - + CENTRAL_WINDOW, + TOP_DECORATION, + LEFT_DECORATION, + RIGHT_DECORATION, + BOTTOM_DECORATION, } _GLFWdecorationSideWayland; -typedef struct _GLFWdecorationWayland -{ - struct wl_surface* surface; - struct wl_subsurface* subsurface; - struct wp_viewport* viewport; - -} _GLFWdecorationWayland; // Wayland-specific per-window data // @@ -150,10 +142,38 @@ typedef struct _GLFWwindowWayland bool fullscreened; struct { - bool serverSide; - struct wl_buffer* edge_buffer; - _GLFWdecorationWayland top, left, right, bottom; - int focus; + bool serverSide; + _GLFWdecorationSideWayland focus; + + struct { + struct wl_surface *top, *left, *right, *bottom; + } surfaces; + + struct { + struct wl_subsurface *top, *left, *right, *bottom; + } subsurfaces; + + struct { + struct wp_viewport *top, *left, *right, *bottom; + } viewports; + + struct { + struct wl_buffer *front_buffer, *back_buffer; + uint8_t *data; + size_t buffer_sz; + } title_bar; + + struct { + struct wl_buffer *left, *right, *bottom; + } edges; + + struct { + int width, height, scale; + } for_window_size; + + struct { + unsigned int width, top, horizontal, vertical; + } metrics; } decorations; struct { @@ -162,10 +182,6 @@ typedef struct _GLFWwindowWayland struct wl_callback *current_wl_callback; } frameCallbackData; - struct { - unsigned int width, top, horizontal, vertical; - } decoration_metrics; - } _GLFWwindowWayland; typedef enum _GLFWWaylandOfferType diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 68fe455d4..e93e1b60c 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -32,6 +32,7 @@ #include "backend_utils.h" #include "memfd.h" #include "linux_notify.h" +#include "wl_client_side_decorations.h" #include "../kitty/monotonic.h" #include @@ -221,32 +222,8 @@ static void resizeFramebuffer(_GLFWwindow* window) setOpaqueRegion(window); _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); - if (!window->wl.decorations.top.surface) - return; + if (window->wl.decorations.surfaces.top) resize_csd(window); - // Top decoration. - wp_viewport_set_destination(window->wl.decorations.top.viewport, - window->wl.width, window->wl.decoration_metrics.top); - wl_surface_commit(window->wl.decorations.top.surface); - - // Left decoration. - wp_viewport_set_destination(window->wl.decorations.left.viewport, - window->wl.decoration_metrics.width, window->wl.height + window->wl.decoration_metrics.top); - wl_surface_commit(window->wl.decorations.left.surface); - - // Right decoration. - wl_subsurface_set_position(window->wl.decorations.right.subsurface, - window->wl.width, -window->wl.decoration_metrics.top); - wp_viewport_set_destination(window->wl.decorations.right.viewport, - window->wl.decoration_metrics.width, window->wl.height + window->wl.decoration_metrics.top); - wl_surface_commit(window->wl.decorations.right.surface); - - // Bottom decoration. - wl_subsurface_set_position(window->wl.decorations.bottom.subsurface, - -window->wl.decoration_metrics.width, window->wl.height); - wp_viewport_set_destination(window->wl.decorations.bottom.viewport, - window->wl.width + window->wl.decoration_metrics.horizontal, window->wl.decoration_metrics.width); - wl_surface_commit(window->wl.decorations.bottom.surface); } @@ -280,75 +257,11 @@ static void dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, in } -static void createDecoration(_GLFWdecorationWayland* decoration, - struct wl_surface* parent, - struct wl_buffer* buffer, - int x, int y, - int width, int height) -{ - decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor); - decoration->subsurface = - wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, - decoration->surface, parent); - wl_subsurface_set_position(decoration->subsurface, x, y); - decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter, - decoration->surface); - wp_viewport_set_destination(decoration->viewport, width, height); - wl_surface_attach(decoration->surface, buffer, 0, 0); - wl_surface_commit(decoration->surface); -} +static void +createDecorations(_GLFWwindow* window) { + if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide) return; -static void createDecorations(_GLFWwindow* window) -{ - unsigned char data[] = { 224, 224, 224, 255 }; - const GLFWimage image = { 1, 1, data }; - bool is_opaque = (data[3] == 255); - - if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide) - return; - - if (!window->wl.decorations.edge_buffer) - window->wl.decorations.edge_buffer = createShmBuffer(&image, is_opaque, true); - if (!window->wl.decorations.edge_buffer) - return; - - createDecoration(&window->wl.decorations.top, window->wl.surface, - window->wl.decorations.edge_buffer, - 0, -window->wl.decoration_metrics.top, - window->wl.width, window->wl.decoration_metrics.top); - createDecoration(&window->wl.decorations.left, window->wl.surface, - window->wl.decorations.edge_buffer, - -window->wl.decoration_metrics.width, -window->wl.decoration_metrics.top, - window->wl.decoration_metrics.width, window->wl.height + window->wl.decoration_metrics.top); - createDecoration(&window->wl.decorations.right, window->wl.surface, - window->wl.decorations.edge_buffer, - window->wl.width, -window->wl.decoration_metrics.top, - window->wl.decoration_metrics.width, window->wl.height + window->wl.decoration_metrics.top); - createDecoration(&window->wl.decorations.bottom, window->wl.surface, - window->wl.decorations.edge_buffer, - -window->wl.decoration_metrics.width, window->wl.height, - window->wl.width + window->wl.decoration_metrics.horizontal, window->wl.decoration_metrics.width); -} - -static void destroyDecoration(_GLFWdecorationWayland* decoration) -{ - if (decoration->subsurface) - wl_subsurface_destroy(decoration->subsurface); - if (decoration->surface) - wl_surface_destroy(decoration->surface); - if (decoration->viewport) - wp_viewport_destroy(decoration->viewport); - decoration->surface = NULL; - decoration->subsurface = NULL; - decoration->viewport = NULL; -} - -static void destroyDecorations(_GLFWwindow* window) -{ - destroyDecoration(&window->wl.decorations.top); - destroyDecoration(&window->wl.decorations.left); - destroyDecoration(&window->wl.decorations.right); - destroyDecoration(&window->wl.decorations.bottom); + ensure_csd_resources(window); } static void xdgDecorationHandleConfigure(void* data, @@ -474,8 +387,7 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, bool on) xdg_toplevel_set_fullscreen( window->wl.xdg.toplevel, monitor ? monitor->wl.output : NULL); - if (!window->wl.decorations.serverSide) - destroyDecorations(window); + if (!window->wl.decorations.serverSide) free_csd_surfaces(window); } else { xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); if (!_glfw.wl.decorationManager) @@ -541,9 +453,9 @@ static void xdgToplevelHandleConfigure(void* data, } window->wl.fullscreened = fullscreen; if (!fullscreen) { - if (window->decorated && !window->wl.decorations.serverSide && window->wl.decorations.edge_buffer) { - width -= window->wl.decoration_metrics.horizontal; - height -= window->wl.decoration_metrics.vertical; + if (window->decorated && !window->wl.decorations.serverSide && window->wl.decorations.edges.left) { + width -= window->wl.decorations.metrics.horizontal; + height -= window->wl.decorations.metrics.vertical; } } dispatchChangesAfterConfigure(window, width, height); @@ -659,7 +571,7 @@ static bool createXdgSurface(_GLFWwindow* window) static void incrementCursorImage(_GLFWwindow* window) { - if (window && window->wl.decorations.focus == mainWindow && window->cursorMode != GLFW_CURSOR_HIDDEN) { + if (window && window->wl.decorations.focus == CENTRAL_WINDOW && window->cursorMode != GLFW_CURSOR_HIDDEN) { _GLFWcursor* cursor = window->wl.currentCursor; if (cursor && cursor->wl.cursor) { @@ -802,10 +714,10 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - window->wl.decoration_metrics.width = 4; - window->wl.decoration_metrics.top = 24; - window->wl.decoration_metrics.horizontal = 2 * window->wl.decoration_metrics.width; - window->wl.decoration_metrics.vertical = window->wl.decoration_metrics.width + window->wl.decoration_metrics.top; + window->wl.decorations.metrics.width = 4; + window->wl.decorations.metrics.top = 24; + window->wl.decorations.metrics.horizontal = 2 * window->wl.decorations.metrics.width; + window->wl.decorations.metrics.vertical = window->wl.decorations.metrics.width + window->wl.decorations.metrics.top; window->wl.transparent = fbconfig->transparent; strncpy(window->wl.appId, wndconfig->wl.appId, sizeof(window->wl.appId)); @@ -880,13 +792,10 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->context.destroy) window->context.destroy(window); - destroyDecorations(window); + free_all_csd_resources(window); if (window->wl.xdg.decoration) zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); - if (window->wl.decorations.edge_buffer) - wl_buffer_destroy(window->wl.decorations.edge_buffer); - if (window->wl.native) wl_egl_window_destroy(window->wl.native); @@ -1010,13 +919,13 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, if (window->decorated && !window->monitor && !window->wl.decorations.serverSide) { if (top) - *top = window->wl.decoration_metrics.top; + *top = window->wl.decorations.metrics.top; if (left) - *left = window->wl.decoration_metrics.width; + *left = window->wl.decorations.metrics.width; if (right) - *right = window->wl.decoration_metrics.width; + *right = window->wl.decorations.metrics.width; if (bottom) - *bottom = window->wl.decoration_metrics.width; + *bottom = window->wl.decorations.metrics.width; } } @@ -1176,7 +1085,7 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled) if (enabled) createDecorations(window); else - destroyDecorations(window); + free_csd_surfaces(window); } } @@ -1435,7 +1344,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) // If we're not in the correct window just save the cursor // the next time the pointer enters the window the cursor will change - if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow) + if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != CENTRAL_WINDOW) return; // Unlock possible pointer lock if no longer disabled.