mirror of
https://github.com/kovidgoyal/kitty.git
synced 2024-11-10 13:04:03 +03:00
Refactor the rendering of CSD on Wayland
This commit is contained in:
parent
1e6fe7785a
commit
aeb82e7fb0
@ -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",
|
||||
|
200
glfw/wl_client_side_decorations.c
vendored
Normal file
200
glfw/wl_client_side_decorations.c
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* wl_client_side_decorations.c
|
||||
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "wl_client_side_decorations.h"
|
||||
|
||||
#include "backend_utils.h"
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
14
glfw/wl_client_side_decorations.h
vendored
Normal file
14
glfw/wl_client_side_decorations.h
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* 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);
|
87
glfw/wl_init.c
vendored
87
glfw/wl_init.c
vendored
@ -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;
|
||||
|
58
glfw/wl_platform.h
vendored
58
glfw/wl_platform.h
vendored
@ -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
|
||||
|
135
glfw/wl_window.c
vendored
135
glfw/wl_window.c
vendored
@ -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 <stdio.h>
|
||||
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user