wip: add --layer=shell for menu bars

This commit is contained in:
Aleksei Gmitron 2026-06-11 09:28:02 +04:00
parent c79bba89ff
commit 511cb7b0b9
8 changed files with 15 additions and 13 deletions

View file

@ -2698,13 +2698,11 @@ _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig
// See: https://stackoverflow.com/questions/4982584/how-do-i-draw-the-desktop-on-mac-os-x/4982619#4982619
level = kCGDesktopWindowLevel;
break;
case GLFW_LAYER_SHELL_DESKTOP_SHELL: level = kCGBackstopMenuLevel; break;
case GLFW_LAYER_SHELL_OVERLAY: case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_PANEL: level = NSNormalWindowLevel - 1; break;
case GLFW_LAYER_SHELL_TOP: level--; break;
}
if (config.use_physical_screen_frame && config.type == GLFW_LAYER_SHELL_OVERLAY && config.edge == GLFW_EDGE_TOP) {
level = NSMainMenuWindowLevel + 1;
}
if (config.type != GLFW_LAYER_SHELL_BACKGROUND && config.edge != GLFW_EDGE_CENTER) {
double panel_height = spacing_y + ysz / yscale, panel_width = spacing_x + xsz / xscale;
switch (config.edge) {

2
glfw/glfw3.h vendored
View file

@ -1349,7 +1349,7 @@ typedef struct GLFWkeyevent
bool fake_event_on_focus_change;
} GLFWkeyevent;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_DESKTOP_SHELL, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE, GLFW_EDGE_CENTER_SIZED } GLFWEdge;

3
glfw/wl_window.c vendored
View file

@ -1020,7 +1020,7 @@ get_layer_shell_layer(const _GLFWwindow *window) {
case GLFW_LAYER_SHELL_BACKGROUND: case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_PANEL: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; break;
case GLFW_LAYER_SHELL_TOP: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; break;
case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
case GLFW_LAYER_SHELL_DESKTOP_SHELL: case GLFW_LAYER_SHELL_OVERLAY: which_layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; break;
}
return which_layer;
}
@ -1043,6 +1043,7 @@ layer_set_properties(const _GLFWwindow *window, bool during_creation, uint32_t w
case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_BACKGROUND: exclusive_zone = -1; break;
case GLFW_LAYER_SHELL_TOP:
case GLFW_LAYER_SHELL_DESKTOP_SHELL:
case GLFW_LAYER_SHELL_OVERLAY:
case GLFW_LAYER_SHELL_PANEL:
switch (config.edge) {

4
glfw/x11_window.c vendored
View file

@ -644,7 +644,7 @@ calculate_layer_geometry(_GLFWwindow *window) {
double xsz = config.x_size_in_pixels ? (unsigned)(config.x_size_in_pixels * xscale) : (cell_width * config.x_size_in_cells);
double ysz = config.y_size_in_pixels ? (unsigned)(config.y_size_in_pixels * yscale) : (cell_height * config.y_size_in_cells);
ans.width = (int)(1. + spacing_x + xsz); ans.height = (int)(1. + spacing_y + ysz);
GeometryRect m = config.type == GLFW_LAYER_SHELL_TOP || config.type == GLFW_LAYER_SHELL_OVERLAY ? mg.workarea : mg.full;
GeometryRect m = config.type == GLFW_LAYER_SHELL_TOP || config.type == GLFW_LAYER_SHELL_DESKTOP_SHELL || config.type == GLFW_LAYER_SHELL_OVERLAY ? mg.workarea : mg.full;
static const struct {
unsigned left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x;
} s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
@ -762,7 +762,7 @@ update_wm_hints(_GLFWwindow *window, const WindowGeometry *wg, const _GLFWwndcon
// i3 does not support NET_WM_STATE_BELOW but panels work without it
if (_glfw.x11.NET_WM_STATE_BELOW) { S(NET_WM_STATE_BELOW); }
break;
case GLFW_LAYER_SHELL_TOP: case GLFW_LAYER_SHELL_OVERLAY: S(NET_WM_STATE_ABOVE); break;
case GLFW_LAYER_SHELL_TOP: case GLFW_LAYER_SHELL_DESKTOP_SHELL: case GLFW_LAYER_SHELL_OVERLAY: S(NET_WM_STATE_ABOVE); break;
}
#undef S
} else if (wndconfig) {

View file

@ -26,6 +26,7 @@ from kitty.fast_data_types import (
GLFW_LAYER_SHELL_BACKGROUND,
GLFW_LAYER_SHELL_OVERLAY,
GLFW_LAYER_SHELL_PANEL,
GLFW_LAYER_SHELL_DESKTOP_SHELL,
GLFW_LAYER_SHELL_TOP,
layer_shell_config_for_os_window,
set_layer_shell_config,
@ -69,6 +70,7 @@ def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
'background': GLFW_LAYER_SHELL_BACKGROUND,
'bottom': GLFW_LAYER_SHELL_PANEL,
'top': GLFW_LAYER_SHELL_TOP,
'shell': GLFW_LAYER_SHELL_DESKTOP_SHELL,
'overlay': GLFW_LAYER_SHELL_OVERLAY
}.get(opts.layer, GLFW_LAYER_SHELL_PANEL)
ltype = GLFW_LAYER_SHELL_BACKGROUND if opts.edge == 'background' else ltype

2
kitty/glfw-wrapper.h generated
View file

@ -1077,7 +1077,7 @@ typedef struct GLFWkeyevent
bool fake_event_on_focus_change;
} GLFWkeyevent;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL, GLFW_LAYER_SHELL_TOP, GLFW_LAYER_SHELL_DESKTOP_SHELL, GLFW_LAYER_SHELL_OVERLAY } GLFWLayerShellType;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_CENTER, GLFW_EDGE_NONE, GLFW_EDGE_CENTER_SIZED } GLFWEdge;

View file

@ -1372,7 +1372,7 @@ toggle_fullscreen_for_os_window(OSWindow *w) {
if (!prev) return false;
GLFWLayerShellConfig lsc;
memcpy(&lsc, prev, sizeof(lsc));
if (prev->type == GLFW_LAYER_SHELL_OVERLAY || prev->type == GLFW_LAYER_SHELL_TOP) {
if (prev->type == GLFW_LAYER_SHELL_OVERLAY || prev->type == GLFW_LAYER_SHELL_DESKTOP_SHELL || prev->type == GLFW_LAYER_SHELL_TOP) {
if (prev->was_toggled_to_fullscreen) {
lsc.edge = prev->previous.edge;
lsc.requested_bottom_margin = prev->previous.requested_bottom_margin;
@ -3262,7 +3262,7 @@ init_glfw(PyObject *m) {
ADDC(GLFW_REPEAT);
ADDC(true); ADDC(false);
ADDC(GLFW_PRIMARY_SELECTION); ADDC(GLFW_CLIPBOARD);
ADDC(GLFW_LAYER_SHELL_NONE); ADDC(GLFW_LAYER_SHELL_PANEL); ADDC(GLFW_LAYER_SHELL_BACKGROUND); ADDC(GLFW_LAYER_SHELL_TOP); ADDC(GLFW_LAYER_SHELL_OVERLAY);
ADDC(GLFW_LAYER_SHELL_NONE); ADDC(GLFW_LAYER_SHELL_PANEL); ADDC(GLFW_LAYER_SHELL_BACKGROUND); ADDC(GLFW_LAYER_SHELL_TOP); ADDC(GLFW_LAYER_SHELL_DESKTOP_SHELL); ADDC(GLFW_LAYER_SHELL_OVERLAY);
ADDC(GLFW_FOCUS_NOT_ALLOWED); ADDC(GLFW_FOCUS_EXCLUSIVE); ADDC(GLFW_FOCUS_ON_DEMAND);
ADDC(GLFW_EDGE_TOP); ADDC(GLFW_EDGE_BOTTOM); ADDC(GLFW_EDGE_LEFT); ADDC(GLFW_EDGE_RIGHT); ADDC(GLFW_EDGE_CENTER); ADDC(GLFW_EDGE_NONE);
ADDC(GLFW_EDGE_CENTER_SIZED);

View file

@ -639,19 +639,20 @@ that the panel is centered instead of in the top left corner and the margins hav
--layer
choices=background,bottom,top,overlay
choices=background,bottom,top,shell,overlay
default={layer}
On a Wayland compositor that supports the wlr layer shell protocol, specifies the layer
on which the panel should be drawn. This parameter is ignored and set to
:code:`background` if :option:`--edge` is set to :code:`background`. On macOS, maps
these to appropriate NSWindow *levels*.
these to appropriate NSWindow *levels*. On macOS, :code:`shell` places the panel
above normal application windows but below native system UI such as the menu bar.
--use-physical-screen-frame
type=bool-set
default={use_physical_screen_frame}
On macOS, use the physical screen frame rather than the visible frame when placing the panel.
This allows top overlay panels to draw over the native menu bar. Ignored on other platforms.
This allows panels to draw in areas reserved for the native menu bar or dock. Ignored on other platforms.
--config -c