From 96b0c463e8de8e53965fc15b7451f92be0b9595d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 19 Apr 2025 12:45:06 +0530 Subject: [PATCH] Start work on floating windows --- kitty/borders.py | 2 +- kitty/layout/base.py | 34 +++++++---- kitty/layout/grid.py | 10 ++-- kitty/layout/tall.py | 16 ++--- kitty/layout/vertical.py | 11 ++-- kitty/tabs.py | 8 +-- kitty/types.py | 7 +++ kitty/window.py | 10 +++- kitty/window_list.py | 125 +++++++++++++++++++++++++-------------- kitty_tests/layout.py | 23 +++---- 10 files changed, 156 insertions(+), 90 deletions(-) diff --git a/kitty/borders.py b/kitty/borders.py index 3577c49b4..046f0c9d2 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -91,7 +91,7 @@ class Borders: for tbr in tab_bar_rects: add_borders_rect(self.os_window_id, self.tab_id, *tbr) bw = 0 - groups = tuple(all_windows.iter_all_layoutable_groups(only_visible=True)) + groups = tuple(all_windows.iter_all_layoutable_groups()) if groups: bw = groups[0].effective_border() draw_borders = bw > 0 and draw_window_borders diff --git a/kitty/layout/base.py b/kitty/layout/base.py index c1b812c94..07338843a 100644 --- a/kitty/layout/base.py +++ b/kitty/layout/base.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # License: GPLv3 Copyright: 2020, Kovid Goyal -from collections.abc import Generator, Iterable, Iterator, Sequence +from collections.abc import Generator, Iterable, Sequence from functools import partial from itertools import repeat from typing import Any, NamedTuple @@ -9,7 +9,7 @@ from typing import Any, NamedTuple from kitty.borders import BorderColor from kitty.fast_data_types import Region, set_active_window, viewport_for_window from kitty.options.types import Options -from kitty.types import Edges, WindowGeometry +from kitty.types import Edges, FloatType, WindowGeometry from kitty.typing_compat import TypedDict, WindowType from kitty.window_list import WindowGroup, WindowList @@ -241,9 +241,9 @@ class Layout: def bias_increment_for_cell(self, all_windows: WindowList, is_horizontal: bool) -> float: self._set_dimensions() - return self.calculate_bias_increment_for_a_single_cell(all_windows, is_horizontal) + return self.calculate_bias_increment_for_a_single_cell(is_horizontal) - def calculate_bias_increment_for_a_single_cell(self, all_windows: WindowList, is_horizontal: bool) -> float: + def calculate_bias_increment_for_a_single_cell(self, is_horizontal: bool) -> float: if is_horizontal: return (lgd.cell_width + 1) / lgd.central.width return (lgd.cell_height + 1) / lgd.central.height @@ -284,7 +284,7 @@ class Layout: return self.neighbors_for_window(w, all_windows) def move_window(self, all_windows: WindowList, delta: int = 1) -> bool: - if all_windows.num_groups < 2 or not delta: + if all_windows.num_of_non_floating_groups < 2 or not delta: return False return all_windows.move_window_group(by=delta) @@ -332,7 +332,7 @@ class Layout: def _bias_slot(self, all_windows: WindowList, idx: int, bias: float) -> bool: fractional_bias = max(10, min(abs(bias), 90)) / 100 - h, v = self.calculate_bias_increment_for_a_single_cell(all_windows, True), self.calculate_bias_increment_for_a_single_cell(all_windows, False) + h, v = self.calculate_bias_increment_for_a_single_cell(True), self.calculate_bias_increment_for_a_single_cell(False) nh, nv = lgd.central.width / lgd.cell_width, lgd.central.height / lgd.cell_height f = max(-90, min(bias, 90)) / 100. return self.bias_slot(all_windows, idx, fractional_bias, h * nh *f, v * nv * f) @@ -342,9 +342,21 @@ class Layout: def update_visibility(self, all_windows: WindowList) -> None: active_window = all_windows.active_window - for window, is_group_leader in all_windows.iter_windows_with_visibility(): - is_visible = window is active_window or (is_group_leader and not self.only_active_window_visible) - window.set_visible_in_layout(is_visible) + floating_windows = [] + vismap = {} + for window, is_group_leader, is_floating in all_windows.iter_windows_with_visibility(): + if is_floating: + floating_windows.append((window, is_group_leader)) + else: + is_visible = window is active_window or (is_group_leader and not self.only_active_window_visible) + window.set_visible_in_layout(is_visible) + vismap[window.id] = is_visible + for window, is_group_leader in sorted(floating_windows, key=lambda x: x[0].id): + vis = is_group_leader + if vis and window.float_type is FloatType.window: + vis = vismap.get(window.floating_in_window, True) # if floating_in_window not found float in tab + window.set_visible_in_layout(vis) + vismap[window.id] = vis def _set_dimensions(self) -> None: lgd.central, tab_bar, vw, vh, lgd.cell_width, lgd.cell_height = viewport_for_window(self.os_window_id) @@ -372,7 +384,7 @@ class Layout: def xlayout( self, - groups: Iterator[WindowGroup], + groups: Iterable[WindowGroup], bias: None | Sequence[float] | dict[int, float] = None, start: int | None = None, size: int | None = None, @@ -391,7 +403,7 @@ class Layout: def ylayout( self, - groups: Iterator[WindowGroup], + groups: Iterable[WindowGroup], bias: None | Sequence[float] | dict[int, float] = None, start: int | None = None, size: int | None = None, diff --git a/kitty/layout/grid.py b/kitty/layout/grid.py index a41f82d2c..32ff830e2 100644 --- a/kitty/layout/grid.py +++ b/kitty/layout/grid.py @@ -75,7 +75,7 @@ class Grid(Layout): return 0, 0 def bias_slot(self, all_windows: WindowList, idx: int, fractional_bias: float, cell_increment_bias_h: float, cell_increment_bias_v: float) -> bool: - num_windows = all_windows.num_groups + num_windows = all_windows.num_layoutable_groups ncols, nrows, special_rows, special_col = calc_grid_size(num_windows) row_num, col_num = self.position_for_window_idx(idx, num_windows, ncols, nrows, special_rows, special_col) if row_num == 0: @@ -93,7 +93,7 @@ class Grid(Layout): return tuple(self.variable_layout(layout_func, num_windows, b)) == before_layout def apply_bias(self, idx: int, increment: float, all_windows: WindowList, is_horizontal: bool = True) -> bool: - num_windows = all_windows.num_groups + num_windows = all_windows.num_layoutable_groups ncols, nrows, special_rows, special_col = calc_grid_size(num_windows) row_num, col_num = self.position_for_window_idx(idx, num_windows, ncols, nrows, special_rows, special_col) @@ -151,7 +151,7 @@ class Grid(Layout): on_col_done(col_windows) def do_layout(self, all_windows: WindowList) -> None: - n = all_windows.num_groups + n = all_windows.num_layoutable_groups if n == 1: self.layout_single_window_group(next(all_windows.iter_all_layoutable_groups())) return @@ -193,7 +193,7 @@ class Grid(Layout): position_window_in_grid_cell(window_idx, xl, yl) def minimal_borders(self, all_windows: WindowList) -> Generator[BorderLine, None, None]: - n = all_windows.num_groups + n = all_windows.num_layoutable_groups if not lgd.draw_minimal_borders or n < 2: return needs_borders_map = all_windows.compute_needs_borders_map(lgd.draw_active_borders) @@ -260,7 +260,7 @@ class Grid(Layout): yield BorderLine(edges, color) def neighbors_for_window(self, window: WindowType, all_windows: WindowList) -> NeighborsMap: - n = all_windows.num_groups + n = all_windows.num_layoutable_groups if n < 4: return neighbors_for_tall_window(1, window, all_windows) diff --git a/kitty/layout/tall.py b/kitty/layout/tall.py index 082f43a1d..a5761284f 100644 --- a/kitty/layout/tall.py +++ b/kitty/layout/tall.py @@ -118,9 +118,10 @@ class Tall(Layout): return True def variable_layout(self, all_windows: WindowList, biased_map: dict[int, float]) -> LayoutDimension: - num = all_windows.num_groups - self.num_full_size_windows + windows = tuple(all_windows.iter_all_layoutable_groups()) + num = len(windows) - self.num_full_size_windows bias = biased_map if num > 1 else None - return self.perp_axis_layout(all_windows.iter_all_layoutable_groups(), bias=bias, offset=self.num_full_size_windows) + return self.perp_axis_layout(windows, bias=bias, offset=self.num_full_size_windows) def bias_slot(self, all_windows: WindowList, idx: int, fractional_bias: float, cell_increment_bias_h: float, cell_increment_bias_v: float) -> bool: if idx < len(self.main_bias): @@ -134,7 +135,7 @@ class Tall(Layout): return before_layout == after_layout def apply_bias(self, idx: int, increment: float, all_windows: WindowList, is_horizontal: bool = True) -> bool: - num_windows = all_windows.num_groups + num_windows = all_windows.num_layoutable_groups if self.main_is_horizontal == is_horizontal: before_main_bias = self.main_bias ncols = self.num_full_size_windows + 1 @@ -159,10 +160,10 @@ class Tall(Layout): return before != after def simple_layout(self, all_windows: WindowList) -> Generator[tuple[WindowGroup, LayoutData, LayoutData, bool], None, None]: - num = all_windows.num_groups is_fat = not self.main_is_horizontal mirrored = self.layout_opts.mirrored groups = tuple(all_windows.iter_all_layoutable_groups()) + num = len(groups) main_bias = self.main_bias[::-1] if mirrored else self.main_bias if mirrored: groups = tuple(reversed(groups)) @@ -218,9 +219,10 @@ class Tall(Layout): yield wg, xl, yl, False def do_layout(self, all_windows: WindowList) -> None: - num = all_windows.num_groups + windows = tuple(all_windows.iter_all_layoutable_groups()) + num = len(windows) if num == 1: - self.layout_single_window_group(next(all_windows.iter_all_layoutable_groups())) + self.layout_single_window_group(windows[0]) return layouts = (self.simple_layout if num <= self.num_full_size_windows + 1 else self.full_layout)(all_windows) for wg, xl, yl, is_full_size in layouts: @@ -270,7 +272,7 @@ class Tall(Layout): return None def minimal_borders(self, all_windows: WindowList) -> Generator[BorderLine, None, None]: - num = all_windows.num_groups + num = all_windows.num_layoutable_groups if num < 2 or not lgd.draw_minimal_borders: return try: diff --git a/kitty/layout/vertical.py b/kitty/layout/vertical.py index 6671a8fee..4012cff61 100644 --- a/kitty/layout/vertical.py +++ b/kitty/layout/vertical.py @@ -68,9 +68,10 @@ class Vertical(Layout): perp_axis_layout = Layout.xlayout def variable_layout(self, all_windows: WindowList, biased_map: dict[int, float]) -> LayoutDimension: - num_windows = all_windows.num_groups + windows = tuple(all_windows.iter_all_layoutable_groups()) + num_windows = len(windows) bias = biased_map if num_windows > 1 else None - return self.main_axis_layout(all_windows.iter_all_layoutable_groups(), bias=bias) + return self.main_axis_layout(windows, bias=bias) def fixed_layout(self, wg: WindowGroup) -> LayoutDimension: return self.perp_axis_layout(iter((wg,)), border_mult=0 if lgd.draw_minimal_borders else 1) @@ -82,7 +83,7 @@ class Vertical(Layout): def apply_bias(self, idx: int, increment: float, all_windows: WindowList, is_horizontal: bool = True) -> bool: if self.main_is_horizontal != is_horizontal: return False - num_windows = all_windows.num_groups + num_windows = all_windows.num_layoutable_groups if num_windows < 2: return False before_layout = list(self.variable_layout(all_windows, self.biased_map)) @@ -109,7 +110,7 @@ class Vertical(Layout): yield wg, xl, yl def do_layout(self, all_windows: WindowList) -> None: - window_count = all_windows.num_groups + window_count = all_windows.num_layoutable_groups if window_count == 1: self.layout_single_window_group(next(all_windows.iter_all_layoutable_groups())) return @@ -117,7 +118,7 @@ class Vertical(Layout): self.set_window_group_geometry(wg, xl, yl) def minimal_borders(self, all_windows: WindowList) -> Generator[BorderLine, None, None]: - window_count = all_windows.num_groups + window_count = all_windows.num_layoutable_groups if window_count < 2 or not lgd.draw_minimal_borders: return yield from borders(self.generate_layout_data(all_windows), self.main_is_horizontal, all_windows) diff --git a/kitty/tabs.py b/kitty/tabs.py index ed5013398..2cc95d797 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -192,7 +192,7 @@ class Tab: # {{{ def has_single_window_visible(self) -> bool: if self.current_layout.only_active_window_visible: return True - for i, g in enumerate(self.windows.iter_all_layoutable_groups(only_visible=True)): + for i, g in enumerate(self.windows.iter_all_layoutable_groups()): if i > 0: return False return True @@ -673,8 +673,8 @@ class Tab: # {{{ if self.windows: if num < 0: self.windows.make_previous_group_active(-num) - elif self.windows.num_groups: - self.current_layout.activate_nth_window(self.windows, min(num, self.windows.num_groups - 1)) + elif self.windows.num_of_floating_groups_and_non_floating_groups: + self.current_layout.activate_nth_window(self.windows, min(num, self.windows.num_of_floating_groups_and_non_floating_groups - 1)) self.relayout_borders() @ac('win', 'Focus the first window') @@ -893,7 +893,7 @@ class Tab: # {{{ @property def num_window_groups(self) -> int: - return self.windows.num_groups + return self.windows.num_of_non_floating_groups def __contains__(self, window: Window) -> bool: return window in self.windows diff --git a/kitty/types.py b/kitty/types.py index 68bf40a65..9747c1498 100644 --- a/kitty/types.py +++ b/kitty/types.py @@ -27,6 +27,13 @@ class OverlayType(Enum): main = 'main' +class FloatType(Enum): + none = 'none' + window = 'window' + tab = 'tab' + os_window = 'os_window' + + class ParsedShortcut(NamedTuple): mods: int key_name: str diff --git a/kitty/window.py b/kitty/window.py index 16540e2c5..a4e7b0ff5 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -91,7 +91,7 @@ from .keys import keyboard_mode_name, mod_mask from .progress import Progress from .rgb import to_color from .terminfo import get_capabilities -from .types import MouseEvent, OverlayType, WindowGeometry, ac, run_once +from .types import FloatType, MouseEvent, OverlayType, WindowGeometry, ac, run_once from .typing_compat import BossType, ChildType, EdgeLiteral, TabType, TypedDict from .utils import ( color_as_int, @@ -623,12 +623,16 @@ class Window: watchers: Watchers | None = None, allow_remote_control: bool = False, remote_control_passwords: dict[str, Sequence[str]] | None = None, + float_type: FloatType = FloatType.none, + floating_in_window: int = 0, ): if watchers: self.watchers = watchers self.watchers.add(global_watchers()) else: self.watchers = global_watchers().copy() + self.float_type = float_type + self.floating_in_window = floating_in_window self.keys_redirected_till_ready_from: int = 0 self.last_focused_at = 0. self.is_focused: bool = False @@ -682,6 +686,10 @@ class Window: self.remote_control_passwords = remote_control_passwords self.allow_remote_control = allow_remote_control + @property + def is_floating(self) -> bool: + return self.float_type is not FloatType.none + def remote_control_allowed(self, pcmd: dict[str, Any], extra_data: dict[str, Any]) -> bool: if not self.allow_remote_control: return False diff --git a/kitty/window_list.py b/kitty/window_list.py index 0c4055f7b..a7dbc30a4 100644 --- a/kitty/window_list.py +++ b/kitty/window_list.py @@ -72,6 +72,13 @@ class WindowGroup: else: self.windows.append(window) + @property + def is_floating(self) -> bool: + for w in self.windows: + if w.is_floating: + return True + return False + def move_window_to_top_of_group(self, window: WindowType) -> bool: try: idx = self.windows.index(window) @@ -100,22 +107,19 @@ class WindowGroup: } 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) + w.effective_border() * border_mult + w.effective_padding(which) + for w in self.windows: + return w.effective_margin(which) + w.effective_border() * border_mult + w.effective_padding(which) + return 0 def effective_padding(self, which: EdgeLiteral) -> int: - if not self.windows: - return 0 - w = self.windows[0] - return w.effective_padding(which) + for w in self.windows: + return w.effective_padding(which) + return 0 def effective_border(self) -> int: - if not self.windows: - return 0 - w = self.windows[0] - return w.effective_border() + for w in self.windows: + return w.effective_border() + return 0 def set_geometry(self, geom: WindowGeometry) -> None: for w in self.windows: @@ -123,22 +127,19 @@ class WindowGroup: @property def default_bg(self) -> Color: - if self.windows: - w = self.windows[-1] + for w in reversed(self.windows): return w.screen.color_profile.default_bg or get_options().background return get_options().background @property def geometry(self) -> WindowGeometry | None: - if self.windows: - w = self.windows[-1] + for w in reversed(self.windows): return w.geometry return None @property def is_visible_in_layout(self) -> bool: - if self.windows: - w = self.windows[-1] + for w in reversed(self.windows): return w.is_visible_in_layout return False @@ -202,7 +203,7 @@ class WindowList: def set_active_group_idx(self, i: int, notify: bool = True) -> bool: changed = False - if i != self._active_group_idx and 0 <= i < len(self.groups): + if i != self._active_group_idx and 0 <= i < self.num_of_floating_groups_and_non_floating_groups: old_active_window = self.active_window g = self.active_group if g is not None: @@ -226,14 +227,37 @@ class WindowList: def change_tab(self, tab: TabType) -> None: self.tabref = weakref.ref(tab) - def iter_windows_with_visibility(self) -> Iterator[tuple[WindowType, bool]]: + def iter_windows_with_visibility(self) -> Iterator[tuple[WindowType, bool, bool]]: for g in self.groups: aw = g.active_window_id + is_floating = g.is_floating for window in g: - yield window, window.id == aw + yield window, window.id == aw, is_floating - def iter_all_layoutable_groups(self, only_visible: bool = False) -> Iterator[WindowGroup]: - return iter(g for g in self.groups if g.is_visible_in_layout) if only_visible else iter(self.groups) + def iter_all_layoutable_groups(self) -> Iterator[WindowGroup]: + for g in self.groups: + if g.is_visible_in_layout and not g.is_floating: + yield g + + @property + def num_layoutable_groups(self) -> int: + ans = 0 + for g in self.groups: + if g.is_visible_in_layout and not g.is_floating: + ans += 1 + return ans + + @property + def num_of_non_floating_groups(self) -> int: + ans = 0 + for g in self.groups: + if not g.is_floating: + ans += 1 + return ans + + @property + def num_of_floating_groups_and_non_floating_groups(self) -> int: + return len(self.groups) def iter_windows_with_number(self, only_visible: bool = True) -> Iterator[tuple[int, WindowType]]: for i, g in enumerate(self.groups): @@ -259,10 +283,6 @@ class WindowList: return self.set_active_group_idx(len(self.groups) - 1, notify=notify) - @property - def num_groups(self) -> int: - return len(self.groups) - def group_for_window(self, x: WindowOrId) -> WindowGroup | None: q = self.id_map[x] if isinstance(x, int) else x for g in self.groups: @@ -343,22 +363,28 @@ class WindowList: if group_of is not None: target_group = self.group_for_window(group_of) - if target_group is None and next_to is not None: - q = self.id_map[next_to] if isinstance(next_to, int) else next_to - pos = -1 - for i, g in enumerate(self.groups): - if q in g: - pos = i - break - if pos > -1: + if window.is_floating: + if target_group is None: target_group = WindowGroup() - self.groups.insert(pos + (0 if before else 1), target_group) - if target_group is None: - target_group = WindowGroup() - if before: - self.groups.insert(0, target_group) - else: self.groups.append(target_group) + else: + if target_group is None and next_to is not None: + q = self.id_map[next_to] if isinstance(next_to, int) else next_to + pos = -1 + for i, g in enumerate(self.groups): + if q in g: + pos = i + break + if pos > -1: + target_group = WindowGroup() + self.groups.insert(pos + (0 if before else 1), target_group) + if target_group is None: + target_group = WindowGroup() + if before: + self.groups.insert(0, target_group) + else: + self.groups.append(target_group) + self.move_floating_groups_to_end() old_active_window = self.active_window target_group.add_window(window, head_of_group=head_of_group) @@ -372,6 +398,14 @@ class WindowList: self.notify_on_active_window_change(old_active_window, new_active_window) return target_group + def move_floating_groups_to_end(self) -> None: + fg: list[WindowGroup] = [] + ng: list[WindowGroup] = [] + for g in self.groups: + (fg if g.is_floating else ng).append(g) + ng.extend(fg) + self.groups = ng + def remove_window(self, x: WindowOrId) -> None: old_active_window = self.active_window q = self.id_map[x] if isinstance(x, int) else x @@ -398,8 +432,8 @@ class WindowList: def active_window_in_nth_group(self, n: int, clamp: bool = False) -> WindowType | None: if clamp: - n = max(0, min(n, self.num_groups - 1)) - if 0 <= n < self.num_groups: + n = max(0, min(n, len(self.groups) - 1)) + if 0 <= n < len(self.groups): return self.id_map.get(self.groups[n].active_window_id) return None @@ -410,14 +444,14 @@ class WindowList: return None def activate_next_window_group(self, delta: int) -> None: - self.set_active_group_idx(wrap_increment(self.active_group_idx, self.num_groups, delta)) + self.set_active_group_idx(wrap_increment(self.active_group_idx, self.num_of_floating_groups_and_non_floating_groups, delta)) def move_window_group(self, by: int | None = None, to_group: int | None = None) -> bool: if self.active_group_idx < 0 or not self.groups: return False target = -1 if by is not None: - target = wrap_increment(self.active_group_idx, self.num_groups, by) + target = wrap_increment(self.active_group_idx, len(self.groups), by) if to_group is not None: for i, group in enumerate(self.groups): if group.id == to_group: @@ -427,6 +461,7 @@ class WindowList: if target == self.active_group_idx: return False self.groups[self.active_group_idx], self.groups[target] = self.groups[target], self.groups[self.active_group_idx] + self.move_floating_groups_to_end() self.set_active_group_idx(target) return True return False diff --git a/kitty_tests/layout.py b/kitty_tests/layout.py index bb75bace8..0c75cc5e8 100644 --- a/kitty_tests/layout.py +++ b/kitty_tests/layout.py @@ -14,6 +14,7 @@ class Window: def __init__(self, win_id, overlay_for=None, overlay_window_id=None): self.id = win_id + self.is_floating = False self.overlay_for = overlay_for self.overlay_window_id = overlay_window_id self.is_visible_in_layout = True @@ -98,15 +99,15 @@ class TestLayout(BaseTest): check_visible() # Test nth_window - for i in range(windows.num_groups): + for i in range(windows.num_of_floating_groups_and_non_floating_groups): q.activate_nth_window(windows, i) self.ae(windows.active_group_idx, i) expect_ids(*range(1, len(windows)+1)) check_visible() # Test next_window - for i in range(2 * windows.num_groups): - expected = (windows.active_group_idx + 1) % windows.num_groups + for i in range(2 * windows.num_of_floating_groups_and_non_floating_groups): + expected = (windows.active_group_idx + 1) % windows.num_of_floating_groups_and_non_floating_groups q.next_window(windows) self.ae(windows.active_group_idx, expected) expect_ids(*range(1, len(windows)+1)) @@ -127,9 +128,9 @@ class TestLayout(BaseTest): # Test add_window windows.set_active_group_idx(4) q.add_window(windows, Window(6)) - self.ae(windows.num_groups, 6) + self.ae(windows.num_of_floating_groups_and_non_floating_groups, 6) self.ae(windows.active_group_idx, 5) - expect_ids(*range(1, windows.num_groups+1)) + expect_ids(*range(1, windows.num_of_floating_groups_and_non_floating_groups+1)) check_visible() # Test remove_window @@ -150,7 +151,7 @@ class TestLayout(BaseTest): expect_ids(2, 3, 5, 6) # Test set_active_window - for i in range(windows.num_groups): + for i in range(windows.num_of_floating_groups_and_non_floating_groups): windows.set_active_group_idx(i) self.ae(i, windows.active_group_idx) check_visible() @@ -177,10 +178,10 @@ class TestLayout(BaseTest): w = Window(len(windows) + 1) windows.add_window(w) expect_ids(1, 2, 3, 4, 5, 6) - self.ae(windows.active_group_idx, windows.num_groups - 1) + self.ae(windows.active_group_idx, windows.num_of_floating_groups_and_non_floating_groups - 1) # Test nth_window - for i in range(windows.num_groups): + for i in range(windows.num_of_floating_groups_and_non_floating_groups): q.activate_nth_window(windows, i) self.ae(windows.active_group_idx, i) if i == overlaid_group: @@ -189,8 +190,8 @@ class TestLayout(BaseTest): check_visible() # Test next_window - for i in range(windows.num_groups): - expected = (windows.active_group_idx + 1) % windows.num_groups + for i in range(windows.num_of_floating_groups_and_non_floating_groups): + expected = (windows.active_group_idx + 1) % windows.num_of_floating_groups_and_non_floating_groups q.next_window(windows) self.ae(windows.active_group_idx, expected) expect_ids(1, 2, 3, 4, 5, 6) @@ -210,7 +211,7 @@ class TestLayout(BaseTest): check_visible() # Test set_active_window - for i in range(windows.num_groups): + for i in range(windows.num_of_floating_groups_and_non_floating_groups): windows.set_active_group_idx(i) self.ae(i, windows.active_group_idx) if i == overlaid_group: