mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Implement resizing semantics based on layout
Still need to do splits layout but all others should be OK
This commit is contained in:
@@ -2427,13 +2427,17 @@ class Boss:
|
||||
self, edges: int, x: float, y: float, window_id: int, cell_width: int, cell_height: int,
|
||||
) -> bool:
|
||||
if (w := self.window_id_map.get(window_id)) and (tab := w.tabref()):
|
||||
horizontal, vertical = tab.current_layout.drag_resize_target_windows(w, x, y, tab.windows)
|
||||
horizontal, width_increases_rightwards, vertical, height_increases_downwards = \
|
||||
tab.current_layout.drag_resize_target_windows(w, x, y, edges, tab.windows)
|
||||
horizontal_allowed = bool(edges & (LEFT_EDGE | RIGHT_EDGE))
|
||||
vertical_allowed = bool(edges & (TOP_EDGE | BOTTOM_EDGE))
|
||||
self.drag_resize_of_window = WindowResizeDrag(
|
||||
is_active=True, horizontal_target_window_id=horizontal.id if horizontal_allowed else 0,
|
||||
vertical_target_window_id=vertical.id if vertical_allowed else 0,
|
||||
cell_width=cell_width, cell_height=cell_height, initial_x=x, initial_y=y)
|
||||
cell_width=cell_width, cell_height=cell_height, initial_x=x, initial_y=y,
|
||||
width_increases_rightwards=width_increases_rightwards,
|
||||
height_increases_downwards=height_increases_downwards,
|
||||
)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -2441,18 +2445,20 @@ class Boss:
|
||||
if not (r := self.drag_resize_of_window):
|
||||
return
|
||||
if h := self.window_id_map.get(r.horizontal_target_window_id):
|
||||
step_x = floor((x - r.initial_x) / r.cell_width)
|
||||
mult = 1 if r.width_increases_rightwards else -1
|
||||
step_x = floor((x - r.initial_x) / r.cell_width) * mult
|
||||
dx = step_x - r.last_step_x
|
||||
if dx != 0:
|
||||
self.resize_layout_window(h, float(dx), True, False)
|
||||
self.drag_resize_of_window = r._replace(last_step_x=step_x)
|
||||
if self.resize_layout_window(h, float(dx), is_horizontal=True) is None:
|
||||
self.drag_resize_of_window = r._replace(last_step_x=step_x)
|
||||
|
||||
if v := self.window_id_map.get(r.vertical_target_window_id):
|
||||
step_y = floor((y - r.initial_y) / r.cell_height)
|
||||
mult = 1 if r.height_increases_downwards else -1
|
||||
step_y = floor((y - r.initial_y) / r.cell_height) * mult
|
||||
dy = step_y - r.last_step_y
|
||||
if dy != 0:
|
||||
self.resize_layout_window(v, float(dy), False, False)
|
||||
self.drag_resize_of_window = r._replace(last_step_y=step_y)
|
||||
if self.resize_layout_window(v, float(dy), is_horizontal=False) is None:
|
||||
self.drag_resize_of_window = r._replace(last_step_y=step_y)
|
||||
|
||||
def drag_resize_end(self) -> None:
|
||||
self.drag_resize_of_window = WindowResizeDrag()
|
||||
|
||||
@@ -7,7 +7,7 @@ from itertools import repeat
|
||||
from typing import Any, Callable, NamedTuple
|
||||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.fast_data_types import Region, get_options, set_active_window, viewport_for_window
|
||||
from kitty.fast_data_types import BOTTOM_EDGE, RIGHT_EDGE, Region, get_options, set_active_window, viewport_for_window
|
||||
from kitty.options.types import Options
|
||||
from kitty.types import Edges, NeighborsMap, WindowGeometry, WindowMapper
|
||||
from kitty.typing_compat import WindowType
|
||||
@@ -453,31 +453,9 @@ class Layout:
|
||||
return True
|
||||
|
||||
def drag_resize_target_windows(
|
||||
self, click_window: WindowType, x: float, y: float, all_windows: WindowList
|
||||
) -> tuple[WindowType, WindowType]:
|
||||
g = click_window.geometry
|
||||
left_half_clicked = x <= g.left + (g.right - g.left) / 2
|
||||
top_half_clicked = y <= g.top + (g.bottom - g.top) / 2
|
||||
neighbors = self.neighbors_for_window(click_window, all_windows)
|
||||
left = neighbors.get("left", ())
|
||||
right = neighbors.get("right", ())
|
||||
top = neighbors.get("top", ())
|
||||
bottom = neighbors.get("bottom", ())
|
||||
horizontal_target = vertical_target = click_window
|
||||
|
||||
# Infer which window should be horizontally resized based on click
|
||||
# position and layout state
|
||||
if ((left_half_clicked and len(left) > 0) or
|
||||
(not left_half_clicked and len(left) > 0 and len(right) == 0)):
|
||||
horizontal_target = all_windows.id_map[left[0]]
|
||||
|
||||
# Infer which window should be vertically resized based on click
|
||||
# position and layout state
|
||||
if ((top_half_clicked and len(top) > 0) or
|
||||
(not top_half_clicked and len(top) > 0 and len(bottom) == 0)):
|
||||
vertical_target = all_windows.id_map[top[0]]
|
||||
|
||||
return horizontal_target, vertical_target
|
||||
self, click_window: WindowType, x: float, y: float, edges: int, all_windows: WindowList,
|
||||
) -> tuple[WindowType, bool, WindowType, bool]:
|
||||
return click_window, bool(edges & RIGHT_EDGE), click_window, bool(edges & BOTTOM_EDGE)
|
||||
|
||||
def serialize(self, all_windows: WindowList) -> dict[str, Any]:
|
||||
ans = self.layout_state()
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import sys
|
||||
from collections.abc import Generator, Sequence
|
||||
from itertools import islice, repeat
|
||||
from typing import Any
|
||||
|
||||
from kitty.borders import BorderColor
|
||||
from kitty.conf.utils import to_bool
|
||||
from kitty.fast_data_types import BOTTOM_EDGE, RIGHT_EDGE
|
||||
from kitty.types import Edges, NeighborsMap, WindowMapper
|
||||
from kitty.typing_compat import EdgeLiteral, WindowType
|
||||
from kitty.window_list import WindowGroup, WindowList
|
||||
@@ -24,6 +26,36 @@ from .base import (
|
||||
from .vertical import borders
|
||||
|
||||
|
||||
def drag_resize_target_windows(
|
||||
click_window: WindowType,
|
||||
edges: int,
|
||||
x: float, y: float,
|
||||
num_full_size_windows: int,
|
||||
all_windows: WindowList,
|
||||
main_is_horizontal: bool = True
|
||||
) -> tuple[WindowType, bool, WindowType, bool]:
|
||||
groups = tuple(all_windows.iter_all_layoutable_groups())
|
||||
horizontal = vertical = click_window
|
||||
min_dist = float(sys.maxsize)
|
||||
height_increases_downwards = bool(edges * BOTTOM_EDGE)
|
||||
width_increases_rightwards = bool(edges * RIGHT_EDGE)
|
||||
for gr in groups[num_full_size_windows:]:
|
||||
if gr.windows:
|
||||
w = gr.windows[-1]
|
||||
g = w.geometry
|
||||
if main_is_horizontal:
|
||||
if (dist := min(abs(g.top - y), abs(g.bottom - y))) < min_dist:
|
||||
min_dist = dist
|
||||
vertical = w
|
||||
height_increases_downwards = y > g.top + (g.bottom - g.top) / 2
|
||||
else:
|
||||
if (dist := min(abs(g.left - x), abs(g.right - x))) < min_dist:
|
||||
min_dist = dist
|
||||
horizontal = w
|
||||
width_increases_rightwards = x > g.left + (g.right - g.left) / 2
|
||||
return horizontal, width_increases_rightwards, vertical, height_increases_downwards
|
||||
|
||||
|
||||
def neighbors_for_tall_window(
|
||||
num_full_size_windows: int,
|
||||
window: WindowType,
|
||||
@@ -357,6 +389,11 @@ class Tall(Layout):
|
||||
self.layout_opts = TallLayoutOpts(layout_state['opts'])
|
||||
return True
|
||||
|
||||
def drag_resize_target_windows(
|
||||
self, click_window: WindowType, x: float, y: float, edges: int, all_windows: WindowList,
|
||||
) -> tuple[WindowType, bool, WindowType, bool]:
|
||||
return drag_resize_target_windows(click_window, edges, x, y, self.num_full_size_windows, all_windows, self.main_is_horizontal)
|
||||
|
||||
|
||||
class Fat(Tall):
|
||||
|
||||
|
||||
@@ -253,6 +253,8 @@ class WindowResizeDrag(NamedTuple):
|
||||
initial_y: float = 0
|
||||
last_step_x: float = 0
|
||||
last_step_y: float = 0
|
||||
height_increases_downwards: bool = True
|
||||
width_increases_rightwards: bool = True
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.is_active
|
||||
|
||||
Reference in New Issue
Block a user