Commit Graph
151 Commits
Author SHA1 Message Date
LGUG2Z 2be21aaa6d docs(repo): tiling_off passes on kfw, and lifecycle_hidden is in the table 2026-10-30 12:03:00 -07:00
LGUG2Z 74ddcce4d9 feat(nix): the tiling_off scenario
toggle-tiling leaves the windows where they are, a layout change moves
none of them, and toggled again every window is tiled where the layout
says. core-e2e passes 254 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 1e2b10eb86 docs(repo): pausing passes on kfw, and tiling_off is in the table 2026-10-30 12:03:00 -07:00
LGUG2Z 6e111411e7 feat(nix): the pausing scenario
A window that opens while the daemon is paused is not managed; after
toggle-pause again the next one is, and every window is where the
layout says. core-e2e passes 248 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 0d8f073dc8 docs(repo): promoting and flipping pass on kfw, and pausing is in the table 2026-10-30 12:03:00 -07:00
LGUG2Z d58353d22e feat(nix): the flipping scenario
flip-layout horizontal puts every window where the mirror of its place
is, with every window where the layout says, and flipping again gives
the places back. core-e2e passes 244 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 63d5833a84 feat(nix): the promoting scenario
promote puts the focused window on the first tile and keeps its focus,
with every window where the layout says. core-e2e passes 241 checks on
KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 211acae92d docs(repo): workspace_moves, resize_commands and promoting in the table 2026-10-30 12:03:00 -07:00
LGUG2Z 9b1162dcbe feat(nix): the resize_commands scenario
resize-axis horizontal increase widens the focused window and decrease
gives the width back, with every window inside the work area and none
over another, and no pointer. core-e2e passes 237 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z a8b30e1c1b feat(nix): the workspace_moves scenario
move-to-workspace takes a window to another workspace and the focus
with it, focus-last-workspace goes back and forth, and moving the window
home tiles everything again. core-e2e passes 233 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 4a3b0c4b14 docs(repo): layouts, floating, minimizing and padding, and a padding finding
The scenario table has the four new scenarios, which pass on both
ports, and maximizing, which kfw has not run. The state's padding and
the frames' disagree on both ports, by 10 px on kfde and 7 on kfw.
2026-10-30 12:03:00 -07:00
LGUG2Z f1ea111fd0 feat(nix): the maximizing scenario
toggle-maximize gives a window the work area, with the others where they
were and the daemon naming it as the maximized window; toggled again,
every window is tiled where the layout says. core-e2e passes 225 checks
on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z d4d356c70e feat(nix): the padding scenario, and padding in Snapshot
Raising the workspace padding moves the windows in from the edge by as
much, and raising the container padding leaves them less room; putting
the padding back gives back the windows' frames. The measure is of the
padding the scenario sets itself: on KDE the state says 0 and 0 while
the windows sit 10 px in, and the first run's padding is not what the
state says. Workspace has workspace_padding and container_padding now.
core-e2e passes 220 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 4471cc01a8 feat(nix): the minimizing scenario, and Platform.minimize
A minimized window leaves its room to the others, and a restored one
takes it back. Platform.minimize is new: the title bar button on KDE;
activate restores. core-e2e passes 213 checks on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z 4835907b2e feat(nix): the layouts and floating scenarios
layouts changes the layout of the first workspace to each of eight, with
three windows and with five, and checks every window is where the
daemon's layout says, inside the work area and clear of the others.
floating floats a window, checks the others take its room, and that
floating it again tiles it back. Both run in core-e2e: 209 checks pass
on KDE.
2026-10-30 12:03:00 -07:00
LGUG2Z b4dffcaa7a docs(repo): focus_follows_mouse passes, and five green runs on kfw
The scenario's failure was its own: it waited for a focus that already
held. Five consecutive runs of 14 scenarios on Windows passed, hotplug
and focus_follows_mouse apart.
2026-10-30 12:03:00 -07:00
LGUG2Z 4158f63557 fix(nix): focus_follows_mouse rests the pointer over the focused window
On again, the scenario moved the pointer over the first window, which
already had the focus, so it waited for nothing and moved on to the
second at once. A platform that follows the pointer by a hover delay
never saw it enter the first. The pointer now rests there for a
moment, as it would for a person.
2026-10-30 12:03:00 -07:00
LGUG2Z 4c8404dfa0 docs(repo): the scenarios there are, restart_with and known failures 2026-10-30 12:03:00 -07:00
LGUG2Z 7e20061763 docs(repo): focus follows mouse, on again, fails on kfw
The last check of focus_follows_mouse fails on a Windows guest after
the setting was turned off with the pointer on a window and on again;
disable then enable works. The cause is not known, and the scenario is
unchanged.
2026-10-30 12:03:00 -07:00
LGUG2Z ddab35b5b9 feat(nix): the focus_follows_mouse scenario, with a pointer
With focus follows mouse on, the pointer over a window gives it the
focus, and the daemon follows; turned off, it moves nothing; turned on
again, it follows again. The scenario needs a pointer and is skipped
without one. The toggle passes --implementation windows, which kfw's
subcommand requires. drag-resize runs it after resize.
2026-10-30 12:03:00 -07:00
LGUG2Z 7e271955d7 docs(repo): startup_rules passes on Windows too 2026-10-30 12:03:00 -07:00
LGUG2Z efeaafad28 feat(nix): the startup_rules scenario, workspace rules of a file
A window that was open before the daemon, and one that opens after, go
to the workspace a rule in the config names, by the start of their
title; a window no rule names stays on the first. The rule is in the
file, so what is checked is how the file is read at start. core-e2e
runs it as section 12a2.
2026-10-30 12:03:00 -07:00
LGUG2Z 157b3d5e8c docs(repo): kfw keeps a monitor that was unplugged, sometimes
Reported by the kfw session from a probe: the reconciliator sees the
removal and loops on it, and state lists two monitors for as long as it
is watched. It passes in some runs, so it is not a known failure; the
check stays red when it fails.
2026-10-30 12:03:00 -07:00
LGUG2Z 00aec79ee4 docs(repo): the same overlapping-tiles mutation turns kfw red
65 checks failed over 14 scenarios on Windows, all about geometry; rules
and placement, which check only order, stayed green.
2026-10-30 12:03:00 -07:00
LGUG2Z 45fa501d20 docs(repo): a daemon whose tiles overlap turns core-e2e red
Run once on a real KWin with every tile 200 pixels too wide, and not
committed: seven checks failed, all about tiles on each other, and the
other 139 passed.
2026-10-30 12:03:00 -07:00
LGUG2Z f5fad1b2e6 docs(repo): the three ways kfw's placement type is described
Its docs say a place is a string or an integer, its deserializer takes
a string only, and its schema describes objects. Nothing tests the
integer.
2026-10-30 12:03:00 -07:00
LGUG2Z b1e041f53d feat(nix): placement takes known failures by case
A port that cannot start with a case's rules, or orders its windows
otherwise, is recorded as a known failure for that case, and the other
cases run on. kfw does not accept the place as a JSON number, so
BEHAVIOUR.md lists the case as a known failure there.
2026-10-30 12:03:00 -07:00
LGUG2Z b5e9cf5301 feat(nix): the placement scenario, and Platform.restart_with
Where a window that opens goes, from the placement rules of the
config: none, Primary, a number as a number and as text, and rules by
title for the first and the last place. restart_with starts the daemon
afresh with a komorebi.json the scenario gives. KdePlatform.spawn
quotes the title, which a title with spaces needs. core-e2e runs it as
section 12a.
2026-10-30 12:03:00 -07:00
LGUG2Z 7b8a559590 docs(repo): what a daemon that starts again takes up on kfw
A window kfw had cloaked is uncloaked by the stop and managed again on
the first workspace. A minimized window is left minimized and is not
managed. The lifecycle scenario counts only the windows in view.
2026-10-30 12:03:00 -07:00
LGUG2Z 2afe3554ee docs(repo): what is not covered on Windows, and the sweep under load
The pointer on kfw reaches the first display only, because QMP's
absolute tablet is mapped there. The commands sweep passed in the two
runs that had the host to themselves and failed in the two that ran
beside a VM suite and a build.
2026-10-30 12:03:00 -07:00
LGUG2Z 88a431ce8a docs(repo): resize, rules and lifecycle pass on Windows
kfw's 0ffc502c fixes the resize shortfall: a 60 pixel drag widens the
left tile by exactly 60. The commands sweep passes with a second
display, and rules, hotplug and lifecycle pass on a Windows guest.
The earlier sweep failures came with a kfde suite running beside it.
2026-10-30 12:03:00 -07:00
LGUG2Z 8fc7c961d0 feat(nix): known failures, with unknown_monitor the first
Checks.known_failure records a check that fails for a reason that is
to be followed up on: the suite does not fail, the totals say how many
known failures there are, and one that holds fails the suite so the
marker goes. unknown_monitor takes the reason, and core-e2e runs it
last, because the window it loses stays lost. BEHAVIOUR.md says so.
2026-10-30 12:03:00 -07:00
LGUG2Z 54d866f83a feat(nix): rules, a window the cleared rules matched stays put
After clear-all-workspace-rules a window that the old rules matched
opens on the workspace in view and stays there. The first window of
that title is closed before the next opens, because the title is how
a window is named on both ports.
2026-10-30 12:03:00 -07:00
LGUG2Z 6dbc4d8f63 feat(nix): the lifecycle scenario, a daemon that starts again
The daemon stops, every window stays, and a daemon that starts again
manages the windows that were in view, tiled inside the work area and
clear of each other, and also a window opened afterwards. The fake
platform learns to stop and to start with no memory of workspaces.
core-e2e runs it before its final stop.
2026-10-30 12:03:00 -07:00
LGUG2Z 93c786242b feat(nix): give the sweep's toggle-focus-follows-mouse its option
kfw declares the subcommand with arg_required_else_help, so without an
argument it prints help and exits 2, although the option has a default.
kfde accepts the same option, so the sweep passes it explicitly:
--implementation windows, the default on both ports.
2026-10-30 12:03:00 -07:00
LGUG2Z 32b08d1b77 feat(nix): unknown_monitor, a window sent to no monitor must stay managed
The scenario sends the focused window to monitor 7 with send-to-monitor and
move-to-monitor, which no display has, and checks that the daemon still
manages every window. A port may refuse or ignore the command, but a window
that was managed has to stay so: one that is not is left on the screen with
nothing tiling it.

It found a bug in both ports. kfw managed one window fewer than the OS had
afterwards (seen by hand on a Windows guest), and kfde failed it in
core-e2e on a real KWin: move_container_to_monitor takes the focused
container out of its workspace before it looks the monitor up, so the
error for a monitor that is not there comes after the container is gone.
It is not fixed, so the scenario is not in core-e2e, which would fail;
BEHAVIOUR.md has the finding. Its unit tests run it against a fake that
loses the window and one that ignores the command.
2026-10-30 12:03:00 -07:00
LGUG2Z b22ae83e6a feat(nix): the command sweep plugs in a second display when it needs one
The sweep has commands that name the second monitor, send-to-monitor 1 and
the ones after it, so it needs two displays. The KDE suite runs with two
outputs and never noticed. On Windows, with one display, the first run of
the sweep reported that after send-to-monitor 1 kfw managed one window
fewer than the OS had, and every command after it was reported unhealthy;
whether that is kfw losing a window sent to a monitor that does not exist
has not been confirmed by hand. The sweep now plugs in a display first if
the platform has one, and a fake with one display shows it does.
2026-10-30 12:03:00 -07:00
LGUG2Z 631d8267f3 docs(repo): what the shared scenarios found on kfde and on kfw
A table of the scenarios against the two ports, with where each result
comes from, the resize finding and its cause (kfw reads the rectangle a
drag started from when it handles the start event, about 100 ms after the
drag began, so the distance it measures is short by what the window moved
in that time, and more so for a longer drag), what the scenarios had to
allow for, and what is not covered.
2026-10-30 12:03:00 -07:00
LGUG2Z 1c0bc9eae9 feat(nix): the commands, rules and hotplug scenarios, for every platform
commands is every layout, a sweep of 216 commands and the commands that
only print, each of which must be understood and leave the daemon healthy
(it answers state and manages the windows the OS has). A command the port
lacks, which komorebic says with 'unrecognized subcommand', is skipped with
its name, which is what a behaviour matrix is made of: Checks.skip records
it and finish prints how many. The commands suite runs it instead of its
own copy of the list: 270 checks pass, none skipped.

