From e844ad6db3e3cf25b49c10ef35e3fbec12a6c626 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 6 May 2020 13:44:32 +0530 Subject: [PATCH] Respect per-window margin/padding in stack layout Also use the margin/padding of the base window for all overlay windows --- kitty/layout/base.py | 46 ++++++++++++++++++++----------------------- kitty/layout/stack.py | 13 +++++------- kitty/window_list.py | 24 ++++++++++++++++------ 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/kitty/layout/base.py b/kitty/layout/base.py index 7a43f80b2..b9bd0c84b 100644 --- a/kitty/layout/base.py +++ b/kitty/layout/base.py @@ -16,7 +16,7 @@ from kitty.fast_data_types import ( ) from kitty.options_stub import Options from kitty.typing import TypedDict, WindowType -from kitty.window_list import WindowList +from kitty.window_list import WindowGroup, WindowList class Borders(NamedTuple): @@ -332,35 +332,32 @@ class Layout: self.blank_rects = [] self.do_layout(all_windows) - def layout_single_window(self, w: WindowType, return_geometry: bool = False, left_align: bool = False) -> Optional[WindowGeometry]: - bw = w.effective_border() if self.must_draw_borders else 0 + def layout_single_window_group(self, wg: WindowGroup, add_blank_rects: bool = True) -> None: + bw = 1 if self.must_draw_borders else 0 xdecoration_pairs = (( - w.effective_padding('left') + w.effective_margin('left', is_single_window=True) + bw, - w.effective_padding('right') + w.effective_margin('right', is_single_window=True) + bw, + wg.decoration('left', border_mult=bw, is_single_window=True), + wg.decoration('right', border_mult=bw, is_single_window=True), ),) ydecoration_pairs = (( - w.effective_padding('top') + w.effective_margin('top', is_single_window=True) + bw, - w.effective_padding('bottom') + w.effective_margin('bottom', is_single_window=True) + bw, + wg.decoration('top', border_mult=bw, is_single_window=True), + wg.decoration('bottom', border_mult=bw, is_single_window=True), ),) - wg = layout_single_window(xdecoration_pairs, ydecoration_pairs, left_align=left_align) - if return_geometry: - return wg - w.set_geometry(wg) - self.blank_rects = list(blank_rects_for_window(wg)) - return None + geom = layout_single_window(xdecoration_pairs, ydecoration_pairs, left_align=lgd.align_top_left) + wg.set_geometry(geom) + if add_blank_rects and wg: + self.blank_rects.extend(blank_rects_for_window(geom)) def xlayout( self, - windows: WindowList, + all_windows: WindowList, bias: Optional[Sequence[float]] = None, start: Optional[int] = None, - size: Optional[int] = None + size: Optional[int] = None, + offset: int = 0 ) -> LayoutDimension: decoration_pairs = tuple( - ( - w.effective_margin('left') + w.effective_border() + w.effective_padding('left'), - w.effective_margin('right') + w.effective_border() + w.effective_padding('right'), - ) for w in windows + (g.decoration('left'), g.decoration('right')) for i, g in + enumerate(all_windows.iter_all_layoutable_groups()) if i >= offset ) if start is None: start = lgd.central.left @@ -370,16 +367,15 @@ class Layout: def ylayout( self, - windows: WindowList, + all_windows: WindowList, bias: Optional[Sequence[float]] = None, start: Optional[int] = None, - size: Optional[int] = None + size: Optional[int] = None, + offset: int = 0 ) -> LayoutDimension: decoration_pairs = tuple( - ( - w.effective_margin('top') + w.effective_border() + w.effective_padding('top'), - w.effective_margin('bottom') + w.effective_border() + w.effective_padding('bottom'), - ) for w in windows + (g.decoration('top'), g.decoration('bottom')) for i, g in + enumerate(all_windows.iter_all_layoutable_groups()) if i >= offset ) if start is None: start = lgd.central.top diff --git a/kitty/layout/stack.py b/kitty/layout/stack.py index a0c04cc6f..8b98029de 100644 --- a/kitty/layout/stack.py +++ b/kitty/layout/stack.py @@ -4,7 +4,7 @@ from kitty.window_list import WindowList -from .base import Layout, blank_rects_for_window, lgd +from .base import Layout class Stack(Layout): @@ -13,10 +13,7 @@ class Stack(Layout): needs_window_borders = False only_active_window_visible = True - def do_layout(self, windows: WindowList) -> None: - for i, w in enumerate(windows.iter_all_layoutable_windows()): - wg = self.layout_single_window(w, left_align=lgd.align_top_left, return_geometry=True) - if wg is not None: - w.set_geometry(wg) - if i == 0: - self.blank_rects = list(blank_rects_for_window(wg)) + def do_layout(self, all_windows: WindowList) -> None: + active_group = all_windows.active_group + for group in all_windows.iter_all_layoutable_groups(): + self.layout_single_window_group(group, add_blank_rects=group is active_group) diff --git a/kitty/window_list.py b/kitty/window_list.py index 0062d8307..ad4aef63c 100644 --- a/kitty/window_list.py +++ b/kitty/window_list.py @@ -10,7 +10,8 @@ from typing import ( Any, Deque, Dict, Generator, Iterator, List, Optional, Tuple, Union ) -from .typing import TabType, WindowType +from .constants import WindowGeometry +from .typing import EdgeLiteral, TabType, WindowType WindowOrId = Union[WindowType, int] group_id_counter = count() @@ -64,6 +65,16 @@ class WindowGroup: 'windows': [w.serialize_state() for w in self.windows] } + def decoration(self, which: EdgeLiteral, border_mult: int = 1, is_single_window: bool = False) -> int: + if not self.windows: + return 0 + w = self.windows[0] + return w.effective_margin(which, is_single_window=is_single_window) + w.effective_border() * border_mult + w.effective_padding(which) + + def set_geometry(self, geom: WindowGeometry) -> None: + for w in self.windows: + w.set_geometry(geom) + class WindowList: @@ -147,9 +158,8 @@ class WindowList: for window in g: yield window, window.id == aw - def iter_all_layoutable_windows(self) -> Generator[WindowType, None, None]: - for g in self.groups: - yield from g + def iter_all_layoutable_groups(self) -> Iterator[WindowGroup]: + return iter(self.groups) def make_previous_group_active(self, which: int = 1, notify: bool = False) -> None: which = max(1, which) @@ -175,7 +185,6 @@ class WindowList: for g in self.groups: if q in g: return g - return None def windows_in_group_of(self, x: WindowOrId) -> Iterator[WindowType]: g = self.group_for_window(x) @@ -198,7 +207,10 @@ class WindowList: return self.id_map[self.groups[self.active_group_idx].base_window_id] def set_active_window_group_for(self, x: WindowOrId) -> None: - q = self.id_map[x] if isinstance(x, int) else x + try: + q = self.id_map[x] if isinstance(x, int) else x + except KeyError: + return for i, group in enumerate(self.groups): if q in group: self.set_active_group_idx(i)