core::asc re-exports ApplicationSpecificConfiguration, AscApplicationRules and AscApplicationRulesOrSchema, and config_generation re-exports ApplicationOptions and ApplicationConfiguration, from komorebi-config. The From<Vec<ApplicationConfiguration>> conversion that komorebic uses moved with them (orphan rule). The YAML generator stays. 215 lines removed.
AscApplicationRules is now the union, so komorebic's application-specific-configuration-schema prints the Windows view of it (komorebic gains the komorebi-config dependency; a three-line change in the arm, the minimum that keeps its output equal to schema.asc.json; step 4 owns the rest of the file). The daemon's own socket answer for this message is a different schema (Vec<ApplicationConfiguration>) and is untouched.
Verified: Windows cargo clippy --workspace --locked --all-targets -D warnings: clean (tier 2). Not verified: running komorebic.exe; the oracle test proves the Windows view equals schema.asc.json byte for byte.
ApplicationSpecificConfiguration, AscApplicationRulesOrSchema and AscApplicationRules are code-identical in the trees except that AscApplicationRules differs in its rule kinds: five Windows-only kinds, titleless and tabbed on KDE and macOS. The crate holds the union (declaration order floating-first as before; the platform-only fields carry x-komorebi-platforms, so a view prunes them) and, for the Windows From<Vec<ApplicationConfiguration>> conversion that the orphan rule keeps next to its types, ApplicationOptions and ApplicationConfiguration (data only: the YAML generator stays in the Windows daemon). The crate gains the color-eyre dependency.
The oracle test builds the view of ApplicationSpecificConfiguration for Windows, KDE and macOS and compares it with each tree's checked-in schema.asc.json byte for byte: all three are identical. This is the first proof that per-platform views of one union reproduce the checked-in files exactly (D17/D18); the three trees still use their own copies.
Verified: native cargo test -p komorebi-config: 4 unit + 6 schemas passed, 0 failed (tier 1).
WindowContainerBehaviour, FloatingLayerBehaviour (with should_float), Placement (with should_center and should_resize), CrossBoundaryBehaviour, WindowHidingPosition (KDE and macOS), WindowHandlingBehaviour and ZOrder (with its From<ZOrder> for isize; Windows) in behaviour.rs. The text is the KDE copy for the five that all trees share (identical to the Windows and macOS copies after the previous converge revision) and the Windows copy for the two Windows-only enums. A platform-only enum is defined here without a cfg: the daemon that does not read the key says so at load time. The trees keep their copies until the next revisions. The crate gains the clap dependency (ValueEnum) and the three Cargo.lock files the package entry.
The oracle gains a check that the generated definition of each enum equals the $defs entry of every checked-in schema.json that has it (all three trees for four of them, KDE and macOS for WindowHidingPosition, Windows for the other two).
Verified: native cargo test -p komorebi-config: 4 unit + 4 schemas passed, 0 failed (tier 1).
komorebi depends on komorebi-config and core::config_generation re-exports MatchingRule, WorkspaceMatchingRule, IdWithIdentifier, MatchingStrategy and IdWithIdentifierAndComment from it, so no call site changes. The 84 duplicated lines (five types and the From impl) are removed; ApplicationOptions, ApplicationConfiguration and the generator stay.
Verified: Windows cargo clippy --workspace --locked --all-targets -D warnings: clean (tier 2, persistent target). Schema files untouched.
Add crates/komorebi-config (edition 2024, root workspace member) with the feature-gated schema module that prints a schema the way komorebic does (pretty JSON plus a newline). No type has moved yet: the crate depends on komorebi-layouts, komorebi-themes and komorebi-protocol, which every type that follows needs.
Verified: native cargo test -p komorebi-config compiles (tier 1). Cargo.lock gains only the new package. Windows, KDE and macOS trees do not depend on the crate yet.
Merge revision: wip-main (history merges, fixes, step 0 path dependencies, step 1 komorebi-collections, KDE A3 fixes, flake phase 2) and wip-step2 (the komorebi-protocol crate, goldens and the unified SocketMessage used by all three trees). Conflicts in the root Cargo.toml members line, the trees' Cargo.toml dependency tables and the Cargo.lock files are resolved in this revision by keeping both sides' additions.
Moves the identical ring.rs and lockable_sequence.rs out of komorebi/src into the crate (rename). Necessary edits: lib.rs with pub use Lockable and a hidden pastey re-export; #[macro_export] on impl_ring_elements! using $crate::pastey::paste!; the doc test now says komorebi_collections::ring::Ring. The Windows tree gets the path dependency, re-exports (pub use komorebi_collections::{ring, lockable_sequence, Lockable}, #[macro_use] extern crate), forwards its schemars feature, and drops pastey again. Windows is bundled here because it is the tree the files move out of.
Verified: fast-check native, Windows clippy --all-targets -D warnings, KDE and macOS checks: PASS.
New crates/komorebi-collections (edition 2024; deps pastey, serde, optional schemars feature, dev serde_json_lenient) added to the root workspace members, with an empty lib.rs. Cargo.lock for this revision alone is not refreshed (it is in the next revision).
Verified: cargo test -p komorebi-collections --offline built (0 tests yet).
Windows ring.rs is replaced by the KDE copy (doc comments, tests, pastey::paste!, std::collections::VecDeque path). pastey 0.2 added to the root workspace deps and komorebi/Cargo.toml (paste stays: windows_api.rs and komorebic use it). The VecDeque imports in container.rs and workspace.rs only served the old macro text and are removed.
Verified: fast-check Windows clippy --all-targets -D warnings: PASS (tests compiled, not run: Windows-only).
Delete komorebi-for-kde/komorebi/src/core/pathext.rs (identical to the crate's copy) and re-export komorebi_protocol::pathext from core, so every existing path keeps working. komorebi-protocol becomes a workspace dependency of komorebi-for-kde (schemars feature on); the crate no longer lists dirs (unused until the client moves), so the root Cargo.lock loses that edge. KDE's Cargo.lock gains komorebi-protocol and cargo re-resolved one windows-sys entry.
Verified: cargo check --workspace --all-targets in komorebi-for-kde: 0 errors; cargo test -p komorebi --lib --test schemas: 305 + 5 passed, 0 failed. Full KDE workspace test run is done at the end of the stage.
Pure move of the converged pathext.rs (identical in all three trees, cmp checked) to crates/komorebi-protocol/src/pathext.rs. The Windows daemon depends on the crate (schemars feature forwarded) and re-exports it as komorebi::core::pathext, so every existing path keeps working. Cargo.lock gains the dependency edge.
Verified: Windows clippy --workspace --locked --all-targets -D warnings clean; native cargo test -p komorebi-protocol: 4 passed 0 failed, including the moved pathext unit test (unix branch). The Windows branch of that test cannot run on Linux (not verified).
Add crates/komorebi-protocol (edition 2024, member of the root workspace) with empty modules message, platforms, types, animation and pathext. The client transport stays out of the crate (D16). Cargo.lock gains the new package only.
Verified: native cargo build -p komorebi-protocol succeeds. Windows, KDE and macOS gates not run for this revision (no tree depends on the crate yet).
komorebi-e2e-agent runs in the interactive session of the guest and answers
the host over a forwarded TCP port: exec, spawn, os_windows (DWM frame, cloak
and focus), displays, window verbs and file transfer. komorebi-testwin is a
plain Win32 window with a stable exe name and class and a control channel on
stdin. Both cross-build from Linux and pass clippy; neither has run in a
guest yet.
komorebi-layouts now carries what a host needs of the Scrolling layout
without touching an operating system: the scrolling config section and its
checked settings, the layout options for the model, placement of containers
in a work area, resizing a column or tile, and the hand-over of column
records between workspaces. It re-exports the model as
komorebi_layouts::scrolling::model, so komorebi-for-mac can pick all of it up
through its existing komorebi-layouts git dependency.
Also add the Workspace methods for columns, consume/expel/stack, focus and
ordering, which sit on top of it.
libz-sys before 1.1.31 logs the compiler command of its zlib probe, which
with cc 1.6.0 or later includes every environment variable of the build,
and cargo stores that output under target/. It is a build dependency of
shadow-rs via git2 and libgit2-sys; bump it in the lockfile.
A new System Tray widget has been added to komorebi-bar, bringing native
Windows system tray functionality directly into the bar.
Special thanks to the Zebar project and its contributors for developing
the systray-util crate library that makes Windows system tray
integration possible.
The widget intercepts system tray icon data by creating a hidden "spy"
window that mimics the Windows taskbar. When applications use the
Shell_NotifyIcon API to manage their tray icons, the widget receives the
same broadcast messages, allowing it to monitor all system tray activity
while forwarding messages to the real taskbar to avoid disruption.
Users can configure which icons to hide using flexible rules. A plain
string matches by exe name (case-insensitive). A structured object can
match on exe, tooltip, and/or GUID fields using AND logic. Each field
supports matching strategies from komorebi's window rules (Equals,
StartsWith, EndsWith, Contains, Regex, and their negated variants),
allowing precise filtering even when multiple icons share the same exe
and GUID. An info button opens a floating panel listing all icons with
their properties and copy buttons, making it easy to identify which
values to use in filter rules.
The widget fully supports mouse interactions including left-click,
right-click, middle-click, and double-click actions on tray icons.
Double-click support uses the LeftDoubleClick action from systray-util
0.2.0, which sends WM_LBUTTONDBLCLK and NIN_SELECT messages. It handles
right-aligned placement correctly by adjusting the rendering order and
toggle button arrow directions to maintain consistent visual appearance
regardless of which panel the widget is placed in.
Some system tray icons register a click callback but never actually
respond to click messages, effectively becoming "zombie" icons from an
interaction standpoint. The widget includes fallback commands for known
problematic icons that override the native click action with a direct
shell command (e.g. opening Windows Security or volume settings).
The implementation uses a background thread with its own tokio runtime
to handle the async systray events, communicating with the UI thread
through crossbeam channels. Icon images are cached efficiently using
hash-based keys that update when icons change. Rapid icon updates are
deduplicated to prevent UI freezing, and image conversion (RgbaImage to
ColorImage) is performed on the background thread to keep the UI
responsive.
The widget automatically detects and removes stale icons whose owning
process has exited, using the Win32 IsWindow API on a configurable
interval. A manual refresh button is also available for immediate
cleanup.
A shortcuts button can be configured to toggle komorebi-shortcuts by
killing the process if running or starting it otherwise. The refresh,
info, and shortcuts buttons can each be placed in the main visible area
or in the overflow section.
This commit moves layout-related code into a new workspace crate
komorebi-layouts, with the intention of re-using it all in komorebi for
Mac instead of maintaining two separate implementations.