rules gives the daemon an initial rule, a rule that is not, and an ignore
rule, by title, and checks where each window goes. It found that
enforce-workspace-rules applies initial rules again on purpose, so the
scenario asks whether the daemon sends the window back on its own.

hotplug unplugs a display, plugs one in and sends a window to it, and
starts by plugging one in if the platform has only one. Platform gets
displays, add_display and remove_display, and KdePlatform does them with
kscreen-doctor. The hotplug suite runs it: 34 checks pass.

core-e2e runs rules after the others, then leaves a window for the stop to
leave behind: 130 checks pass on KVM. One run failed the check that the
daemon had exited after komorebic stop and the next did not; the cause is
not known, and the suite now prints the unit's status when it happens.
Snapshot.workspace_of tells which workspace has a window.
2026-10-30 12:03:00 -07:00
LGUG2Z d7ed89579e docs(repo): monocle and closing pass on Windows too
Seven of the eight shared scenarios pass on a Windows 11 guest under QEMU
against kfw's daemon, as the session that ran them reports. The eighth,
resize, ran there and found that the edge moves less than the pointer; an
unmanaged window followed the same drag exactly, so the shortfall is in
what kfw does with the drag.
2026-10-30 12:03:00 -07:00
LGUG2Z ed792445d0 feat(nix): the monocle and closing scenarios, and Platform.close
monocle toggles monocle on the focused window and checks that it fills the
work area up to the layout's padding, that the state has it as the monocle
container, that every other window is put away, that it keeps the focus,
and that toggling back puts every window in view on the tile it had.
closing closes a window and checks that the OS has no frame for it, that
the daemon manages one window fewer, and that the windows left in view
take more room between them, inside the work area and clear of each other.

