From 3830bb27e966954c3f4256f99dfdaf9b8d6ba3fa Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Fri, 30 Oct 2026 14:07:30 -0700 Subject: [PATCH] feat(nix): title_rule asserts what kfw does: a rule decides when a window opens --- .../komorebi_vm/core/scenarios/title_rule.py | 44 +++++++++++-------- nix/tests/vm/lib/tests/fake_platform.py | 6 +-- nix/tests/vm/lib/tests/test_moved.py | 10 ++--- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/nix/tests/vm/lib/komorebi_vm/core/scenarios/title_rule.py b/nix/tests/vm/lib/komorebi_vm/core/scenarios/title_rule.py index 37b47d26..adeee289 100644 --- a/nix/tests/vm/lib/komorebi_vm/core/scenarios/title_rule.py +++ b/nix/tests/vm/lib/komorebi_vm/core/scenarios/title_rule.py @@ -1,48 +1,54 @@ -"""A rule that matches a title decides when the window has its title.""" +"""A rule decides when a window opens: a title change later does not make the daemon look again.""" from komorebi_vm.core.checks import Checks from komorebi_vm.core.platform import Client, Platform +from komorebi_vm.core.scenarios.support import QUIET PENDING = "pending-rule" RENAMED = "renamed-rule" +MANAGED = "managed-before" +MANAGED_RENAMED = "managed-after" +AFTER = 6 def run(platform: Platform, checks: Checks) -> None: - """A window that opens with a title the ignore rule matches is left alone, and tiled once it - gives itself another title. + """A window that opens with a title an ignore rule matches is left alone, and stays so when it + gives itself another title; a window that is managed stays managed when it renames itself. - The daemon runs with its windows tiled; the window is closed at the end, and the rule stays. + The daemon runs with its windows tiled; the windows are closed at the end, and the rule stays. """ platform.komorebic("ignore-rule", "title", PENDING) before = platform.state().managed() - # the window renames itself after the daemon has had time to decide about the first title - platform.spawn(PENDING, rename_to=RENAMED, after=6) + platform.spawn(PENDING, rename_to=RENAMED, after=AFTER) renamed = Client(RENAMED) checks.check( "a window the ignore rule matches by its title is left alone", - not platform.wait_for(lambda: platform.state().managed() != before, timeout=2) - and platform.os_window(Client(PENDING)) is not None, + platform.state().workspace_of(PENDING) is None and platform.state().managed() == before, ) checks.check( - "once it has a title the rule does not match, it is tiled", - platform.wait_for( - lambda: ( - platform.os_window(renamed) is not None and platform.state().managed() == before + 1 - ), - timeout=30, - ), + "it gives itself another title", + platform.wait_for(lambda: platform.os_window(renamed) is not None, timeout=30), ) - window = platform.os_window(renamed) checks.check( - "... and inside the work area", - window is not None and window.frame.inside(platform.work_area(), 2), + "... and the daemon leaves it alone: a rule decides when a window opens", + not platform.wait_for(lambda: platform.state().managed() != before, timeout=QUIET), ) platform.close(renamed) + platform.wait_for(lambda: platform.os_window(renamed) is None, timeout=10) + + platform.spawn(MANAGED, rename_to=MANAGED_RENAMED, after=AFTER) + kept = Client(MANAGED_RENAMED) + checks.check( + "a window that is managed when it renames itself stays managed", + platform.wait_for(lambda: platform.os_window(kept) is not None, timeout=30) + and platform.wait_for(lambda: platform.state().managed() == before + 1, timeout=10), + ) + platform.close(kept) checks.check( "closed, it leaves the daemon", platform.wait_for( - lambda: platform.os_window(renamed) is None and platform.state().managed() == before, + lambda: platform.os_window(kept) is None and platform.state().managed() == before, timeout=10, ), ) diff --git a/nix/tests/vm/lib/tests/fake_platform.py b/nix/tests/vm/lib/tests/fake_platform.py index f50ded50..1b4a1bea 100644 --- a/nix/tests/vm/lib/tests/fake_platform.py +++ b/nix/tests/vm/lib/tests/fake_platform.py @@ -78,7 +78,7 @@ class FakePlatform: panel: int = 0, ignores_panel: bool = False, second: Rect | None = None, - follows_renames: bool = True, + reevaluates_on_rename: bool = False, honours_ignore: bool = True, unmanages: bool = True, manages: bool = True, @@ -131,7 +131,7 @@ class FakePlatform: self.manages = manages self.let_go: list[str] = [] """The windows `unmanage` let go of, the last one at the end.""" - self.follows_renames = follows_renames + self.reevaluates_on_rename = reevaluates_on_rename self.honours_ignore = honours_ignore self.clock = 0.0 self.renames: list[tuple[float, str, str]] = [] @@ -253,7 +253,7 @@ class FakePlatform: for table in (self.exes, self.classes): if old in table: table[new] = table.pop(old) - if old not in self.unmanaged or not self.follows_renames: + if old not in self.unmanaged or not self.reevaluates_on_rename: for stack in [s for cs in self.spaces for s in cs]: stack[:] = [new if t == old else t for t in stack] self.unmanaged[:] = [new if t == old else t for t in self.unmanaged] diff --git a/nix/tests/vm/lib/tests/test_moved.py b/nix/tests/vm/lib/tests/test_moved.py index 0faeed08..9539696a 100644 --- a/nix/tests/vm/lib/tests/test_moved.py +++ b/nix/tests/vm/lib/tests/test_moved.py @@ -27,14 +27,14 @@ def opened(platform: FakePlatform, checks: Checks): # noqa: ANN201 return tiling.run(platform, checks) -def test_a_daemon_that_follows_a_rename_passes_title_rule() -> None: +def test_a_daemon_that_does_not_look_again_at_a_renamed_window_passes_title_rule() -> None: platform = FakePlatform() checks = Checks() opened(platform, checks) base = checks.passed title_rule.run(platform, checks) assert checks.failed == 0, checks.failures - assert checks.passed - base == 4 + assert checks.passed - base == 5 def test_a_daemon_that_manages_an_ignored_title_fails_title_rule() -> None: @@ -45,12 +45,12 @@ def test_a_daemon_that_manages_an_ignored_title_fails_title_rule() -> None: assert any("left alone" in f for f in checks.failures) -def test_a_daemon_that_misses_the_rename_fails_title_rule() -> None: - platform = FakePlatform(follows_renames=False) +def test_a_daemon_that_looks_again_at_a_renamed_window_fails_title_rule() -> None: + platform = FakePlatform(reevaluates_on_rename=True) checks = Checks() opened(platform, checks) title_rule.run(platform, checks) - assert any("it is tiled" in f for f in checks.failures) + assert any("leaves it alone" in f for f in checks.failures) def test_a_daemon_that_lets_go_and_takes_up_again_passes_handover() -> None: