Infrastructure to go from panel CLI opts all the way to wayland layer shell implementation

This commit is contained in:
Kovid Goyal
2024-03-24 13:58:26 +05:30
parent 56978189e0
commit 333ea519ed
10 changed files with 135 additions and 49 deletions

View File

@@ -8,27 +8,34 @@ from typing import Any, Callable, Dict, List, Tuple
from kitty.cli import parse_args
from kitty.cli_stub import PanelCLIOptions
from kitty.constants import appname, is_macos, is_wayland
from kitty.fast_data_types import make_x11_window_a_dock_window
from kitty.os_window_size import WindowSizeData
from kitty.fast_data_types import (
GLFW_EDGE_BOTTOM,
GLFW_EDGE_LEFT,
GLFW_EDGE_RIGHT,
GLFW_EDGE_TOP,
GLFW_LAYER_SHELL_BACKGROUND,
GLFW_LAYER_SHELL_PANEL,
glfw_primary_monitor_size,
make_x11_window_a_dock_window,
)
from kitty.os_window_size import WindowSizeData, edge_spacing
from kitty.types import LayerShellConfig
from kitty.typing import EdgeLiteral
OPTIONS = r'''
--lines
--lines --columns
type=int
default=1
The number of lines shown in the panel (the height of the panel). Applies to horizontal panels.
--columns
type=int
default=20
The number of columns shown in the panel (the width of the panel). Applies to vertical panels.
The number of lines shown in the panel if horizontal otherwise the number of columns shown in the panel. Ignored for background panels.
--edge
choices=top,bottom,left,right
choices=top,bottom,left,right,background
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.
The value :code:`background` means make the panel the "desktop wallpaper". This
is only supported on Wayland, not X11.
--config -c
@@ -42,6 +49,12 @@ Override individual kitty configuration options, can be specified multiple times
Syntax: :italic:`name=value`. For example: :option:`kitty +kitten panel -o` font_size=20
--output-name
On Wayland, the panel can only be displayed on a single monitor (output) at a time. This allows
you to specify which output is used, by name. If not specified the compositor will choose an
output automatically, typically the last output the user interacted with or the primary monitor.
--class
dest=cls
default={appname}-panel
@@ -96,26 +109,17 @@ window_width = window_height = 0
def setup_x11_window(win_id: int) -> None:
if is_wayland():
return
func = globals()[f'create_{args.edge}_strut']
strut = func(win_id, window_width, window_height)
make_x11_window_a_dock_window(win_id, strut)
def initial_window_size_func(opts: WindowSizeData, cached_values: Dict[str, Any]) -> Callable[[int, int, float, float, float, float], Tuple[int, int]]:
from kitty.fast_data_types import glfw_primary_monitor_size
from kitty.typing import EdgeLiteral
def effective_margin(which: EdgeLiteral) -> float:
ans: float = getattr(opts.single_window_margin_width, which)
if ans < 0:
ans = getattr(opts.window_margin_width, which)
return ans
def effective_padding(which: EdgeLiteral) -> float:
ans: float = getattr(opts.single_window_padding_width, which)
if ans < 0:
ans = getattr(opts.window_padding_width, which)
return ans
def es(which: EdgeLiteral) -> float:
return edge_spacing(which, opts)
def initial_window_size(cell_width: int, cell_height: int, dpi_x: float, dpi_y: float, xscale: float, yscale: float) -> Tuple[int, int]:
if not is_macos and not is_wayland():
@@ -125,20 +129,26 @@ def initial_window_size_func(opts: WindowSizeData, cached_values: Dict[str, Any]
monitor_width, monitor_height = glfw_primary_monitor_size()
if args.edge in {'top', 'bottom'}:
spacing = effective_margin('top') + effective_margin('bottom')
spacing += effective_padding('top') + effective_padding('bottom')
spacing = es('top') + es('bottom')
window_height = int(cell_height * args.lines / yscale + (dpi_y / 72) * spacing + 1)
window_width = monitor_width
elif args.edge == 'background':
window_width, window_height = monitor_width, monitor_height
else:
spacing = effective_margin('left') + effective_margin('right')
spacing += effective_padding('left') + effective_padding('right')
window_width = int(cell_width * args.columns / xscale + (dpi_x / 72) * spacing + 1)
spacing = es('left') + es('right')
window_width = int(cell_width * args.lines / xscale + (dpi_x / 72) * spacing + 1)
window_height = monitor_height
return window_width, window_height
return initial_window_size
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 None)
def main(sys_args: List[str]) -> None:
global args
if is_macos or not os.environ.get('DISPLAY'):
@@ -154,10 +164,12 @@ def main(sys_args: List[str]) -> None:
sys.argv.extend(('--name', args.name))
for override in args.override:
sys.argv.extend(('--override', override))
sys.argv.append('--override=linux_display_server=auto')
sys.argv.extend(items)
from kitty.main import main as real_main
from kitty.main import run_app
run_app.cached_values_name = 'panel'
run_app.layer_shell_config = layer_shell_config(args)
run_app.first_window_callback = setup_x11_window
run_app.initial_window_size_func = initial_window_size_func
real_main()