Platform.close closes a window as its button would; KdePlatform does it
with kdotool. The fake daemon models monocle and closing, and its
os_window now knows the workspace a window is on, which the workspaces
scenario had passed without. core-e2e runs both: 120 checks pass on KVM.
2026-10-30 12:03:00 -07:00
LGUG2Z 37b75f8205 feat(nix): the resize scenario and a pointer on the Platform
Platform.has says whether a platform can do what a scenario needs, and
Platform.pointer is a Pointer (move, down, up, drag) where it has one;
KdePlatform takes the pointer of a session node. scenarios.resize drags the
edge two tiles share by 60 pixels and checks that the tiles that end at the
edge are that much wider, the ones that start after it start that much
later and end where they did, nothing moves up or down, and tiles that do
not touch the edge are where they were. A platform with no pointer skips
it, and says so.

The fake daemon has a pointer that moves an edge. The scenario runs on KDE
at the end of drag-resize: 19 checks pass on KVM. Its first run failed one
check that was the scenario's: both tiles of a BSP column share the dragged
edge, and the check took the second for one that had not moved.
2026-10-30 12:03:00 -07:00
LGUG2Z e385bace05 test(nix): Snapshot against states recorded from both ports
core-e2e writes the komorebic state of kfde, with three tiled windows and
with one stacked onto another, into its output, and the files are kept in
tests/fixtures beside kfw's three, recorded from a Windows guest (tiled,
stacked, one window floated). test_recorded.py reads all five with the
same checks: three containers of one window, a layout rectangle for each
inside the work area, each window where its container's rectangle is up to
a terminal cell (foot rounds to cells, kfw's test window does not), and a
stack that is a container of two whose focused window is the one the ring
names. Nothing in the parser had to change; the checks passed on the first
real kfw state.

The scenes written from the serializers stay for the shapes no run has
recorded. The sync script copies the fixtures too. The workspaces scenario
prints which windows are in view after the switch: one run of core-e2e
failed that check and passed on the next, and the log did not say which
window had been in view.
2026-10-30 12:03:00 -07:00
LGUG2Z 22a5dbdb32 docs(repo): the shared scenarios run on two platforms
tiling has run against kfw's daemon on a Windows 11 guest under QEMU, 10 of
10 checks, with this core copied unchanged; the other four scenarios have
not run there yet. Says so in vm-tests.md, and what keeps the copy in
step.
2026-10-30 12:02:55 -07:00
LGUG2Z 030e580a49 build(repo): sync the neutral core to kfw while it is on its way there
scripts/sync-e2e-core copies komorebi_vm.core and the unit tests that
belong to it into another directory, and --check says whether the copy is
in step, so that kfw's Windows platform can be written against the code it
will run with while the move is not made. This repository is the source
until the move, and the script goes with it.

Two of those tests imported Rect and Checks from komorebi_vm, which pulls
in the KDE half; they import them from komorebi_vm.core now. The copy
passes its 25 tests in a directory with nothing but pytest and Pillow.
2026-10-30 12:02:55 -07:00
LGUG2Z c59f5dddd0 build(nix): scale of 1.5 on every Linux host, and what the suites take on WSL 2
latency measured a p95 of 128.9 ms against its 100 ms times scale on the
WSL2 machine, under nested KVM with nothing else running, where x86-1 had
passed it at scale 1. Every Linux host is no faster than a Mac to the
suites that time the daemon, so scale is 1.5 on all of them: latency
passes at it with a p95 of 132.4 ms against 150 ms. The run-to-run
difference (p50 46.0 ms, then 70.0) is as large as the margin left, which
PLATFORM.md says.

PLATFORM.md records the wall times of the suites on this machine. All 33
were run there after the library was split: 32 passed at scale 1, and
latency is the one that failed. The other 32 were not rerun at 1.5, which
changes their derivations.
2026-10-30 12:02:55 -07:00
LGUG2Z 875a9ef41d feat(nix): the workspaces scenario, for every platform
workspaces sends the focused window to workspace 1, checks that it is put
away and that the daemon has it there while the others stay in view,
switches to workspace 1 and checks that only that window is in view and has
the focus, and switches back.

hidden now says a window is out of sight for any reason the daemon has: on
KDE that is the parking desktop and also a desktop that is not the one in
view. Snapshot's workspace, containers and focused_title take the focused
workspace when none is given, and the fake daemon has two workspaces. The
scenario passes in core-e2e on KVM: 106 checks.
2026-10-30 12:02:55 -07:00
LGUG2Z e3cc27035a docs(repo): how to write a scenario for every platform 2026-10-30 12:02:55 -07:00
LGUG2Z 0f73ba3a55 feat(nix): the stacks scenario, and Platform.hidden
hidden says that a window exists but the daemon has put it away: the others
of a stack, here, and later those of another workspace or behind a monocle.
It is a window on the parking desktop on KDE and will be a cloaked one on
Windows. scenarios.stacks stacks the focused window onto its neighbor,
cycles the stack, checks that the window in view has the focus and fills
the tile the first had, and takes the stack apart.

The scenario's fake daemon now models stacks. Running it on KDE found a bug
in Snapshot: focused_title took the first window of the focused container,
and a stack's focused window is the one its ring names. Snapshot keeps that
index now. core-e2e runs the scenario after the others: 98 checks pass on
KVM.
2026-10-30 12:02:55 -07:00
LGUG2Z c861f4f789 feat(nix): the focus and moving scenarios, for every platform
focus moves the focus with focus and cycle-focus and checks that the OS and
the daemon's state agree on the window that has it and that no window moved.
moving swaps the focused window with its neighbor with move and puts every
window back with cycle-move, and checks that the focus stays with it. Both
read the windows through the Platform, so they are what kfw's suite will
run.

Their unit tests run against a fake daemon that follows the commands over
three tiles, and against two that do not (a move that moves nothing, a move
that loses the focus). core-e2e runs them after tiling on KDE: 85 checks
pass on KVM.
2026-10-30 12:02:55 -07:00