diff --git a/glfw/wl_client_side_decorations.c b/glfw/wl_client_side_decorations.c index 14d6549f8..9996fd3d4 100644 --- a/glfw/wl_client_side_decorations.c +++ b/glfw/wl_client_side_decorations.c @@ -15,9 +15,16 @@ #define decs window->wl.decorations #define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define SWAP(x, y) do { __typeof__(x) SWAP = x; x = y; y = SWAP; } while (0) static const uint32_t bg_color = 0xfffefefe; +static void +swap_buffers(_GLFWWaylandBufferPair *pair) { + SWAP(pair->front, pair->back); + SWAP(pair->data.front, pair->data.back); +} + static size_t init_buffer_pair(_GLFWWaylandBufferPair *pair, size_t width, size_t height, unsigned scale) { memset(pair, 0, sizeof(_GLFWWaylandBufferPair)); @@ -38,7 +45,6 @@ alloc_buffer_pair(_GLFWWaylandBufferPair *pair, struct wl_shm_pool *pool, uint8_ *offset += pair->size_in_bytes; pair->front = pair->a; pair->back = pair->b; pair->data.front = pair->data.a; pair->data.back = pair->data.b; - pair->back_buffer_is_safe = true; } static void @@ -131,6 +137,11 @@ create_csd_surfaces(_GLFWwindow *window, _GLFWWaylandCSDEdge *s) { s->subsurface = wl_subcompositor_get_subsurface(_glfw.wl.subcompositor, s->surface, window->wl.surface); } +#define damage_csd(which, xbuffer) \ + wl_surface_attach(decs.which.surface, xbuffer, 0, 0); \ + wl_surface_damage(decs.which.surface, 0, 0, decs.which.buffer.width, decs.which.buffer.height); \ + wl_surface_commit(decs.which.surface) + bool ensure_csd_resources(_GLFWwindow *window) { const bool is_focused = window->id == _glfw.focusedWindowId; @@ -142,7 +153,7 @@ ensure_csd_resources(_GLFWwindow *window) { !decs.mapping.data ); const bool needs_update = focus_changed || size_changed || !decs.left.surface; - if (!needs_update) return true; + if (!needs_update) return false; if (size_changed) { free_csd_buffers(window); if (!create_shm_buffers(window)) return false; @@ -165,16 +176,10 @@ ensure_csd_resources(_GLFWwindow *window) { if (!decs.right.surface) create_csd_surfaces(window, &decs.right); position_csd_surface(&decs.right, x, y, scale); -#define c(which, xbuffer) \ - wl_surface_attach(decs.which.surface, xbuffer, 0, 0); \ - wl_surface_damage(decs.which.surface, 0, 0, decs.which.buffer.width, decs.which.buffer.height); \ - wl_surface_commit(decs.which.surface) - - c(top, decs.top.buffer.front); - c(left, is_focused ? decs.left.buffer.front : decs.left.buffer.back); - c(bottom, is_focused ? decs.bottom.buffer.front : decs.bottom.buffer.back); - c(right, is_focused ? decs.right.buffer.front : decs.right.buffer.back); -#undef c + damage_csd(top, decs.top.buffer.front); + damage_csd(left, is_focused ? decs.left.buffer.front : decs.left.buffer.back); + 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; @@ -193,3 +198,13 @@ void resize_csd(_GLFWwindow *window) { ensure_csd_resources(window); } + +void +change_csd_title(_GLFWwindow *window) { + if (ensure_csd_resources(window)) return; // CSD were re-rendered for other reasons + if (decs.top.surface) { + render_title_bar(window, false); + swap_buffers(&decs.top.buffer); + damage_csd(top, decs.top.buffer.front); + } +} diff --git a/glfw/wl_client_side_decorations.h b/glfw/wl_client_side_decorations.h index b999f6e01..cb99e0543 100644 --- a/glfw/wl_client_side_decorations.h +++ b/glfw/wl_client_side_decorations.h @@ -11,4 +11,5 @@ void free_all_csd_resources(_GLFWwindow *window); void free_csd_surfaces(_GLFWwindow *window); void resize_csd(_GLFWwindow *window); +void change_csd_title(_GLFWwindow *window); bool ensure_csd_resources(_GLFWwindow *window); diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 5a4dbef09..19b1139bd 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -100,7 +100,7 @@ typedef enum _GLFWdecorationSideWayland typedef struct _GLFWWaylandBufferPair { struct wl_buffer *a, *b, *front, *back; struct { uint8_t *a, *b, *front, *back; } data; - bool back_buffer_is_safe, has_pending_update; + bool has_pending_update; size_t size_in_bytes, width, height, stride; } _GLFWWaylandBufferPair; diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 6d7db296b..934bb900e 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -817,14 +817,13 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { - if (window->wl.title) - free(window->wl.title); + if (window->wl.title) free(window->wl.title); // Wayland cannot handle requests larger than ~8200 bytes. Sending // one causes an abort(). Since titles this large are meaningless anyway // ensure they do not happen. window->wl.title = utf_8_strndup(title, 2048); - if (window->wl.xdg.toplevel) - xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title); + if (window->wl.xdg.toplevel) xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title); + if (window->wl.decorations.top.surface) change_csd_title(window); } void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,