From 595706d66f0721c4ffbc3ca5c65dacd7ff28dc48 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Fri, 30 Oct 2026 12:45:12 -0700 Subject: [PATCH] feat(nix): the drag-resize edge cases are a shared scenario resize.edge_cases makes its drags from the daemon's layout and reads the frames from the operating system: both sides of a shared edge, a horizontal edge, a corner and an edge of the screen, with a neighbour or without. The KDE extra keeps pointer_is_exact. --- docs/dev/suite-ledger.md | 15 +- .../lib/komorebi_vm/core/scenarios/resize.py | 214 +++++++++++++++++ .../platforms/kde/extras/drag_resize.py | 215 +----------------- nix/tests/vm/lib/tests/fake_platform.py | 6 +- nix/tests/vm/lib/tests/test_moved.py | 43 ++++ nix/tests/vm/suites/drag-resize/test.py | 9 +- 6 files changed, 284 insertions(+), 218 deletions(-) diff --git a/docs/dev/suite-ledger.md b/docs/dev/suite-ledger.md index 41681c83..d811c791 100644 --- a/docs/dev/suite-ledger.md +++ b/docs/dev/suite-ledger.md @@ -58,12 +58,15 @@ every count, with the extra's own check left to say only where KWin has the wind ## drag-resize -The suite's own cases are all KDE's: the pointer put to the pixel, and eight drags of edges and -corners checked against frames, tiles and neighbors. None of them is removed; they moved to -`kde_drag_resize` as `pointer_is_exact` and `edge_cases`, and the suite calls the shared `resize` -and `focus_follows_mouse` after them, as before. The shared `resize` makes one drag of one edge, -which the extra's `win1:right:...` cases also make: that is a repeat by design, because the extra -reads the daemon's tiles and the frames together, and the shared one reads only the system. +The suite's own cases were all KDE's: the pointer put to the pixel, and eight drags of edges and +corners checked against frames, tiles and neighbors. The pointer check is the extra +`pointer_is_exact`. The eight drags are the shared `resize.edge_cases`, which makes its cases from +the daemon's layout (`latest_layout`) and reads the frames from the operating system, not from +KWin: both sides of an edge two tiles share, a horizontal edge, a corner and an edge of the screen. +With three windows in BSP the cases are the same eight as before. What changed: the wait for the +end of a drag is the layout changing (three seconds at most) and the frames settling, not the +daemon's log line `ResizeEnd`; and the strict checks use the platform's `tolerance` where the extra +used the cell of the font. The shared `resize.run` makes one drag of one edge, as before. One run of the suite failed `win2:left:-240,0` ("frame R moved -96 but was not dragged": the terminal's frame four cells short of an unchanged tile) and the next passed; not seen again. diff --git a/nix/tests/vm/lib/komorebi_vm/core/scenarios/resize.py b/nix/tests/vm/lib/komorebi_vm/core/scenarios/resize.py index 89e4d05b..439513ca 100644 --- a/nix/tests/vm/lib/komorebi_vm/core/scenarios/resize.py +++ b/nix/tests/vm/lib/komorebi_vm/core/scenarios/resize.py @@ -93,3 +93,217 @@ def run(platform: Platform, checks: Checks, clients: list[Client], dx: int | Non "and do not overlap", not any(a.overlaps(b) for i, a in enumerate(frames) for b in frames[i + 1 :]), ) + + +GRABS = { + "left": "L", + "right": "R", + "top": "T", + "bottom": "B", + "topleft": "LT", + "topright": "RT", + "bottomleft": "LB", + "bottomright": "RB", +} +# how far apart two windows may be for one to be the neighbour of the other: twice the gap +NEIGHBOUR = 80 + + +def _edges(r: Rect) -> dict[str, int]: + return {"L": r.x, "T": r.y, "R": r.x + r.w, "B": r.y + r.h} + + +def _tiles(platform: Platform) -> dict[str, Rect]: + """The daemon's layout: the tile it gave each container, by the title of its window in view.""" + workspace = platform.state().workspace() + return { + c[min(workspace.focused_windows[i], len(c) - 1)].title: workspace.latest_layout[i] + for i, c in enumerate(workspace.containers) + if i < len(workspace.latest_layout) and c + } + + +def _frames(platform: Platform, clients: list[Client]) -> dict[str, Rect]: + return {c.title: w.frame for c in clients if (w := platform.os_window(c)) is not None} + + +def _settled(platform: Platform, clients: list[Client]) -> dict[str, Rect]: + """The frames once they have stopped changing.""" + last = _frames(platform, clients) + for _ in range(20): + platform.wait_for(lambda: False, timeout=0.5) + now = _frames(platform, clients) + if now == last: + return now + last = now + return last + + +def _press_point(grab: str, r: Rect) -> tuple[int, int]: + """Where the pointer is pressed for a grab: in the gap outside the frame.""" + left, right, top, bottom = r.x - OFFSET, r.x + r.w + OFFSET, r.y - OFFSET, r.y + r.h + OFFSET + cx, cy = r.x + r.w // 2, r.y + r.h // 2 + return { + "left": (left, cy), + "right": (right, cy), + "top": (cx, top), + "bottom": (cx, bottom), + "topleft": (left, top), + "topright": (right, top), + "bottomleft": (left, bottom), + "bottomright": (right, bottom), + }[grab] + + +def _has_neighbour(edge: str, name: str, frames: dict[str, Rect]) -> bool: + """Is there another window within a gap's reach on that side of this one, overlapping it.""" + me = frames[name] + for other, o in frames.items(): + if other == name: + continue + vertical = o.y < me.y + me.h and me.y < o.y + o.h + horizontal = o.x < me.x + me.w and me.x < o.x + o.w + if edge == "L" and vertical and 0 <= me.x - (o.x + o.w) <= NEIGHBOUR: + return True + if edge == "R" and vertical and 0 <= o.x - (me.x + me.w) <= NEIGHBOUR: + return True + if edge == "T" and horizontal and 0 <= me.y - (o.y + o.h) <= NEIGHBOUR: + return True + if edge == "B" and horizontal and 0 <= o.y - (me.y + me.h) <= NEIGHBOUR: + return True + return False + + +def _stacked(layout: list[Rect]) -> tuple[int, int] | None: + """The first pair of tiles of which the second is below the first and overlaps it sideways.""" + for i, a in enumerate(layout): + for j, b in enumerate(layout): + if i != j and b.y >= a.y + a.h and a.x < b.x + b.w and b.x < a.x + a.w: + return i, j + return None + + +def _cases(layout: list[Rect], titles: list[str], area: Rect) -> list[tuple[str, str, int, int]]: + """Drags to make, as (window, grab, dx, dy), from the layout: both sides of an edge that two + tiles share, a horizontal one, a corner next to two neighbours, and an edge of the screen.""" + cases: list[tuple[str, str, int, int]] = [] + if (pair := _side_by_side(layout)) is not None: + a, b = pair + cases += [ + (titles[a], "right", 72, 0), + (titles[a], "right", -72, 0), + (titles[b], "left", -72, 0), + (titles[b], "left", -240, 0), + ] + if (stack := _stacked(layout)) is not None: + a, b = stack + cases += [(titles[a], "bottom", 0, 72), (titles[b], "top", 0, -72)] + for k, tile in enumerate(layout): + right_of = any( + i != k and tile.x >= t.x + t.w and t.y < tile.y + tile.h and tile.y < t.y + t.h + for i, t in enumerate(layout) + ) + above = any( + i != k and t.y >= tile.y + tile.h and tile.x < t.x + t.w and t.x < tile.x + tile.w + for i, t in enumerate(layout) + ) + if right_of and above: + cases.append((titles[k], "bottomleft", -72, 72)) + break + first = min(range(len(layout)), key=lambda i: layout[i].x) + if _press_point("left", layout[first])[0] >= area.x: + cases.append((titles[first], "left", -72, 0)) + return cases + + +def _problems( + platform: Platform, + clients: list[Client], + case: tuple[str, str, int, int], +) -> list[str]: + """Makes a drag and says what is wrong with the outcome: the frame the user sees, the layout, + the edges that were not dragged and the windows.""" + name, grab, dx, dy = case + area = platform.work_area() + platform.komorebic("retile") + before = _settled(platform, clients) + tiles_before = _tiles(platform) + + px, py = _press_point(grab, before[name]) + end = (max(area.x, px + dx), max(area.y, py + dy)) + platform.pointer.drag((px, py), end) + platform.wait_for(lambda: _tiles(platform) != tiles_before, timeout=3) + after = _settled(platform, clients) + tiles_after = _tiles(platform) + + held = GRABS[grab] + want = {"L": dx, "R": dx, "T": dy, "B": dy} + problems = [] + moved = {e: _edges(after[name])[e] - _edges(before[name])[e] for e in "LTRB"} + for e in "LTRB": + if e in held and _has_neighbour(e, name, before): + if abs(moved[e] - want[e]) > platform.tolerance: + problems.append(f"frame {e} moved {moved[e]}, the pointer moved {want[e]}") + elif abs(moved[e]) > platform.tolerance: + why = "was not dragged" if e not in held else "has no neighbour" + problems.append(f"frame {e} moved {moved[e]} but {why}") + + tile_moved = {e: _edges(tiles_after[name])[e] - _edges(tiles_before[name])[e] for e in "LTRB"} + for e in "LTRB": + if e in held and _has_neighbour(e, name, before): + if abs(tile_moved[e] - want[e]) > 2: + problems.append(f"tile {e} moved {tile_moved[e]}, the pointer moved {want[e]}") + elif abs(tile_moved[e]) > 1: + why = "was not dragged" if e not in held else "has no neighbour" + problems.append(f"tile {e} moved {tile_moved[e]} but {why}") + + # nothing else moves, but with a dragged edge: they share it + follows = [m for m in tile_moved.values() if abs(m) > 1] + for other in tiles_after: + if other == name: + continue + for e in "LTRB": + m = _edges(tiles_after[other])[e] - _edges(tiles_before[other])[e] + if abs(m) > 1 and not any(abs(m - f) <= 2 for f in follows): + problems.append(f"{other} tile {e} moved {m}: not with the dragged edge") + + names = list(after) + for i, a in enumerate(names): + if not after[a].inside(area): + problems.append(f"{a} {after[a]} is outside the work area") + problems += [f"{a} and {b} overlap" for b in names[i + 1 :] if after[a].overlaps(after[b])] + print(f" {case}: frame {before[name]} -> {after[name]}, tile edges {tile_moved}") + return problems + + +def edge_cases(platform: Platform, checks: Checks, clients: list[Client]) -> None: + """Drags both sides of an edge two tiles share, a horizontal edge, a corner and an edge of the + screen, and checks, against the layout the daemon computed (`latest_layout`) and the frames the + operating system has: + + - a dragged edge that has a neighbour moves by what the pointer moved, and the neighbour's + edge moves with it + - a dragged edge with no neighbour does not move, and the window is put back + - edges that were not dragged do not move, and every edge of another tile stays or moves with + a dragged one + - the windows still tile: inside the work area, not on each other + + `clients` are the tiled windows of the first workspace, each in a container of its own, in a + layout that has them side by side or stacked. The cases are made from the layout, so that + a layout with no stacked tiles has no horizontal case. The layout is retiled before each one. + """ + if not platform.has("pointer"): + print(" skipped: this platform has no pointer") + return + platform.komorebic("retile") + platform.wait_for(lambda: len(_tiles(platform)) == len(clients), timeout=20) + tiles = _tiles(platform) + titles = list(tiles) + layout = [tiles[t] for t in titles] + for case in _cases(layout, titles, platform.work_area()): + problems = _problems(platform, clients, case) + name, grab, dx, dy = case + checks.check( + f"{name}:{grab}:{dx},{dy}: " + ("as expected" if not problems else "; ".join(problems)), + not problems, + ) diff --git a/nix/tests/vm/lib/komorebi_vm/platforms/kde/extras/drag_resize.py b/nix/tests/vm/lib/komorebi_vm/platforms/kde/extras/drag_resize.py index 0abae589..9a39091e 100644 --- a/nix/tests/vm/lib/komorebi_vm/platforms/kde/extras/drag_resize.py +++ b/nix/tests/vm/lib/komorebi_vm/platforms/kde/extras/drag_resize.py @@ -1,211 +1,22 @@ -"""What only KDE can tell about dragging the edges of tiles with a real pointer. +"""What only KDE can tell about dragging with a real pointer. -The pointer is a device made inside the guest, and KWin gives the daemon the end of each drag. Edges -and corners of three tiles are grabbed and dragged, and what happened is checked against what a -user expects (`komorebi/tests/drag_resize.rs` checks the window manager's side against the fake): +The pointer is a device made inside the guest. The shared `resize` makes the drags of the edges and +corners of the tiles, against the daemon's layout and the frames the operating system has +(`komorebi/tests/drag_resize.rs` checks the window manager's side against the fake); what is here is +that the device puts the pointer to the pixel, which a drag at a gap of four pixels depends on. -* a dragged edge that has a neighbor moves by what the pointer moved, and the neighbor's edge moves - with it: they share it -* a dragged edge with no neighbor (the edge of the screen) does not move, and the window is put back -* edges that were not dragged do not move, and every edge of every other tile either stays or moves - with a dragged one -* the windows still tile: inside the screen, not overlapping - -The strict checks are on the tiles, which are the daemon's own layout (`latest_layout` in -`komorebic state`). A terminal's frame is checked loosely: it sizes itself to whole cells of its -font, so it is a few pixels short of its tile. The shared `resize` makes one drag and reads the -operating system; these are the cases it leaves out. - -The suite runs `pointer_is_exact` and `edge_cases` on a session with a pointer and three tiled -windows, `win1` to `win3`, then the shared scenarios. +The suite runs `pointer_is_exact` on a session with a pointer and three tiled windows, `win1` to +`win3`, then the shared `resize.edge_cases`, `resize.run` and `focus_follows_mouse`. """ import re -import time -from komorebi_vm import daemon from komorebi_vm.core.checks import Checks from komorebi_vm.core.platform import Client -from komorebi_vm.kde_platform import CELL, KdePlatform +from komorebi_vm.kde_platform import KdePlatform -# the module's unit, which the session starts when it logs in: the daemon the suite drags against -UNIT = "komorebi.service" - -# how far from its frame a window's resize border is pressed: in the gap between two tiles -OFFSET = 4 WINDOWS = 3 -GRABS = { - "left": "L", - "right": "R", - "top": "T", - "bottom": "B", - "topleft": "LT", - "topright": "RT", - "bottomleft": "LB", - "bottomright": "RB", -} - -# BSP: win1 is the left half, win2 the top right and win3 the bottom right -CASES = [ - "win1:right:72,0", - "win1:right:-72,0", - "win2:left:-72,0", - "win2:left:-240,0", - "win2:bottom:0,72", - "win3:top:0,-72", - "win2:bottomleft:-72,72", - "win1:left:-72,0", -] - -Box = tuple[int, int, int, int] - - -def frames(platform: KdePlatform) -> dict[str, Box]: - kde = platform.kde - out = {} - for n in range(1, WINDOWS + 1): - r = kde.rect(kde.wid(f"win{n}")) - out[f"win{n}"] = (r.x, r.y, r.w, r.h) - return out - - -def tiles(platform: KdePlatform) -> dict[str, Box]: - """komorebi's layout: the tile it gave each window, by title""" - workspace = platform.kde.state()["monitors"]["elements"][0]["workspaces"]["elements"][0] - out = {} - for i, container in enumerate(workspace["containers"]["elements"]): - windows = container["windows"] - title = windows["elements"][windows["focused"]]["details"]["title"] - tile = workspace["latest_layout"][i] - out[title] = (tile["left"], tile["top"], tile["right"], tile["bottom"]) - return out - - -def edges(r: Box) -> dict[str, int]: - x, y, w, h = r - return {"L": x, "T": y, "R": x + w, "B": y + h} - - -def settled(platform: KdePlatform) -> dict[str, Box]: - """The frames once they have stopped changing""" - last = frames(platform) - deadline = time.monotonic() + 10 * platform.kde.scale - while time.monotonic() < deadline: - time.sleep(0.5) - now = frames(platform) - if now == last: - return now - last = now - return last - - -def resize_ends(platform: KdePlatform) -> int: - """How many drags of an edge the daemon has handled the end of, by the unit's log""" - log = platform.kde.run(f"journalctl --user -u {UNIT} --no-pager -o cat")[1] - return sum(1 for e in daemon.events(log) if e.kind == "ResizeEnd") - - -def press_point(grab: str, r: Box) -> tuple[int, int]: - x, y, w, h = r - left, right, top, bottom = x - OFFSET, x + w + OFFSET, y - OFFSET, y + h + OFFSET - cx, cy = x + w // 2, y + h // 2 - return { - "left": (left, cy), - "right": (right, cy), - "top": (cx, top), - "bottom": (cx, bottom), - "topleft": (left, top), - "topright": (right, top), - "bottomleft": (left, bottom), - "bottomright": (right, bottom), - }[grab] - - -def has_neighbor(edge: str, name: str, before: dict[str, Box]) -> bool: - """Is there another window within a gap's reach on that side of this one, overlapping it""" - mx, my, mw, mh = before[name] - for other, (ox, oy, ow, oh) in before.items(): - if other == name: - continue - vertical_overlap = oy < my + mh and my < oy + oh - horizontal_overlap = ox < mx + mw and mx < ox + ow - if edge == "L" and vertical_overlap and 0 <= mx - (ox + ow) <= 80: - return True - if edge == "R" and vertical_overlap and 0 <= ox - (mx + mw) <= 80: - return True - if edge == "T" and horizontal_overlap and 0 <= my - (oy + oh) <= 80: - return True - if edge == "B" and horizontal_overlap and 0 <= oy - (my + mh) <= 80: - return True - return False - - -def run_case(platform: KdePlatform, spec: str) -> list[str]: - kde = platform.kde - W, H = platform.size - name, grab, d = spec.split(":") - dx, dy = (int(v) for v in d.split(",")) - - kde.komorebic("retile") - before = settled(platform) - tiles_before = tiles(platform) - ends = resize_ends(platform) - - px, py = press_point(grab, before[name]) - platform.pointer.drag((px, py), (px + dx, py + dy)) - kde.wait_for(lambda: resize_ends(platform) > ends, timeout=10) - after = settled(platform) - tiles_after = tiles(platform) - - held = GRABS[grab] - want = {"L": dx, "R": dx, "T": dy, "B": dy} - problems = [] - - # the frame the user sees: it did what was asked, give or take the client's cells - moved = {e: edges(after[name])[e] - edges(before[name])[e] for e in "LTRB"} - for e in "LTRB": - if e in held and has_neighbor(e, name, before): - if abs(moved[e] - want[e]) > CELL: - problems.append(f"frame {e} moved {moved[e]}, the pointer moved {want[e]}") - elif abs(moved[e]) > CELL: - why = "was not dragged" if e not in held else "has no neighbor" - problems.append(f"frame {e} moved {moved[e]} but {why}") - - # the layout, which is exact - tile_moved = {e: edges(tiles_after[name])[e] - edges(tiles_before[name])[e] for e in "LTRB"} - for e in "LTRB": - if e in held and has_neighbor(e, name, before): - if abs(tile_moved[e] - want[e]) > 2: - problems.append(f"tile {e} moved {tile_moved[e]}, the pointer moved {want[e]}") - elif abs(tile_moved[e]) > 1: - why = "was not dragged" if e not in held else "has no neighbor" - problems.append(f"tile {e} moved {tile_moved[e]} but {why}") - - # nothing else moves, but with a dragged edge: they share it - follows = [m for m in tile_moved.values() if abs(m) > 1] - for other in tiles_after: - if other == name: - continue - for e in "LTRB": - m = edges(tiles_after[other])[e] - edges(tiles_before[other])[e] - if abs(m) > 1 and not any(abs(m - f) <= 2 for f in follows): - problems.append(f"{other} tile {e} moved {m}: not with the dragged edge") - - # still a tiling - names = list(after) - for i, n1 in enumerate(names): - x, y, w, h = after[n1] - if x < 0 or y < 0 or x + w > W or y + h > H: - problems.append(f"{n1} {after[n1]} is off the screen") - for n2 in names[i + 1 :]: - ox, oy, ow, oh = after[n2] - if x < ox + ow and ox < x + w and y < oy + oh and oy < y + h: - problems.append(f"{n1} and {n2} overlap") - - print(f"{spec}: frame {before[name]} -> {after[name]}, tile edges {tile_moved}") - return problems - def _where(platform: KdePlatform) -> tuple[int, int]: found = re.search(r"x:(-?\d+) y:(-?\d+)", platform.kde.sh("kdotool getmouselocation")) @@ -225,13 +36,3 @@ def pointer_is_exact(platform: KdePlatform, checks: Checks, clients: list[Client gx, gy = _where(platform) worst = max(worst, abs(gx - x), abs(gy - y)) checks.check(f"the pointer is put within a pixel of where it is asked ({worst})", worst <= 1) - - -def edge_cases(platform: KdePlatform, checks: Checks, clients: list[Client]) -> None: - """Drags each edge and corner of `CASES` and checks the frames, the tiles and the neighbors.""" - for spec in CASES: - problems = run_case(platform, spec) - checks.check( - f"{spec}: " + ("as expected" if not problems else "; ".join(problems)), - not problems, - ) diff --git a/nix/tests/vm/lib/tests/fake_platform.py b/nix/tests/vm/lib/tests/fake_platform.py index 0113fb50..fb980293 100644 --- a/nix/tests/vm/lib/tests/fake_platform.py +++ b/nix/tests/vm/lib/tests/fake_platform.py @@ -203,7 +203,9 @@ class FakePlatform: if not self.follows_pointer: return for i, tile in enumerate(self.tiles[:-1]): - if abs(start[0] - (tile.x + tile.w + 4)) <= 1: + right_of_it = abs(start[0] - (tile.x + tile.w + 4)) <= 1 + left_of_next = abs(start[0] - (self.tiles[i + 1].x - 4)) <= 1 + if right_of_it or left_of_next: a, b = tile, self.tiles[i + 1] self.tiles[i] = Rect(a.x, a.y, a.w + dx, a.h) self.tiles[i + 1] = Rect(b.x + dx, b.y, b.w - dx, b.h) @@ -659,6 +661,8 @@ class FakePlatform: self.saved[path] = list(self.tiles) case ("load-resize", path): self._load_resize(path) + case ("retile",): + self._relayout() case ("minimize",): self.minimize(Client(self.containers[self.focus][0])) case ("unmanage",): diff --git a/nix/tests/vm/lib/tests/test_moved.py b/nix/tests/vm/lib/tests/test_moved.py index 37006819..928abff5 100644 --- a/nix/tests/vm/lib/tests/test_moved.py +++ b/nix/tests/vm/lib/tests/test_moved.py @@ -11,6 +11,7 @@ from komorebi_vm.core.scenarios import ( monocle, placement, queries, + resize, rules, title_rule, ) @@ -229,3 +230,45 @@ def test_a_daemon_that_does_not_follow_a_mode_change_fails_display_change() -> N clients = opened(platform, checks) display_change.run(platform, checks, clients) assert any("the daemon's monitor follows" in f for f in checks.failures) + + +def test_a_daemon_that_follows_the_pointer_passes_the_edge_cases() -> None: + platform = FakePlatform() + checks = Checks() + clients = opened(platform, checks) + base = checks.passed + resize.edge_cases(platform, checks, clients) + assert checks.failed == 0, checks.failures + assert checks.passed - base == 4 + + +def test_a_daemon_that_ignores_the_pointer_fails_the_edge_cases() -> None: + platform = FakePlatform(follows_pointer=False) + checks = Checks() + clients = opened(platform, checks) + resize.edge_cases(platform, checks, clients) + assert checks.failed == 4, checks.failures + + +def test_a_daemon_that_moves_the_other_edges_fails_the_edge_cases() -> None: + class Sloppy(FakePlatform): + def resize(self, start: tuple[int, int], dx: int) -> None: + super().resize(start, dx) + # the third tile is moved too, though no edge of it was dragged + a = self.tiles[2] + self.tiles[2] = Rect(a.x + dx, a.y, a.w, a.h) if dx else a + + platform = Sloppy() + checks = Checks() + clients = opened(platform, checks) + resize.edge_cases(platform, checks, clients) + assert any("outside the work area" in f or "overlap" in f for f in checks.failures) + + +def test_a_platform_with_no_pointer_skips_the_edge_cases() -> None: + platform = FakePlatform(pointer=False) + checks = Checks() + clients = opened(platform, checks) + base = checks.passed + resize.edge_cases(platform, checks, clients) + assert (checks.passed, checks.failed) == (base, 0) diff --git a/nix/tests/vm/suites/drag-resize/test.py b/nix/tests/vm/suites/drag-resize/test.py index 6716afcc..8078824e 100644 --- a/nix/tests/vm/suites/drag-resize/test.py +++ b/nix/tests/vm/suites/drag-resize/test.py @@ -1,8 +1,9 @@ # Resizing a tile by dragging its edge, in a Plasma session, with a pointer device the test drives # from inside the guest (`komorebi_vm.Pointer`). What only a real KWin and a real pointer can tell is in -# `komorebi_vm.platforms.kde.extras.drag_resize`: edges and corners of three tiles are grabbed and -# dragged, and what happened is checked against what a user expects. The shared scenarios -# (`resize`, `focus_follows_mouse`) run on Windows too and make one drag and the focus changes. +# `komorebi_vm.platforms.kde.extras.drag_resize`: that the pointer is put to the pixel. The shared +# scenarios run on Windows too: `resize.edge_cases` grabs edges and corners of three tiles and drags +# them, and checks what happened against what a user expects; `resize.run` makes one more drag, and +# `focus_follows_mouse` the focus changes. from komorebi_vm import Checks, Kde, Pointer from komorebi_vm.core.platform import Client from komorebi_vm.core.scenarios import focus_follows_mouse, resize @@ -53,7 +54,7 @@ args = (platform, checks, clients) run_suite( checks, platform_only("kde", kde_drag_resize.pointer_is_exact, *args), - platform_only("kde", kde_drag_resize.edge_cases, *args), + shared(resize.edge_cases, *args), shared(resize.run, platform, checks, clients), shared(focus_follows_mouse.run, platform, checks, clients[0], clients[2]), )