Finish glfw side support for layer shell
This commit is contained in:
parent
0641ec2d89
commit
fe5ccc144b
6 changed files with 147 additions and 14 deletions
|
|
@ -314,7 +314,7 @@ def generate_wrappers(glfw_header: str) -> None:
|
|||
void glfwWaylandRunWithActivationToken(GLFWwindow *handle, GLFWactivationcallback cb, void *cb_data)
|
||||
bool glfwWaylandSetTitlebarColor(GLFWwindow *handle, uint32_t color, bool use_system_color)
|
||||
void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle)
|
||||
GLFWLayerShellConfig* glfwWaylandSetupLayerShellForNextWindow(void)
|
||||
void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c)
|
||||
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
||||
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
|
||||
|
|
|
|||
8
glfw/glfw3.h
vendored
8
glfw/glfw3.h
vendored
|
|
@ -1294,10 +1294,16 @@ typedef struct GLFWkeyevent
|
|||
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL } GLFWLayerShellType;
|
||||
|
||||
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT } GLFWEdge;
|
||||
|
||||
typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAND} GLFWFocusPolicy;
|
||||
|
||||
typedef struct GLFWLayerShellConfig {
|
||||
GLFWLayerShellType type;
|
||||
GLFWEdge edge;
|
||||
const char *output_name;
|
||||
const char *edge;
|
||||
GLFWFocusPolicy focus_policy;
|
||||
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, float scale, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
|
||||
} GLFWLayerShellConfig;
|
||||
|
||||
/*! @brief The function pointer type for error callbacks.
|
||||
|
|
|
|||
4
glfw/wl_init.c
vendored
4
glfw/wl_init.c
vendored
|
|
@ -739,7 +739,7 @@ static void registryHandleGlobal(void* data UNUSED,
|
|||
_glfw.wl.org_kde_kwin_blur_manager = wl_registry_bind(registry, name, &org_kde_kwin_blur_manager_interface, 1);
|
||||
}
|
||||
else if (is(zwlr_layer_shell_v1)) {
|
||||
if (version > 3) {
|
||||
if (version >= 4) {
|
||||
_glfw.wl.zwlr_layer_shell_v1_version = version;
|
||||
_glfw.wl.zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, version);
|
||||
}
|
||||
|
|
@ -986,6 +986,8 @@ void _glfwPlatformTerminate(void)
|
|||
wp_fractional_scale_manager_v1_destroy(_glfw.wl.wp_fractional_scale_manager_v1);
|
||||
if (_glfw.wl.org_kde_kwin_blur_manager)
|
||||
org_kde_kwin_blur_manager_destroy(_glfw.wl.org_kde_kwin_blur_manager);
|
||||
if (_glfw.wl.zwlr_layer_shell_v1)
|
||||
zwlr_layer_shell_v1_destroy(_glfw.wl.zwlr_layer_shell_v1);
|
||||
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
|
|
|
|||
4
glfw/wl_platform.h
vendored
4
glfw/wl_platform.h
vendored
|
|
@ -169,6 +169,10 @@ typedef struct _GLFWwindowWayland
|
|||
struct wp_viewport *wp_viewport;
|
||||
struct org_kde_kwin_blur *org_kde_kwin_blur;
|
||||
bool has_blur;
|
||||
struct {
|
||||
GLFWLayerShellConfig config;
|
||||
struct zwlr_layer_surface_v1* zwlr_layer_surface_v1;
|
||||
} layer_shell;
|
||||
|
||||
_GLFWcursor* currentCursor;
|
||||
double cursorPosX, cursorPosY, allCursorPosX, allCursorPosY;
|
||||
|
|
|
|||
133
glfw/wl_window.c
vendored
133
glfw/wl_window.c
vendored
|
|
@ -45,6 +45,9 @@
|
|||
|
||||
static GLFWLayerShellConfig layer_shell_config_for_next_window = {0};
|
||||
|
||||
static bool
|
||||
is_layer_shell(_GLFWwindow *window) { return window->wl.layer_shell.config.type != GLFW_LAYER_SHELL_NONE; }
|
||||
|
||||
static void
|
||||
activation_token_done(void *data, struct xdg_activation_token_v1 *xdg_token, const char *token) {
|
||||
for (size_t i = 0; i < _glfw.wl.activation_requests.sz; i++) {
|
||||
|
|
@ -312,6 +315,14 @@ commit_window_surface_if_safe(_GLFWwindow *window) {
|
|||
|
||||
static void
|
||||
update_regions(_GLFWwindow* window) {
|
||||
if (is_layer_shell(window) && window->wl.layer_shell.config.type == GLFW_LAYER_SHELL_PANEL) {
|
||||
int32_t exclusive_zone = 1;
|
||||
switch (window->wl.layer_shell.config.edge) {
|
||||
case GLFW_EDGE_TOP: case GLFW_EDGE_BOTTOM: exclusive_zone = window->wl.height; break;
|
||||
case GLFW_EDGE_LEFT: case GLFW_EDGE_RIGHT: exclusive_zone = window->wl.width; break;
|
||||
}
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(window->wl.layer_shell.zwlr_layer_surface_v1, exclusive_zone);
|
||||
}
|
||||
if (window->wl.transparent && !window->wl.org_kde_kwin_blur) return;
|
||||
struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
|
||||
if (!region) return;
|
||||
|
|
@ -766,9 +777,110 @@ setXdgDecorations(_GLFWwindow* window)
|
|||
}
|
||||
}
|
||||
|
||||
static struct wl_output*
|
||||
find_output_by_name(const char* name) {
|
||||
if (!name) return NULL;
|
||||
int count;
|
||||
GLFWmonitor** monitors = glfwGetMonitors(&count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
_GLFWmonitor *m = (_GLFWmonitor*)monitors + i;
|
||||
if (strcmp(m->name, name) == 0) {
|
||||
return m->wl.output;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
layer_surface_handle_configure(void* data, struct zwlr_layer_surface_v1* surface, uint32_t serial, uint32_t width, uint32_t height) {
|
||||
debug("Layer shell configure event: width: %u height: %u\n", width, height);
|
||||
_GLFWwindow* window = data;
|
||||
unsigned monitor_width = 0, monitor_height = 0;
|
||||
if (window->wl.monitorsCount) {
|
||||
_GLFWmonitor *m = window->wl.monitors[0];
|
||||
monitor_width = m->currentMode.width; monitor_height = m->currentMode.height;
|
||||
}
|
||||
window->wl.layer_shell.config.size_callback(
|
||||
(GLFWwindow*)window, &window->wl.layer_shell.config, _glfwWaylandWindowScale(window), monitor_width, monitor_height,
|
||||
&width, &height);
|
||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||
if ((int)width != window->wl.width || (int)height != window->wl.height) {
|
||||
debug("Layer shell size changed to %ux%u in layer_surface_handle_configure\n", width, height);
|
||||
_glfwInputWindowSize(window, width, height);
|
||||
window->wl.width = width; window->wl.height = height;
|
||||
resizeFramebuffer(window);
|
||||
}
|
||||
commit_window_surface_if_safe(window);
|
||||
}
|
||||
|
||||
static void
|
||||
layer_surface_handle_close_requested(void* data, struct zwlr_layer_surface_v1* surface UNUSED) {
|
||||
_GLFWwindow* window = data;
|
||||
_glfwInputWindowCloseRequest(window);
|
||||
}
|
||||
|
||||
static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listener = {
|
||||
.configure=layer_surface_handle_configure,
|
||||
.closed=layer_surface_handle_close_requested,
|
||||
};
|
||||
|
||||
static bool
|
||||
createXdgSurface(_GLFWwindow* window)
|
||||
create_layer_shell_surface(_GLFWwindow *window) {
|
||||
if (!_glfw.wl.zwlr_layer_shell_v1) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: wlr-layer-shell protocol unsupported by compositor");
|
||||
return false;
|
||||
}
|
||||
window->decorated = false; // shell windows must not have decorations
|
||||
struct wl_output *wl_output = find_output_by_name(window->wl.layer_shell.config.output_name);
|
||||
enum zwlr_layer_shell_v1_layer which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
|
||||
enum zwlr_layer_surface_v1_anchor which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||
int exclusive_zone = 0;
|
||||
enum zwlr_layer_surface_v1_keyboard_interactivity focus_policy = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||
switch(window->wl.layer_shell.config.focus_policy) {
|
||||
case GLFW_FOCUS_NOT_ALLOWED: focus_policy = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE; break;
|
||||
case GLFW_FOCUS_EXCLUSIVE: focus_policy = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; break;
|
||||
case GLFW_FOCUS_ON_DEMAND: focus_policy = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND; break;
|
||||
}
|
||||
switch (window->wl.layer_shell.config.type) {
|
||||
case GLFW_LAYER_SHELL_BACKGROUND:
|
||||
exclusive_zone = -1;
|
||||
which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; break;
|
||||
case GLFW_LAYER_SHELL_PANEL:
|
||||
exclusive_zone = 1; // we dont know height of window otherwise this should be height
|
||||
which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; break;
|
||||
switch (window->wl.layer_shell.config.edge) {
|
||||
case GLFW_EDGE_TOP: which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; break;
|
||||
case GLFW_EDGE_BOTTOM: which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; break;
|
||||
case GLFW_EDGE_LEFT: which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT; break;
|
||||
case GLFW_EDGE_RIGHT: which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; break;
|
||||
}
|
||||
case GLFW_LAYER_SHELL_NONE: break;
|
||||
}
|
||||
#define ls window->wl.layer_shell.zwlr_layer_surface_v1
|
||||
ls = zwlr_layer_shell_v1_get_layer_surface(
|
||||
_glfw.wl.zwlr_layer_shell_v1, window->wl.surface, wl_output, which_layer, "kitty");
|
||||
if (!ls) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: layer-surface creation failed");
|
||||
return false;
|
||||
}
|
||||
zwlr_layer_surface_v1_set_size(ls, 0, 0);
|
||||
zwlr_layer_surface_v1_set_anchor(ls, which_anchor);
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(ls, exclusive_zone);
|
||||
zwlr_layer_surface_v1_set_margin(ls, 0, 0, 0, 0);
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(ls, focus_policy);
|
||||
zwlr_layer_surface_v1_add_listener(ls, &zwlr_layer_surface_v1_listener, window);
|
||||
|
||||
wl_surface_commit(window->wl.surface);
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
#undef ls
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
create_window_desktop_surface(_GLFWwindow* window)
|
||||
{
|
||||
if (is_layer_shell(window)) return create_layer_shell_surface(window);
|
||||
|
||||
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
||||
window->wl.surface);
|
||||
if (!window->wl.xdg.surface)
|
||||
|
|
@ -995,13 +1107,14 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
window->wl.layer_shell.config = layer_shell_config_for_next_window;
|
||||
memset(&layer_shell_config_for_next_window, 0, sizeof(layer_shell_config_for_next_window));
|
||||
initialize_csd_metrics(window);
|
||||
window->wl.transparent = fbconfig->transparent;
|
||||
strncpy(window->wl.appId, wndconfig->wl.appId, sizeof(window->wl.appId));
|
||||
window->swaps_disallowed = true;
|
||||
|
||||
if (!createSurface(window, wndconfig))
|
||||
return false;
|
||||
if (!createSurface(window, wndconfig)) return false;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
|
|
@ -1029,7 +1142,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
|
||||
if (wndconfig->visible)
|
||||
{
|
||||
if (!createXdgSurface(window))
|
||||
if (!create_window_desktop_surface(window))
|
||||
return false;
|
||||
|
||||
window->wl.visible = true;
|
||||
|
|
@ -1038,6 +1151,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||
{
|
||||
window->wl.xdg.surface = NULL;
|
||||
window->wl.xdg.toplevel = NULL;
|
||||
window->wl.layer_shell.zwlr_layer_surface_v1 = NULL;
|
||||
window->wl.visible = false;
|
||||
}
|
||||
|
||||
|
|
@ -1073,6 +1187,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||
wp_viewport_destroy(window->wl.wp_viewport);
|
||||
if (window->wl.org_kde_kwin_blur)
|
||||
org_kde_kwin_blur_release(window->wl.org_kde_kwin_blur);
|
||||
if (window->wl.layer_shell.config.output_name) free((void*)window->wl.layer_shell.config.output_name);
|
||||
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
|
|
@ -1270,7 +1385,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
|
|||
{
|
||||
if (!window->wl.visible)
|
||||
{
|
||||
createXdgSurface(window);
|
||||
create_window_desktop_surface(window);
|
||||
window->wl.visible = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2428,8 +2543,8 @@ GLFWAPI void glfwWaylandRedrawCSDWindowTitle(GLFWwindow *handle) {
|
|||
change_csd_title(window);
|
||||
}
|
||||
|
||||
|
||||
GLFWAPI GLFWLayerShellConfig* glfwWaylandSetupLayerShellForNextWindow(void) {
|
||||
memset(&layer_shell_config_for_next_window, 0, sizeof(layer_shell_config_for_next_window));
|
||||
return &layer_shell_config_for_next_window;
|
||||
GLFWAPI void glfwWaylandSetupLayerShellForNextWindow(GLFWLayerShellConfig c) {
|
||||
if (layer_shell_config_for_next_window.output_name) free((void*)layer_shell_config_for_next_window.output_name);
|
||||
layer_shell_config_for_next_window = c;
|
||||
if (layer_shell_config_for_next_window.output_name) layer_shell_config_for_next_window.output_name = strdup(layer_shell_config_for_next_window.output_name);
|
||||
}
|
||||
|
|
|
|||
10
kitty/glfw-wrapper.h
generated
10
kitty/glfw-wrapper.h
generated
|
|
@ -1032,10 +1032,16 @@ typedef struct GLFWkeyevent
|
|||
|
||||
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL } GLFWLayerShellType;
|
||||
|
||||
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT } GLFWEdge;
|
||||
|
||||
typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAND} GLFWFocusPolicy;
|
||||
|
||||
typedef struct GLFWLayerShellConfig {
|
||||
GLFWLayerShellType type;
|
||||
GLFWEdge edge;
|
||||
const char *output_name;
|
||||
const char *edge;
|
||||
GLFWFocusPolicy focus_policy;
|
||||
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, float scale, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
|
||||
} GLFWLayerShellConfig;
|
||||
|
||||
/*! @brief The function pointer type for error callbacks.
|
||||
|
|
@ -2301,7 +2307,7 @@ typedef void (*glfwWaylandRedrawCSDWindowTitle_func)(GLFWwindow*);
|
|||
GFW_EXTERN glfwWaylandRedrawCSDWindowTitle_func glfwWaylandRedrawCSDWindowTitle_impl;
|
||||
#define glfwWaylandRedrawCSDWindowTitle glfwWaylandRedrawCSDWindowTitle_impl
|
||||
|
||||
typedef GLFWLayerShellConfig* (*glfwWaylandSetupLayerShellForNextWindow_func)(void);
|
||||
typedef void (*glfwWaylandSetupLayerShellForNextWindow_func)(GLFWLayerShellConfig);
|
||||
GFW_EXTERN glfwWaylandSetupLayerShellForNextWindow_func glfwWaylandSetupLayerShellForNextWindow_impl;
|
||||
#define glfwWaylandSetupLayerShellForNextWindow glfwWaylandSetupLayerShellForNextWindow_impl
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue