Merge branch 'more_panel_options' of https://github.com/robin-carlier/kitty

This commit is contained in:
Kovid Goyal 2024-11-25 11:30:34 +05:30
commit b522faa875
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
7 changed files with 171 additions and 28 deletions

13
glfw/glfw3.h vendored
View file

@ -1300,9 +1300,9 @@ typedef struct GLFWkeyevent
bool fake_event_on_focus_change;
} GLFWkeyevent;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL } GLFWLayerShellType;
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_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT } GLFWEdge;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_NONE } GLFWEdge;
typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAND} GLFWFocusPolicy;
@ -1311,7 +1311,14 @@ typedef struct GLFWLayerShellConfig {
GLFWEdge edge;
char output_name[64];
GLFWFocusPolicy focus_policy;
unsigned size_in_cells;
unsigned x_size_in_cells;
unsigned y_size_in_cells;
unsigned requested_top_margin;
unsigned requested_left_margin;
unsigned requested_bottom_margin;
unsigned requested_right_margin;
int requested_exclusive_zone;
unsigned override_exclusive_zone;
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
} GLFWLayerShellConfig;

31
glfw/wl_window.c vendored
View file

@ -964,7 +964,7 @@ find_output_by_name(const char* name) {
static void
layer_set_properties(_GLFWwindow *window) {
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 = -1;
int exclusive_zone = window->wl.layer_shell.config.requested_exclusive_zone;
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;
@ -973,28 +973,36 @@ layer_set_properties(_GLFWwindow *window) {
}
int panel_width = 0, panel_height = 0;
switch (window->wl.layer_shell.config.type) {
case GLFW_LAYER_SHELL_BACKGROUND: break; case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_NONE: break;
case GLFW_LAYER_SHELL_BACKGROUND: exclusive_zone = -1; break;
case GLFW_LAYER_SHELL_TOP:
case GLFW_LAYER_SHELL_OVERLAY:
case GLFW_LAYER_SHELL_PANEL:
switch (window->wl.layer_shell.config.edge) {
case GLFW_EDGE_TOP:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
panel_height = window->wl.height;
exclusive_zone = window->wl.height;
if (!window->wl.layer_shell.config.override_exclusive_zone) exclusive_zone = window->wl.height;
break;
case GLFW_EDGE_BOTTOM:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
panel_height = window->wl.height;
exclusive_zone = window->wl.height;
if (!window->wl.layer_shell.config.override_exclusive_zone) exclusive_zone = window->wl.height;
break;
case GLFW_EDGE_LEFT:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
panel_width = window->wl.width;
exclusive_zone = window->wl.width;
if (!window->wl.layer_shell.config.override_exclusive_zone) exclusive_zone = window->wl.width;
break;
case GLFW_EDGE_RIGHT:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
panel_width = window->wl.width;
exclusive_zone = window->wl.width;
if (!window->wl.layer_shell.config.override_exclusive_zone) exclusive_zone = window->wl.width;
break;
case GLFW_EDGE_NONE:
which_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; // None is anchored to "top left"
panel_width = window->wl.width;
panel_height = window->wl.height;
break;
}
}
@ -1004,7 +1012,7 @@ layer_set_properties(_GLFWwindow *window) {
debug("Compositor will be informed that layer size: %dx%d viewport: %dx%d at next surface commit\n", panel_width, panel_height, window->wl.width, window->wl.height);
zwlr_layer_surface_v1_set_anchor(surface, which_anchor);
zwlr_layer_surface_v1_set_exclusive_zone(surface, exclusive_zone);
zwlr_layer_surface_v1_set_margin(surface, 0, 0, 0, 0);
zwlr_layer_surface_v1_set_margin(surface, window->wl.layer_shell.config.requested_top_margin, window->wl.layer_shell.config.requested_right_margin, window->wl.layer_shell.config.requested_bottom_margin, window->wl.layer_shell.config.requested_left_margin);
zwlr_layer_surface_v1_set_keyboard_interactivity(surface, focus_policy);
#undef surface
}
@ -1057,8 +1065,13 @@ create_layer_shell_surface(_GLFWwindow *window) {
}
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;
if (window->wl.layer_shell.config.type == GLFW_LAYER_SHELL_PANEL) which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
enum zwlr_layer_shell_v1_layer which_layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; // Default to background
switch (window->wl.layer_shell.config.type) {
case GLFW_LAYER_SHELL_BACKGROUND: break; 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;
}
#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");

View file

@ -12,8 +12,14 @@
GLFW_EDGE_LEFT,
GLFW_EDGE_RIGHT,
GLFW_EDGE_TOP,
GLFW_EDGE_NONE,
GLFW_LAYER_SHELL_BACKGROUND,
GLFW_LAYER_SHELL_PANEL,
GLFW_LAYER_SHELL_TOP,
GLFW_LAYER_SHELL_OVERLAY,
GLFW_FOCUS_NOT_ALLOWED,
GLFW_FOCUS_EXCLUSIVE,
GLFW_FOCUS_ON_DEMAND,
glfw_primary_monitor_size,
make_x11_window_a_dock_window,
)
@ -22,14 +28,48 @@
from kitty.typing import EdgeLiteral
OPTIONS = r'''
--lines --columns
--lines
type=int
default=1
The number of lines shown in the panel if horizontal otherwise the number of columns shown in the panel. Ignored for background panels.
The number of lines shown in the panel. Ignored for background and vertical panels.
--columns
type=int
default=1
The number of columns shown in the panel. Ignored for background and horizontal panels.
--margin-top
type=int
default=0
Request a given top margin to the compositor.
Only works on a Wayland compositor that supports the wlr layer shell protocol.
--margin-left
type=int
default=0
Request a given left margin to the compositor.
Only works on a Wayland compositor that supports the wlr layer shell protocol.
--margin-bottom
type=int
default=0
Request a given bottom margin to the compositor.
Only works on a Wayland compositor that supports the wlr layer shell protocol.
--margin-right
type=int
default=0
Request a given right margin to the compositor.
Only works on a Wayland compositor that supports the wlr layer shell protocol.
--edge
choices=top,bottom,left,right,background
choices=top,bottom,left,right,background,none
default=top
Which edge of the screen to place the panel on. Note that some window managers
(such as i3) do not support placing docked windows on the left and right edges.
@ -37,6 +77,16 @@
is only supported on Wayland, not X11 and note that when using sway if you set
a background in your sway config it will cover the background drawn using this
kitten.
The value :code:`none` anchors the panel to the top left corner by default
and the panel should be placed using margins parameters.
--layer
choices=background,bottom,top,overlay
default=bottom
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`.
--config -c
@ -68,6 +118,29 @@
Set the name part of the :italic:`WM_CLASS` property (defaults to using the value from :option:`{appname} --class`)
--focus-policy
choices=not-allowed,exclusive,on-demand
default=not-allowed
On a Wayland compositor that supports the wlr layer shell protocol, specify the focus policy for keyboard
interactivity with the panel. Please refer to the wlr layer shell protocol documentation for more details.
--exclusive-zone
type=int
default=-1
On a Wayland compositor that supports the wlr layer shell protocol, request a given exclusive zone for the panel.
Please refer to the wlr layer shell documentation for more details on the meaning of exclusive and its value.
If :option:`--edge` is set to anything else than :code:`none`, this flag will not have any effect unless
the flag :option:`--override-exclusive-zone` is also set.
If :option:`--edge` is set to :code:`background`, this option has no effect.
--override-exclusive-zone
type=bool-set
On a Wayland compositor that supports the wlr layer shell protocol, override the default exclusive zone.
This has effect only if :option:`--edge` is set to :code:`top`, :code:`left`, :code:`bottom` or :code:`right`.
--debug-rendering
type=bool-set
For internal debugging use.
@ -150,9 +223,25 @@ def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y:
def layer_shell_config(opts: PanelCLIOptions) -> LayerShellConfig:
ltype = GLFW_LAYER_SHELL_BACKGROUND if opts.edge == 'background' else GLFW_LAYER_SHELL_PANEL
edge = {'top': GLFW_EDGE_TOP, 'bottom': GLFW_EDGE_BOTTOM, 'left': GLFW_EDGE_LEFT, 'right': GLFW_EDGE_RIGHT}.get(opts.edge, GLFW_EDGE_TOP)
return LayerShellConfig(type=ltype, edge=edge, size_in_cells=max(1, opts.lines), output_name=opts.output_name or '')
ltype = {'background': GLFW_LAYER_SHELL_BACKGROUND,
'bottom': GLFW_LAYER_SHELL_PANEL,
'top': GLFW_LAYER_SHELL_TOP,
'overlay': GLFW_LAYER_SHELL_OVERLAY}.get(opts.layer, GLFW_LAYER_SHELL_PANEL)
ltype = GLFW_LAYER_SHELL_BACKGROUND if opts.edge == 'background' else ltype
edge = {'top': GLFW_EDGE_TOP, 'bottom': GLFW_EDGE_BOTTOM, 'left': GLFW_EDGE_LEFT, 'right': GLFW_EDGE_RIGHT, 'none': GLFW_EDGE_NONE}.get(opts.edge, GLFW_EDGE_TOP)
focus_policy = {'not-allowed': GLFW_FOCUS_NOT_ALLOWED, 'exclusive': GLFW_FOCUS_EXCLUSIVE, 'on-demand': GLFW_FOCUS_ON_DEMAND}.get(opts.focus_policy, GLFW_FOCUS_NOT_ALLOWED);
return LayerShellConfig(type=ltype,
edge=edge,
x_size_in_cells=max(1, opts.columns),
y_size_in_cells=max(1, opts.lines),
requested_top_margin=max(0, opts.margin_top),
requested_left_margin=max(0, opts.margin_left),
requested_bottom_margin=max(0, opts.margin_bottom),
requested_right_margin=max(0, opts.margin_right),
focus_policy=focus_policy,
requested_exclusive_zone=opts.exclusive_zone,
override_exclusive_zone=opts.override_exclusive_zone,
output_name=opts.output_name or '')
def main(sys_args: List[str]) -> None:

View file

@ -14,11 +14,14 @@ from kitty.typing import EdgeLiteral, NotRequired, ReadableBuffer, WriteableBuff
# Constants {{{
GLFW_LAYER_SHELL_NONE: int
GLFW_LAYER_SHELL_PANEL: int
GLFW_LAYER_SHELL_TOP: int
GLFW_LAYER_SHELL_OVERLAY: int
GLFW_LAYER_SHELL_BACKGROUND: int
GLFW_EDGE_TOP: int
GLFW_EDGE_BOTTOM: int
GLFW_EDGE_LEFT: int
GLFW_EDGE_RIGHT: int
GLFW_EDGE_NONE: int
GLFW_FOCUS_NOT_ALLOWED: int
GLFW_FOCUS_EXCLUSIVE: int
GLFW_FOCUS_ON_DEMAND: int

13
kitty/glfw-wrapper.h generated
View file

@ -1038,9 +1038,9 @@ typedef struct GLFWkeyevent
bool fake_event_on_focus_change;
} GLFWkeyevent;
typedef enum { GLFW_LAYER_SHELL_NONE, GLFW_LAYER_SHELL_BACKGROUND, GLFW_LAYER_SHELL_PANEL } GLFWLayerShellType;
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_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT } GLFWEdge;
typedef enum { GLFW_EDGE_TOP, GLFW_EDGE_BOTTOM, GLFW_EDGE_LEFT, GLFW_EDGE_RIGHT, GLFW_EDGE_NONE } GLFWEdge;
typedef enum { GLFW_FOCUS_NOT_ALLOWED, GLFW_FOCUS_EXCLUSIVE, GLFW_FOCUS_ON_DEMAND} GLFWFocusPolicy;
@ -1049,7 +1049,14 @@ typedef struct GLFWLayerShellConfig {
GLFWEdge edge;
char output_name[64];
GLFWFocusPolicy focus_policy;
unsigned size_in_cells;
unsigned x_size_in_cells;
unsigned y_size_in_cells;
unsigned requested_top_margin;
unsigned requested_left_margin;
unsigned requested_bottom_margin;
unsigned requested_right_margin;
int requested_exclusive_zone;
unsigned override_exclusive_zone;
void (*size_callback)(GLFWwindow *window, const struct GLFWLayerShellConfig *config, unsigned monitor_width, unsigned monitor_height, uint32_t *width, uint32_t *height);
} GLFWLayerShellConfig;

View file

@ -1036,6 +1036,7 @@ edge_spacing(GLFWEdge which) {
case GLFW_EDGE_BOTTOM: edge = "bottom"; break;
case GLFW_EDGE_LEFT: edge = "left"; break;
case GLFW_EDGE_RIGHT: edge = "right"; break;
case GLFW_EDGE_NONE: edge = "left"; break; // GLFW_EDGE_NONE is considered as "top left"
}
if (!edge_spacing_func) {
log_error("Attempt to call edge_spacing() without first setting edge_spacing_func");
@ -1066,14 +1067,23 @@ calculate_layer_shell_window_size(
if (!*height) *height = monitor_height;
double spacing = edge_spacing(GLFW_EDGE_LEFT) + edge_spacing(GLFW_EDGE_RIGHT);
spacing *= xdpi / 72.;
spacing += (fonts_data->cell_width * config->size_in_cells) / xscale;
spacing += (fonts_data->cell_width * config->x_size_in_cells) / xscale;
*width = (uint32_t)(1. + spacing);
} else {
} else if (config->edge == GLFW_EDGE_TOP || config->edge == GLFW_EDGE_BOTTOM) {
if (!*width) *width = monitor_width;
double spacing = edge_spacing(GLFW_EDGE_TOP) + edge_spacing(GLFW_EDGE_BOTTOM);
spacing *= ydpi / 72.;
spacing += (fonts_data->cell_height * config->size_in_cells) / yscale;
spacing += (fonts_data->cell_height * config->y_size_in_cells) / yscale;
*height = (uint32_t)(1. + spacing);
} else {
double spacing_x = edge_spacing(GLFW_EDGE_LEFT);
spacing_x *= xdpi / 72.;
spacing_x += (fonts_data->cell_width * config->x_size_in_cells) / xscale;
double spacing_y = edge_spacing(GLFW_EDGE_TOP);
spacing_y *= ydpi / 72.;
spacing_y += (fonts_data->cell_height * config->y_size_in_cells) / yscale;
*width = (uint32_t)(1. + spacing_x);
*height = (uint32_t)(1. + spacing_y);
}
}
@ -1085,7 +1095,14 @@ translate_layer_shell_config(PyObject *p, GLFWLayerShellConfig *ans) {
A(type, PyLong_Check, PyLong_AsLong);
A(edge, PyLong_Check, PyLong_AsLong);
A(focus_policy, PyLong_Check, PyLong_AsLong);
A(size_in_cells, PyLong_Check, PyLong_AsLong);
A(x_size_in_cells, PyLong_Check, PyLong_AsLong);
A(y_size_in_cells, PyLong_Check, PyLong_AsLong);
A(requested_top_margin, PyLong_Check, PyLong_AsLong);
A(requested_left_margin, PyLong_Check, PyLong_AsLong);
A(requested_bottom_margin, PyLong_Check, PyLong_AsLong);
A(requested_right_margin, PyLong_Check, PyLong_AsLong);
A(requested_exclusive_zone, PyLong_Check, PyLong_AsLong);
A(override_exclusive_zone, PyBool_Check, PyLong_AsLong);
#undef A
#define A(attr) { \
RAII_PyObject(attr, PyObject_GetAttrString(p, #attr)); if (attr == NULL) return false; \
@ -2358,9 +2375,9 @@ 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_NONE); ADDC(GLFW_LAYER_SHELL_PANEL); ADDC(GLFW_LAYER_SHELL_BACKGROUND); ADDC(GLFW_LAYER_SHELL_TOP); 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_TOP); ADDC(GLFW_EDGE_BOTTOM); ADDC(GLFW_EDGE_LEFT); ADDC(GLFW_EDGE_RIGHT); ADDC(GLFW_EDGE_NONE)
ADDC(GLFW_COLOR_SCHEME_NO_PREFERENCE); ADDC(GLFW_COLOR_SCHEME_DARK); ADDC(GLFW_COLOR_SCHEME_LIGHT);
/* start glfw functional keys (auto generated by gen-key-constants.py do not edit) */

View file

@ -72,7 +72,14 @@ class LayerShellConfig(NamedTuple):
edge: int = 0
focus_policy: int = 0
output_name: str = ''
size_in_cells: int = 0
x_size_in_cells: int = 0
y_size_in_cells: int = 0
requested_top_margin: int = 0
requested_left_margin: int = 0
requested_bottom_margin: int = 0
requested_right_margin: int = 0
requested_exclusive_zone: int = -1
override_exclusive_zone: bool = False
def mod_to_names(mods: int, has_kitty_mod: bool = False, kitty_mod: int = 0) -> Iterator[str]: