BEHAVIOUR (a small fix, KDE's behaviour). Router arm ManageRule and the method
add_ignore_rule used an inline loop that skipped a rule when any simple rule had the same
id, whatever its kind: 'ignore-rule class foo' after 'ignore-rule exe foo' was dropped.
They now call komorebi_config::matching::push_simple_rule (kind and id), as KDE does
(its test pins it), and the ManageRule arm is the KDE text.
Verified: fast-check macOS PASS; fake-CC cargo clippy -p komorebi-macos --all-targets
-D warnings clean; tools/format-all --check --tree mac clean. Not verified: any macOS
run. Verified on the Mini: not yet. Hand check row added.
Pure formatting by the same nightly rustfmt invocation the nix fmt check uses (tools/format-all, edition 2024, the tree's rustfmt.toml). No code change. Applied last on the candidate because it touches many files other agents were editing. Verified: tools/format-all --check --tree windows passes afterwards; light gates (fast-check) after all three.
Repeats the function comparison of sections 17/18/20 on the three
window_manager.rs files at wip-cand8: identical on all three is 43
functions and 696 lines (15.6% of Windows, 18.5% of KDE, 15.3% of macOS),
at most four lines apart 81 functions (46% of KDE at best), identical on
KDE and macOS 102 functions (64% of KDE). The all-three threshold of 60%
is not met even with every near-identical function converged. Records the
struct analysis (event type, platform field types, daemon-only methods)
and why the struct move is not taken unattended, and the KDE+macOS subset
as the owner's option. Docs only. Verified: counts from the fnsplit and
cmp3 scripts at the cand8 tree; claims about field types read from the
three WindowManager struct definitions.
Moves KDE's push_simple_rule (and its test) to komorebi_config::matching: add a simple
rule that matches id as a kind with the legacy strategy unless a simple rule of that
kind and id is there already; a rule of another kind with the same id and a composite
rule do not stop it. The KDE daemon and, next, the macOS daemon use it for the ignore and
manage rules. Nothing calls it yet.
Verified: native cargo test -p komorebi-config 5 + 16 + 9 + 1 passed.
format-all re-executes itself under 'nix develop' to get the nightly rustfmt, but it did so after its argument loop had shifted every argument away, so the re-run always used the defaults (--check, all trees): '--apply' silently only checked. The original arguments are now saved before parsing and passed on. Found when applying the final formatting of candidate 8: '--apply --tree windows' printed diffs and changed nothing. Verified: bash -n; the revisions after this one are the result of running --apply.
Section 22.1 of core-model.md: KDE and macOS refuse every message before
the router's match while the focused window is not managed
(handle_unmanaged_window_behaviour); Windows gates inside 18 functions.
CommandHost gets a defaulted gate_message(&mut self, &SocketMessage)
that lets everything through (the Windows form, its impl is untouched);
the KDE and macOS impls call handle_unmanaged_window_behaviour and their
routers call the hook where they called the method, so behaviour is
identical per daemon. komorebi-core now depends on komorebi-protocol
(for SocketMessage; Cargo.lock gains that one edge).
This is the groundwork only: the router itself is still per daemon,
because a shared router needs WindowManager<P> in core (see the
struct-move analysis in core-model.md). No BEHAVIOUR change.
Verified: KDE cargo test -p komorebi-linux 670 passed, 0 failed; fake-CC
clippy -D warnings for the four macOS packages passes; cargo clippy -p
komorebi-windows -p komorebi-core --all-targets -D warnings passes;
tools/format-all --check clean. Not verified: KDE VM, macOS hand check
(no behaviour change expected).
Candidate 8 (second draft): cbc40c03 (cand7 + pointer-picks-monitor + thin-events note + bar wgpu fallback + macOS deep dedup) plus wip-u-win-deep (PlatformMonitorId alias, promote_focus_container_idx hook, the WindowManager hook list) and wip-u-fmt (tools/format-all, nix fmt over the nightly rustfmt, deny clarify entries for Windows and KDE). Conflicts, if any, are resolved here.
clippy::useless_conversion: the values are already komorebi_backend::MonitorId
since the Backend id-type change, so .into() converts to the same type.
One line is joined where the shorter call now fits, so rustfmt stays happy
for the touched lines. Test code only, no behaviour change.
Verified: native clippy --all-targets -D warnings over komorebi-linux,
komorebic, komorebi-client, komorebi-hotkeys, komorebi-core, the shared
crates the KDE flake sees and version-linux/komorebic-linux passes.
Candidate 8 (draft): wip-cand7 plus wip-u-deep (which contains wip-u-ptr: shared focus_workspace_number(s), KDE and macOS get the pointer-picks-monitor preamble, the const removed, and the thin-events design note), wip-u-bar4 (eframe wgpu fallback for the Windows bar, scenario rules) and wip-u-mac-deep (ContainerExt removed, nine shared window_manager functions identical on KDE and macOS, five macOS router arms as named methods). Conflicts, if any, are resolved here.
Section 22 of docs/dev/core-model.md, the hook list for kfde: why the
unmanaged-window gate was NOT moved from 18 Windows functions to the router (the
router form refuses every message, an arm that works before its gated call, the
layer split of FocusWindow/MoveWindow/CycleFocusWindow, and callers that bypass
the router), with the defaulted gate_message hook that expresses both shapes; the
WindowManagerPlatform hooks (new, init, stop, restore_all_windows, resize_window,
focus_workspace plan/execute, enforce_workspace_rules, the cross-monitor DPI
check, the floating-window functions); a BorderPlatform hook for the border calls
and the monocle floating hide/restore; wallpaper, window handling behaviour,
workspace names and custom layouts; the result of the cosmetic re-read (nothing
left); and an order for the implementation with the Windows gates.
Docs only.
The Windows fmt check ran the stable `cargo fmt` over the stubbed workspace
source: it failed on the empty stub lib.rs files of the other platforms, on
`mod linux;`/`mod macos;` of the shared entry files (the Windows source does
not have those modules), and its stable rustfmt ignores the nightly options of
rustfmt.toml. It is now a runCommand running tools/format-all --tree windows
with the nightly rustfmt over the files of the Windows source (build.real, no
stubs), file by file with skip_children.
tools/format-all runs the same check locally (--check, or --apply to format;
--tree windows|mac|kde|all; the nightly rustfmt from $RUSTFMT, PATH or the
root dev shell). mac is the explicit-file invocation of the kfm check, kde is
`cargo fmt -p ...` as the KDE check does.
Verified: in a throwaway copy of wip-cand7, --apply formats 17 Windows files
(+211 -88; crates/ komorebi-backend, bar-core, core, protocol, bar windows
modules, client windows.rs, komorebi-gui, testwin) and 12 KDE files
(+22 -29); afterwards --check passes for windows, mac and kde. The formatting
itself is not in this revision (other agents are editing those files). The nix
attribute evaluates; not built.
clippy::ptr_arg (rustc 1.99 in the nix KDE clippy check) rejects &PathBuf
where &Path will do. Callers passing &PathBuf still compile by deref. No
behaviour change. Verified: native clippy --all-targets -D warnings over
the KDE packages passes (see the next revision for the exact set).
komorebi-core is in the workspace default-members since the review fixes, so a bare clippy --all-targets -D warnings now covers its test files. crates/komorebi-core/tests/commands.rs (wip-u-cmd) had two findings that only show there: an unused Result of new_container_for_window (now unwrap()ed: the stub window cannot fail) and a never-read field pointer_for_all (removed: the Windows switch is tested through the associated const in its own host type). No behaviour change; verified: cargo test -p komorebi-core and the Windows clippy (bare, default-members).
Design only, nothing implemented (D-coord-13 (c)). Lists the three
event vocabularies read from the window_manager_event.rs files (only
Destroy, Show and Minimize share a name on all three), proposes a small
CoreEvent<W> produced by the platform adapters, sketches the shared
handlers for Gone, Appeared and Minimized with platform hooks, orders
the prerequisites (unmanaged check converged, shared WindowManager
state, PlatformMonitorId, border hooks) and names the risks (side-effect
order per arm, macOS FocusChange without a Window). Verified: docs only;
claims about handler arms rest on section 17 and were not re-measured.
docs/dev/bar-e2e.md: why the golden guest cannot use glow, how the bar falls
back to wgpu (WARP), what the scenario now counts as real and as a skip (both
renderers failing, naming both errors), the log level kept in bar.out, the
measured cost (622 -> 664 crate versions in the Windows bar tree, one new lock
entry; build time and exe size not measured) and the risks.
Verified: not applicable (docs). The checks of the stack: see the other
revisions.
Records the container API unification (ContainerExt gone, Workspace::hide_spot), the nine
window manager functions that are now identical on KDE and macOS (76 of 92 shared
function names identical, 1521 of KDE's 2713 stripped lines: 56%), the five router arms
that became methods, the four that stay macOS's, and the exact differences between
the macOS update and update_shared (a scrolling workspace returns early and skips the
resize-dimensions fix-up and places the windows itself; the SkyLight batch is wider; the
rest folds with hooks), which is why update is not adopted without the owner's decision.
Verified: documentation only.
The Windows promote_focus_to_front focused the first column of a custom layout
that has no primary column (first_container_idx(primary_idx().unwrap_or(0)))
where the shared primary_container_idx fails for it; this was one of the
Layout::Custom differences of core-model.md section 18. WorkspacePlatform gets
promote_focus_container_idx(layout) -> usize, defaulting to
primary_container_idx(layout).unwrap_or(0), so a shared promote_focus_to_front
can call it on every platform; the Windows platform overrides it with the exact
expression it had (default layouts 0, custom layouts the first container of the
primary column, else of column 0). window_manager.rs calls the hook. A core test
pins the default for the default layouts.
Not a behaviour change on Windows (the same expression, moved). KDE and macOS
see a new defaulted trait method only. Verified: tools/fast-check native (core
tests), bare Windows clippy -D warnings, KDE check + lib tests, macOS fake-CC
type-check PASS; e2e: commands (promote-focus), layouts (custom layout).
The root and KDE deny.toml only clarified the old crate names, so
cargo deny failed with unlicensed for the crates of the unified workspace.
The root deny.toml gets entries (LicenseRef-Komorebi-2.0, as for the
existing ones) for komorebi-backend, -bar-core, -collections, -config, -core,
-protocol, -settings, -transport, komorebic-core, komorebi-e2e-agent and
komorebi-testwin; the KDE one for the same crates that it sees. The KDE deny
check also excludes komorebi-bar-core, which is not a KDE dependency and
brings the git egui-phosphor source that the KDE policy does not allow.
Verified: cargo deny --offline --workspace with the flake's --exclude lists
and `check --config <deny.toml> bans licenses sources` (nix shell
nixpkgs#cargo-deny): root, KDE and macOS: bans ok, licenses ok, sources ok
(before: licenses FAILED for root and KDE, sources FAILED for KDE); taplo
--check passes on both files. Not built in nix.
Candidate 7: wip-cand6 plus wip-u-rulematch (one window-rule matcher in komorebi-config), wip-u-stall2 (lock-holder guard, should_manage before the lock, reaper unlock, heartbeat), wip-u-bar3 (bar e2e scenario fix, skip when the guest cannot draw, bar config tests) and wip-u-cmd (komorebi_core::command: 16 shared router arms). Conflicts, if any, are resolved here.
All three daemons now let the pointer pick the monitor for every shared
command that has the preamble, so the const has no reason left. The
shared functions always call focus_the_monitor_under_the_pointer; the
three CommandHost impls lose the const (Windows had it true already, so
nothing changes there). The core test of the switch becomes
the_pointer_picks_the_monitor_..._on_all_platforms. known-issues item 1
is marked resolved and core-model.md section 18 text is updated.
No behaviour change in this revision beyond the previous two.
Verified: komorebi-core tests all pass (command tests 18); KDE cargo test
-p komorebi-linux 670 passed, 0 failed; fake-CC clippy for the four macOS
packages passes; cargo clippy -p komorebi-windows --all-targets -D warnings
passes. Not verified: Windows tests or e2e (cannot run on Linux).
The bar now falls back to wgpu (Direct3D 12, WARP) when glow has no OpenGL
context, so in the OpenGL-less golden guest the bar can open a window and the
window, stays-alive, daemon-restart and notify checks run for real. They are
skipped only when BOTH renderers fail, and the skip names both errors
(`skip ...: guest cannot draw: glow: ...; wgpu: ...`, taken from the bar's
"Error: glow: ...; wgpu: ..." line); any other early exit still fails. The
scenario starts the bar with RUST_LOG=info,wgpu_hal=debug,wgpu_core=warn so
bar.out keeps what wgpu says about its adapters on the first run, and prints
which renderer drew the window ("the bar draws with wgpu").
Unit tests: both renderers failing (classify + the error line), a bar that fell
back and runs (the glow warning is not an "Error:"), plus the earlier ones.
Verified: runner and library tests 163 passed; ruff clean on the scenario and
its test. NOT run: needs the win-e2e `bar` gate.
Deep dedup D-coord-13 (3), the part that is a move. BEHAVIOUR (a pure move; type-checked
and clippy-clean with the fake CC).
The inline arms of ToggleWorkspaceLayer (88 lines), ResizeWindowAxis (59),
SessionFloatRule, IgnoreRule and ReplaceConfiguration in process_command.rs become the
methods toggle_workspace_layer, resize_window_axis, add_session_float_rule,
add_ignore_rule(identifier, &str) and replace_configuration(&Path) (KDE's is &PathBuf, which clippy::ptr_arg flags) of the same
names as KDE's, with the bodies the arms had (de-indented, ending in Ok(())); the router
arms are now the same text as KDE's. Two spellings changed because the KDE
signature has them: the ignore rule's id is a &str (compared with ==, copied with
to_string()), and replace_configuration takes the run loop from self as the arm did.
What stays macOS's own and is not moved, because the body is the platform's:
Minimize and Close (AdhocWindow on the foreground element), DebugWindow and
ManageRule (role against class; no KDE method to match yet), and the macOS
bodies of the five moved methods (the role in the session float rule, the run loop in
replace_configuration, the animation suspension in resize_window_axis): they are
the methods' own differences now, behind the same names.
Verified: fast-check macOS PASS; fake-CC cargo clippy -p komorebi-macos
--all-targets -D warnings clean. Not verified: any macOS test or run. Verified on the
Mini: not yet. Hand check row added to docs/dev/macos-handcheck.md.
komorebi-core gets pub type PlatformMonitorId<P> = <P as MonitorPlatform>::Id,
the monitor counterpart of PlatformWindowId (blocker 5 of core-model.md
section 18). The Windows daemon aliases it (window::PlatformMonitorId, the
shared MonitorId) and gets window::monitor_id_at_cursor() like KDE's, so
monitor_idx_from_current_pos reads: ask the monitor id at the cursor, compare
monitor.id == monitor_id, and only then the Windows-only stale-handle fallback
(WindowsApi::monitor(monitor_id.to_hmonitor())). Same calls as before
(cursor_pos, monitor_from_point), in the same order.
Not a behaviour change. kfde: the alias is generic over MonitorPlatform; KDE and
macOS can alias it the same way. Verified: tools/fast-check native (core
tests), bare Windows clippy -D warnings, KDE check + lib tests, macOS fake-CC
type-check PASS; e2e: commands (monitor-from-cursor commands), hotplug scenarios
if any.
cargoLock, cargoToml and the vendor directory of the three flakes were taken
as "${real}/Cargo.lock" and crane.vendorCargoDeps { src = real; }. A string
that names a file inside the filtered source carries the whole source in its
context, so every edit of any file in it (a .rs file, a doc) changed the
dependency derivation (komorebi-workspace-deps, about 1000 crates) and the
dependencies rebuilt on every change: the constant COMMIT_HASH alone did not
help once the stubbed workspace source was introduced.
The lock and the root manifest are now builtins.path copies of those two
files (lockFile, tomlFile) and the vendor directory is made from the lock
(vendorCargoDeps { cargoLock = lockFile; }), so the dependencies depend on
Cargo.lock, Cargo.toml and the manifests the dummy source keeps, as before.
Verified (nix eval of drvPath in a throwaway git copy, three commits:
unchanged tree, an edit of crates/komorebi-config, a docs edit): Windows
deps and kfde deps are identical in all three (before: both changed with any
edit); Windows clippy changes with the source edit and the docs edit (docs are
in the Windows source), kfde clippy and vm stacks change with the
komorebi-config edit only; the kfm deny attribute still evaluates. The kfm
deps and clippy cannot be evaluated on this Linux host (the same change was
made there by analogy). Not built: one cold build, then a second commit must
be a cache hit.
Adds four tests to crates/komorebi-config/tests/rule_matching.rs next to
the KDE/macOS ones moved there: a Windows exe rule names the program with
its extension (mirrors rules_exe, where platform.exe_id adds `.exe` on
Windows) and the id without it does not match; a regex id is looked up as
written on Windows and with `.exe` removed elsewhere; the whole grid of
kinds x strategies x ids agrees between RuleQuirks::WINDOWS and UNIX for a
window with one class (mirrors rules_class); a negated class rule for a
window of another class and for one with no class. Each names the e2e
check it mirrors. docs/dev/e2e-to-unit.md points at the shared file.
Verified: cargo test -p komorebi-config --test rule_matching (16 passed);
bare cargo clippy --locked --all-targets -D warnings clean.
The stall analysis could not tell a frozen daemon (or guest) from a lock hold:
in both, the threads are silent. A heartbeat thread (komorebi/src/heartbeat.rs)
sleeps 100 ms in a loop and logs a warning, "heartbeat was N ms late: the
daemon was not scheduled for that long", when a beat comes 500 ms or more
after it should; started next to the command listener. If it is late exactly
when the other threads are silent, the process was not scheduled; if it keeps
beating while they are silent, something holds a lock (see the lock holder
warnings). The Windows connection policy's on_accept also logs, at debug,
"accepted a command connection (N ms since the previous one)", so a request
that waited in the backlog during a stall shows up at its late accept. Both
cost next to nothing (a 100 ms timer and one debug line per connection).
komorebi-transport is unchanged: KDE and macOS do not see either.
Diagnostics only, no behaviour change. Verified: tools/fast-check Windows clippy
-D warnings PASS; e2e: none needed.
The Windows gate showed that the bar cannot open a window in the golden
guest (no OpenGL 2.0: "egui_glow requires opengl 2.0+"). The scenario now
reads the bar's own output (`classify`): that exact failure turns the
window, stays-alive and daemon-restart checks into visible
`skipped: guest has no OpenGL 2.0` lines (counted in `result.json` and
printed as `skipped: N` by the runner); the schema equality, "the bar reads
its configuration" (real: the configuration is parsed before the window),
`komorebic state` and `stop --bar` stay checks; any other early exit of
the bar (a configuration error, a panic) is a failure with the bar's
output in the message, and a bar that opens its window gets the full walk as
before. Unit tests for `classify` run with the runner tests.
komorebi-bar-core gets tests/config.rs: windows-only widgets and the `mouse`
block are accepted on every platform, `supported()/unsupported()/enabled()`
name and skip what the platform cannot run (D-coord-1), a Command mouse
message is a plain string and the tagged form is rejected (the e2e finding),
the network widget accepts `default_interface_options` and the old key
names, layouts read from their names, `KomobarConfig::read` fills the frame
and refuses a non-json file. The warning text itself is not asserted (no
tracing subscriber in the core).
docs/dev/bar-e2e.md records the limitation and an analysis of getting
rendering into the guest (wgpu with the WARP adapter recommended; a mingw
Mesa is not offered by nixpkgs); nothing was added.
Verified: runner and library tests (161 passed), ruff clean on the scenario
(three older findings in other files are not mine), bar-core native tests 3
unit + 7 oracle + 6 config. Windows clippy and the macOS check: see the
report. The scenario itself was not run.
docs/dev/core-model.md section 21: the CommandHost mechanism, the sixteen
router arms that now live in komorebi-core (workspace navigation, the
moves across workspaces and monitors, lock and unlock by index), the one
platform switch (the pointer picks the monitor on Windows), and why the
rest of the router stays (each remaining arm needs a WindowManager method
or field).
Verified: not applicable (documentation).
BEHAVIOUR (macOS): FocusWorkspaceNumber, FocusWorkspaceNumbers and
FocusLastWorkspace now focus the display under the pointer first when
its workspace is empty, then run the workspace command, as on Windows
and (since the previous revision) KDE. Done by setting
CommandHost::POINTER_PICKS_THE_MONITOR_FOR_ALL to true in the macOS
CommandHost impl. Adds hand-check row H1 to docs/dev/macos-handcheck.md.
Verified: fake-CC cargo clippy --all-targets -D warnings on
aarch64-apple-darwin for the four macOS packages passes. Not verified:
nothing ran on a Mac. Gate owed: macOS hand check H1.
The Windows bar starts with glow exactly as before (the renderer is now named
in NativeOptions: with the glow and wgpu features both compiled eframe's
default is wgpu, so leaving it unnamed would have switched every machine).
Only when glow fails to get a context (eframe::Error::OpenGL, Glutin or
NoGlutinConfigs: "egui_glow requires opengl 2.0+" is the one seen in the
Windows e2e guest) it runs once more with `Renderer::Wgpu`, which draws
through Direct3D 12 and finds the software adapter WARP when there is no
GPU driver. If both fail the error names both ("glow: ...; wgpu: ..."), so
the e2e scenario can report it. The renderer in use is logged at info
("renderer: glow", and "renderer: glow failed (...); trying wgpu").
To make a second attempt possible the application creator moved out of the
`run_native` call into a closure that builds it from clones of the channels
and the configuration (the first creator is never run when its renderer
fails to start); its body is unchanged. eframe reuses its thread-local winit
event loop, so a second `run_native` on the same thread is supported.
BEHAVIOUR (Windows, only where glow fails): the bar now opens with wgpu
instead of exiting. Nothing changes where glow works except one info log
line. The macOS bar and the bar core are untouched.
Verified: Windows clippy --all-targets -D warnings clean (default members);
a unit test that a creation error is not a context failure. NOT verified:
that WARP accepts egui's Direct3D 12 device in the guest, or transparency
under wgpu: needs the win-e2e bar scenario.
Deep dedup D-coord-13 (2), the KDE side (kfde had not edited it; no other KDE
revision touches these functions). add_window_to_container, cycle_container_window_in_direction,
cycle_container_window_index_in_direction, focus_container_window, stack_all,
monocle_on, monocle_off, cycle_monocle and transfer_window are replaced by the macOS
text: 'let spot = workspace.hide_spot(); container.load_focused_window(spot)?;'
(and hide(None, spot)?, restore()?) where KDE had 'let _ = container.load_focused_window(())'.
The shared form is ?, which is equivalent here: the KDE window operations always answer
Ok, so no ? ever returns; hide_spot() is () on KDE. The functions are now byte-identical
in the two daemons (checked with the function splitter diff: no changed line).
The binding of a () value is allowed for the file with a comment
(clippy::let_unit_value) because the point is the identical text.
BEHAVIOUR: none intended (the ? cannot fail), so the gate is to confirm that.
Gate for the coordinator: KDE fast tier and VM scenarios that stack, unstack,
cycle a stack, monocle on and off and cycle, move a window to another workspace.
Verified: KDE cargo check + lib tests (fast-check) PASS; cargo clippy
-p komorebi-linux --all-targets -D warnings shows only errors that predate this
revision (a ptr_arg in process_command.rs:456 and useless conversions in
kwin/mod.rs), none in these files. Not run: the VM.
Pure formatting, no other change: the same rustfmt invocation as the kfm fmt
check (nightly rustfmt, edition 2024, komorebi-for-mac/rustfmt.toml) over
komorebi-for-mac/komorebi/src/animation/mod.rs and static_config.rs, which the
merge took from wip-u-settings3 unformatted.
Verified: the check's rustfmt --check over the macOS files passes after it.
BEHAVIOUR (expected none; gate needed): Windows' should_act and
should_act_individual become thin wrappers over komorebi_config::rules
with RuleQuirks::WINDOWS (a rule id is compared as written, no `.exe`
stripping, unlike KDE and macOS) and the window's one class passed as a
one-element slice. Signatures, should_act_window* and every call site are
unchanged. Equivalence was checked arm by arm: for a one-element slice the
any-of loops of the shared body are the single comparisons of the old one,
negated strategies included (docs/dev/rule-matching.md).
Verified: bare cargo clippy --locked --all-targets -D warnings
(default-members) clean. Not verified: any Windows run. Gate owed: the
Windows e2e scenarios rules, rules_class, rules_exe, manage_rules,
title_rule and startup_rules (the ones that assert which window a rule
catches) plus a smoke of the transparency blacklist and
window_manager_event show/hide rules that also call should_act.
The reaper held the lock across workspace.update(), notify_subscribers for each
reaped window and the komorebi.hwnd.json write (the stall analysis: real holds
of 1.0 to 1.3 s in the state_fidelity and placement scenarios, with a command
dropped meanwhile). Now it reaps and updates under the lock, builds the
Destroy notifications there (each carries the state as it was after that
window was reaped), takes a sequence number for the list of known handles
(HWND_LIST_SEQ), and then drops the lock; the subscribers are pushed to, the
borders notified and the file written afterwards. The write stays synchronous
and on the same thread (no writer thread).
Ordering. The notifications still go out in the order they were made and each
carries its own snapshot, but a command may now run between the reap and the
push, so its notification can reach subscribers before the Destroy of the
reaper; subscribers get full states, so the later one is still correct. The
hwnd file: update_known_hwnds (commands) and the reaper both write it through
reaper::write_known_hwnds(seq, list), which holds a small mutex around the write
and skips a list older than the one in the file, so the two writers do not
interleave and an older list never overwrites a newer one. If workspace.update()
fails for a window (the existing ? ), the notifications made before it are
dropped with the lock released; before they had been sent.
BEHAVIOUR: notification order relative to commands, and the file written
after the unlock. Gate needed: Windows e2e lifecycle, lifecycle_hidden,
state_fidelity, placement, commands, and the lock stress; the next hold ranking
should lose the reaper holds. Verified: tools/fast-check Windows clippy
-D warnings PASS; e2e not run.
`MouseMessage::Command(String)` is an untagged variant, so
`"on_middle_click": {"Command": ...}` in the scenario's bar configuration
did not deserialize and the bar exited at start ("data did not match any
variant of untagged enum MouseMessage"). The value is the string itself.
Found by the Windows gate on candidate 5 (win-e2e, S/e2e-win/gate-cand5.md,
bar section; the fix is its bar-fix.diff). Verified: ruff clean; not run.
BEHAVIOUR (Windows runtime): LockMonitorWorkspaceContainer and
UnlockMonitorWorkspaceContainer call komorebi_core::set_container_locked (the
text the Windows arms had byte for byte), and WindowManager implements
ContainerCommandHost. By construction the same; marked because it was only
type-checked.
Windows e2e scenarios needed: commands (toggle-lock, and lock/unlock by
index if the sweep has them), stacking.
Verified: Windows cargo clippy -p komorebi-windows --locked --all-targets -D
warnings: PASS. Not run: Windows tests, e2e.
BEHAVIOUR (KDE): FocusWorkspaceNumber, FocusWorkspaceNumbers and
FocusLastWorkspace now focus the monitor under the pointer first when
its workspace is empty, then run the workspace command, as on Windows.
This resolves item 1 of docs/dev/known-issues.md. Done by setting
CommandHost::POINTER_PICKS_THE_MONITOR_FOR_ALL to true in the KDE
CommandHost impl; the shared komorebi-core functions do the rest.
New tests/pointer_monitor.rs on FakeBackend: three of four failed
before the flip, all pass after it (the fourth checks that a pointer
on the focused monitor changes nothing).
Verified: cargo test -p komorebi-linux in the lite env, 670 passed,
0 failed. Not verified: KDE VM suites. Gate owed: KDE VM commands and
workspace-switch.
komorebi-bar gets a second renderer, wgpu, for machines without OpenGL 2.0
(the Windows e2e guest is one: egui_glow refuses its generic OpenGL 1.1).
wgpu draws through Direct3D 12 on Windows, which has the software adapter
WARP, so it needs no driver. The feature is on only in the
`[target.cfg(windows)]` table of komorebi-bar, so the macOS bar and the
shared bar-core are untouched and nothing here compiles for them.
Cargo.lock gains exactly one entry, `pollster` 0.4.0 (eframe's optional
block_on helper) and two dependency lines of eframe and nothing else: the
wgpu stack (wgpu 27, naga, wgpu-hal, egui-wgpu, ash, gpu-allocator ...) was
already locked as optional dependencies. pollster was not in the offline
registry, so `cargo metadata` fetched it from crates.io; no other version
changed.
Cost measured with `cargo tree -e normal --target x86_64-pc-windows-msvc -p
komorebi-bar`: 622 -> 664 distinct crate versions (+42) for the Windows bar.
With both features compiled, eframe's default renderer becomes Wgpu, so the
next revision names the renderer explicitly.
Verified: lock diff reviewed; not built yet (the next revision builds).
Deep dedup D-coord-13 (1), the container API. BEHAVIOUR (type-checked and
clippy-clean with the fake CC; the macOS tests are the oracle).
ContainerExt is deleted. Its four methods were the shared Container's with
the monitor's corner as an argument; every call (about 28 sites in
window_manager.rs, process_event.rs, scrolling.rs, workspace.rs, monitor.rs) is now
the shared one: add_window(window, spot), load_focused_window(spot), hide(omit,
spot), restore(), with spot = workspace.hide_spot() (MacosPlatform::hide_spot:
the workspace's corner, no display, which is what the old calls passed;
hide_on's screen argument was None at every remaining caller; the whole-workspace
hide with the display is Workspace::hide, already shared). The nine window
manager functions that differed from KDE's only in these calls (add_window_to_container,
cycle_container_window_in_direction, cycle_container_window_index_in_direction,
focus_container_window, stack_all, monocle_on, monocle_off, cycle_monocle,
transfer_window) now differ from KDE's text only in the spot and in the
error policy (let _ against ?), which the next revisions remove.
Two things change at run time, both small: monocle_on and cycle_monocle took the
corner from the monitor (monitor.extra.window_hiding_position) and now take it
from the workspace's state, which the monitor writes into every workspace when it
updates their globals, so they differ only if a workspace's globals are stale
(a config reload without a layout update in between); and Container::restore
skips the Accessibility call under cfg!(test), as hide and load_focused_window
already did.
Verified: fast-check macOS PASS; fake-CC cargo clippy -p komorebi-macos
--all-targets -D warnings clean. Not verified: any macOS test or run.
Verified on the Mini: not yet. Hand check row added to docs/dev/macos-handcheck.md.
Merge of wip-cand5, wip-u-bugfix, wip-u-wm, wip-u-settings3, wip-u-repotools,
wip-u-nix3 and wip-u-e2e2unit.
Resolutions:
- docs/dev/macos-handcheck.md: every section is kept, in order. The bugfix
agent's section F (bar clicks) and the settings agent's section (also
headed F) both appended after E; the settings one is renamed G, text
unchanged.
- komorebi-for-mac/komorebi/src/animation/mod.rs and static_config.rs: the
formatting-only revision of wip-u-nix3 (76ab52da, import order) conflicts
with the semantic edits of wip-u-settings3 (S4/S5). The files are taken
from wip-u-settings3 as they are; the following style(macos) revision
formats them again with the check's rustfmt invocation.
Verified: see the following revisions and the report.
macOS' should_act and should_act_individual become thin wrappers over
komorebi_config::rules (RuleQuirks::UNIX: a `.exe` in a rule id is
ignored, as before). Signatures and the trait methods in workspace.rs that
call them are unchanged. The old bodies were byte-identical to KDE's, which
the shared tests (crates/komorebi-config/tests/rule_matching.rs) now cover.
No behaviour change intended. Verified: cargo clippy --target
aarch64-apple-darwin -p komorebi -p komorebi-macos -p komorebic-macos -p
komorebi-client-macos -p komorebi-bar-macos --all-targets -D warnings with
the fake CC: clean. Not run: any macOS test (type-check only on Linux);
the Mini must run the suite on this revision.
The stall analysis of the cand5 gate: the remaining real holds of 1 to 4.5 s
are process_event for Show/Uncloak/FocusChange of freshly created windows, with
no log line between the lock and the first line of the handler: that gap is
Window::should_manage, i.e. Win32 calls on the new window (IsWindow,
GetWindowRect, title, DwmGetWindowAttribute for the cloaked state, process
name and path, class, styles) and rule matching, run with the lock held.
Read: should_manage reads only the window, the rule lists (taken in the order
documented at the statics in lib.rs, unchanged), the transparency manager's
list of known layered windows (its own lock) and size settings. It does not
touch the WindowManager. The event thread now calls ManageCheck::compute(event)
before locking, and process_event_checked(event, check) uses it. The old
process_event(event) stays and computes inline.
Race windows this opens, and the guards. (1) The rule lists change between the
check and the handling: only commands change them, so COMMAND_GENERATION is read
before the check and incremented when each command ends (a drop guard in
process_command, after the command has changed what it changes); if it differs
under the lock the check is thrown away and computed again there, as it always
was. (2) The window changes while the event waits for the lock (closed,
cloaked, retitled): the wait was already there before (the event sat in the
queue; the check used to run after the lock, now it runs up to one wait
earlier) and the handlers cope with a window that is gone or different, as for
any queued event; no state of the window manager is read from the old answer.
(3) Paused: the check is wasted work, the paused test still comes first under
the lock.
BEHAVIOUR: events are classified up to one lock wait earlier. Gate needed:
Windows e2e commands, config_reload, lifecycle, rules (rules_class, rules_exe),
placement, scrolling, and the lock stress; the hold ranking of the next gate
should lose the process_event holds of new windows. Verified: tools/fast-check
Windows clippy -D warnings PASS; e2e not run.
The same two arms as on KDE call komorebi_core::set_container_locked, and
WindowManager implements ContainerCommandHost. No behaviour change.
Verified: fake-CC cargo clippy -p komorebi-macos ... --all-targets -D
warnings: PASS (type-check only). Not run: the macOS tests (the Mac Mini).
komorebi_core::command gets focus_workspace_number (show a workspace unless
it is in front) and focus_workspace_numbers (show it on every other monitor,
then on the focused one), both with the pointer preamble when the host's
POINTER_PICKS_THE_MONITOR_FOR_ALL says so, over a new CommandHost method
show_workspace_on (focus the workspace of a monitor and load it, which the
daemons already did inline). The three daemons' arms call them (Windows keeps
its focus_workspace_numbers method as a wrapper) and implement
show_workspace_on. The const is unchanged: true for Windows, false for KDE and
macOS, so nothing changes yet; the next revisions flip it. Tests: the
Windows-switch test becomes a test of all five commands with the switch off and
on, and focus_workspace_number(s) are tested on the stub host (commands.py:
focus-workspace, focus-workspaces).
Verified: cargo test -p komorebi-core --features schemars --test commands: 18
passed; KDE cargo test -p komorebi-linux (lite env): 666 passed, 0 failed; fake-CC cargo
clippy -D warnings on the macOS packages: PASS; Windows cargo clippy -p
komorebi-windows --locked --all-targets -D warnings: PASS. Not run: Windows
tests, VM and Mac.
Convenience for the callers that have a workspace and no platform type to name
(the window manager functions, which are the same text on KDE and macOS): the
same as P::hide_spot(self) and P::hide_spot_on_display(self). Nothing calls them
yet in the KDE and Windows daemons; no behaviour change.
Verified: native cargo test -p komorebi-core passes; fast-check all trees PASS.
wip-u-coretests (written against the hook's old name after_floating_removed) and wip-u-core4 (which renamed it to before_floating_removed because it runs before the window leaves the ring) were merged in candidate 5; the stub platform and the expected hook logs now use the new name. No behaviour change: the order test already pinned 'before the removal'. Verified: cargo test -p komorebi-core (with and without the schemars feature).
macos-handcheck.md gets section F (rows M1-M3) for the battery, CPU/network
and update clicks fixed in the two preceding revisions (appended, the file is
kfm's). known-issues.md is new: four findings that are not fixed because
whether they are bugs, or the fix, is the owner's call, each with evidence
(file and line), why it may or may not be a bug, the platforms and a proposed
fix: KDE FocusWorkspaceNumber/Numbers/LastWorkspace without the pointer
monitor preamble, Monitor::focus_workspace overwriting a workspace name,
remove_container focusing focused-1, and the macOS subscriber push without a
write timeout.
Docs only. The line references were read in this tree (pointer-monitor
preamble compared between the Windows and KDE process_command.rs); nothing
was run.
docs/dev/core-model.md section 20: what the converge batch did (two
platform accessors, eleven macOS arms onto KDE's named methods), where the
two daemons stand (137 of 155 router arms byte-identical, 45% of KDE's
window_manager function lines identical with macOS), why it is below the
60% bar (macOS's ContainerExt against the shared Container with a hiding
spot, the ? against let _ policy, the platform entry points, the one-sided
functions) and the four blockers with the recommended next step.
Verified: not applicable (documentation); counts from the arm and function
comparison at this tip.
docs/dev/settings.md section 10: what S4 and S5 moved, the differences
between the daemons that were kept on purpose (KDE resets transparency keys
on load and Windows keeps them; Windows animates a kind when the global flag
is on or the per-kind value is true, KDE and macOS let the per-kind value
win; the scoped guard on KDE, the suspend counter on macOS, the Windows
shutdown write). docs/dev/macos-handcheck.md section F (appended, nothing
else changed): the Mac checks for S3 and S5.
Verified: not applicable (documentation).