Commit Graph
2689 Commits
Author SHA1 Message Date
LGUG2Z cab39bedfb refactor(windows): move paddings, aspect ratio, layout defaults and display preferences to settings
Plan step 10, S3. The two default paddings, the aspect ratio of a window
toggled to floating (centre with resize), layout_defaults and
display_index_preferences are no longer statics: their writers
(apply_globals through SharedDelta::apply, the DisplayIndexPreference
command) and all readers use settings() together. The semantics are the
statics': a missing padding or display_index_preferences key keeps the
value, a missing layout_defaults clears it, a missing aspect ratio is
Standard (not the initial Widescreen), and the command inserts one entry.
Readers get an owned copy from one snapshot (accessors in settings.rs).

BEHAVIOUR only in this: apply_globals used to store these keys one at a
time and now publishes the group in one update, so a thread can no longer see
a half-applied reload of them. Value semantics are pinned by
crates/komorebi-settings tests/reload.rs and shared.rs (reload merges, a
few keys reset, a load never touches groups it does not name).

Windows: window.rs, windows_api.rs, workspace.rs, monitor.rs,
monitor_reconciliator, stackbar_manager (the gap reads the container padding
from settings), state.rs, static_config.rs, process_command.rs, lib.rs.
MONITOR_INDEX_PREFERENCES stays a static (Windows only).

Verified: Windows clippy -D warnings --locked --all-targets on
komorebi-windows (cross): clean. e2e not run: config_reload, layouts,
workspaces, stackbars (container padding gap) are needed.
2026-11-05 10:30:05 -08:00
LGUG2Z faf7bbd79e refactor(macos): move paddings, aspect ratio, layout defaults and display preferences to settings
Plan step 10, S3. The two default paddings, the aspect ratio of a window
toggled to floating (centre with resize), layout_defaults and
display_index_preferences are no longer statics: their writers
(apply_globals through SharedDelta::apply, the DisplayIndexPreference
command) and all readers use settings() together. The semantics are the
statics': a missing padding or display_index_preferences key keeps the
value, a missing layout_defaults clears it, a missing aspect ratio is
Standard (not the initial Widescreen), and the command inserts one entry.
Readers get an owned copy from one snapshot (accessors in settings.rs).

BEHAVIOUR only in this: apply_globals used to store these keys one at a
time and now publishes the group in one update, so a thread can no longer see
a half-applied reload of them. Value semantics are pinned by
crates/komorebi-settings tests/reload.rs and shared.rs (reload merges, a
few keys reset, a load never touches groups it does not name).

macOS: window.rs, monitor.rs, monitor_reconciliator.rs, macos_api.rs,
state.rs, static_config.rs, process_command.rs, lib.rs. rustfmt also
reflowed a few unrelated lines in window.rs and process_command.rs.

Verified: macOS fake-CC cargo check --locked --target aarch64-apple-darwin
-p komorebi-macos --all-targets: 0 errors, 0 warnings from these files.
Nothing run on a Mac.
2026-11-05 10:30:05 -08:00
LGUG2Z 04c10a00a5 refactor(kde): move paddings, aspect ratio, layout defaults and display preferences to settings
Plan step 10, S3. The two default paddings, the aspect ratio of a window
toggled to floating (centre with resize), layout_defaults and
display_index_preferences are no longer statics: their writers
(apply_globals through SharedDelta::apply, the DisplayIndexPreference
command) and all readers use settings() together. The semantics are the
statics': a missing padding or display_index_preferences key keeps the
value, a missing layout_defaults clears it, a missing aspect ratio is
Standard (not the initial Widescreen), and the command inserts one entry.
Readers get an owned copy from one snapshot (accessors in settings.rs).

BEHAVIOUR only in this: apply_globals used to store these keys one at a
time and now publishes the group in one update, so a thread can no longer see
a half-applied reload of them. Value semantics are pinned by
crates/komorebi-settings tests/reload.rs and shared.rs (reload merges, a
few keys reset, a load never touches groups it does not name).

KDE: window.rs, desktop.rs, monitor.rs, monitor_reconciliator.rs, state.rs,
static_config.rs, process_command.rs, lib.rs and tests/config.rs (the test
harness resets the paddings through settings()).

Verified: KDE cargo test --locked -p komorebi-linux --lib --tests (lite env,
own target dir): 63 test binaries, 631 passed, 0 failed, including
tests/config.rs that loads configurations over a fake desktop. KDE VM suites
not run (gate: config reload and workspace padding suites).
2026-11-05 10:30:05 -08:00
LGUG2Z 6f8bc2b0ba refactor(settings): pin a configuration load through the handle
Adds crates/komorebi-settings/tests/reload.rs: a load applied through a
Handle merges what the file gives, resets layout_defaults and the aspect
ratio when absent (the first load without the key turns the initial
Widescreen into Standard, as the statics do), keeps paddings and display
index preferences, never touches groups it does not name, and a reader that
holds the earlier snapshot still sees the earlier load whole. Test only.

Verified: native cargo test -p komorebi-settings: 18 unit + 3 integration
passed.
2026-11-05 10:30:05 -08:00
LGUG2Z 1cb147b2f9 feat(windows): install the settings handle
New module settings.rs: WindowsSettings (empty platform part) and
settings(), a LazyLock<Handle<WindowsSettings>> starting from
Shared::defaults_for(PlatformDefaults::WINDOWS). Nothing reads it yet, so
nothing changes at runtime. A test pins that the starting settings equal the
starting values of the statics (paddings, resize delta, mouse follows focus,
border enabled/width/offset, six colours; Windows has no border radius
static). Plan step 10, S2. Pure refactor.

Verified: Windows clippy -D warnings --locked --all-targets on
komorebi-windows (cross, compiles the pin test; it cannot run on this host).
The pin test was not run. e2e not run.
2026-11-05 10:30:05 -08:00
LGUG2Z 2429e3d5fa refactor(windows): take the default constants from komorebi-settings
DEFAULT_RESIZE_DELTA, DEFAULT_MOUSE_FOLLOWS_FOCUS and the initial values of
DEFAULT_WORKSPACE_PADDING and DEFAULT_CONTAINER_PADDING now come from
komorebi_settings::shared (PlatformDefaults::WINDOWS: 10, 10; 50; true); the
statics keep their names and types, so no reader changes. Adds the
komorebi-settings dependency edge to komorebi-windows (Cargo.lock edge only;
the crate is already a workspace member). Plan step 10, S1. Pure refactor.

Verified: Windows clippy -D warnings --all-targets on komorebi-windows
(dev shell, cross, target-fast-win): clean. e2e not run; tools/e2e-needed
will report the crate as an input of komorebi.exe, behaviour is unchanged.
2026-11-05 10:30:05 -08:00
LGUG2Z b937a3d716 chore(repo): merge kfde's core line into the package migration
Merge of wip-u-core (kfde: komorebi-core with Container, Workspace<P>, Monitor<P>) and wip-u-pkg-mig3.
Conflicts and how they were resolved:
- komorebi-for-kde/Cargo.toml, komorebi-for-kde/Cargo.lock: deleted, as in the migration (one root
  workspace); kfde's only edit there, the komorebi-core workspace dependency, is applied as a path
  dependency in the crate manifest.
- komorebi-for-kde/komorebi/Cargo.toml: the migration's manifest (inlined dependencies, package name
  komorebi-linux, [lib]/[[bin]]) plus kfde's komorebi-core dependency and the komorebi-core/schemars
  feature.
- Cargo.lock: the migration's lock re-resolved with cargo metadata --offline: the only change is the
  new komorebi-core 0.1.42 entry; no version of any other package moved (compared by name/version with
  both parents; kfde's Windows lock differs only by the komorebi -> komorebi-windows rename).
- komorebi-bar/src/widgets/komorebi.rs: deleted (the Windows bar moved to komorebi-bar/src/windows/);
  kfde's one-line edit (title: value.title() instead of value.title().ok()) applied to
  komorebi-bar/src/windows/widgets/komorebi.rs.
- komorebi-for-kde/nix/root-crates.json: crates/komorebi-core added (tools/kde-closure-check now ok with
  11 root crates).
Gates run: tools/fast-check --since wip-u-pkg-mig3: native tests, Windows clippy -D warnings, KDE check+lib+schemas, macOS fake-CC check, nix evaluation (root and both nested flakes) PASS; KDE cargo test -p komorebi-linux -p komorebic -p komorebi-client -p komorebi-hotkeys -p komorebi-core: 902 passed, 0 failed; CLI docs oracle identical x3; bar schema harness byte-identical for both bars (its Window::title stub now returns Option); bar-core tests 3+6; kde-closure-check ok; by evaluation an edit of the Windows bar or daemon leaves the kfde derivations unchanged, a KDE edit leaves Windows unchanged, and an edit of crates/komorebi-core changes Windows and kfde but not macOS. Not run: nix builds, VM, e2e (the Windows daemon changed: kfde's e2e gate applies), any Mac run.
2026-11-05 10:30:05 -08:00
LGUG2Z 4e508c347a fix(bar): the macOS bar module's leftovers from the old layout (unused imports, f32 literal)
On the Mac Mini native clippy -D warnings failed in the macOS bar module with three findings that the fake-CC
check only printed as warnings: the re-exports of ICONS_CACHE and ImageIconId in macos/widgets/mod.rs are
unused (they were pub items of the crate root before the module move, which the lint does not flag),
and Stroke::new(1.0, ...) in macos/widgets/komorebi.rs:393 falls back to f32. The two re-exports are removed
(grep: nothing in the macOS module uses them; the Windows module does and keeps them), the literal is
1.0_f32 (the type it already had). The same sweep removed the #[allow(unused_imports)] re-export of
rgba_to_color_image, also unused on macOS. Remaining pub use lines (render, selected_frame, ui, statics,
Alignment) are used. Behaviour identical.
Gates run: macOS fake-CC check of komorebi-bar and komorebi-bar-macos --all-targets: no warning left in the
bar; Windows clippy -D warnings PASS; S/bar2 schemas byte-identical. Not run: native macOS clippy (the Mini).
2026-11-05 10:30:05 -08:00
LGUG2Z 072ba7a471 chore(repo): merge the kfm clippy fixes into the package migration line
wip-u-kfm carries the macOS clippy fixes (&Path, drain, filter, slice fill, sort_by_key, collapsible_match allows, capture_spike, bar stroke literals). The bar stroke literal revision touches komorebi-for-mac/komorebi-bar, which the migration moved to komorebi-bar/src/macos; conflicts are resolved here by applying the same edit at the new paths.
2026-11-05 10:30:05 -08:00
LGUG2Z 29bdd0b2c7 docs(macos): record that the Mini runs so far are compile and unit tests only
Adds a status section to the hand-check list: cargo test --workspace passed
on the Mini (daemon 366 passed, 1 ignored) and clippy is clean, but nothing
was run as a daemon, so every walk-through item stays open.

Verified: documentation only.
2026-11-05 10:30:05 -08:00
LGUG2Z afd0f82f91 style(mac-bar): spell the stroke widths 1.0_f32 (float_literal_f32_fallback)
Six literals in the macOS bar (applications.rs, komorebi.rs x3, komorebi_layout.rs,
time.rs) passed 1.0 to egui's Stroke::new, which rustc 1.99 reports as an f32
fallback (a future hard error). The Windows bar and komorebi-bar-core
already say 1.0_f32 for the same calls, so this makes the macOS bar text
match them; the value is the same f32. No behaviour change.

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin
--workspace --all-targets -D warnings: clean (whole workspace). The Windows
bar and komorebi-bar-core are untouched. Verified on the Mini: not yet.
2026-11-05 10:30:05 -08:00
LGUG2Z b9125ddb65 style(mac): sample the capture spike's pixels with chunks(4) and a length filter (clippy)
examples/capture_spike.rs iterated bytes.chunks_exact(4), which clippy flags
as chunks_exact_with_const_size on 1.93 and as chunks_exact_to_as_chunks on
1.99 (the allow name differs between the two, so an allow cannot serve
both). chunks(4).filter(len == 4) visits the same full pixels in the same
order and still drops a trailing partial one; the spike is an example
binary, not the daemon. No behaviour change.

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin
--workspace --all-targets -D warnings: clean (whole workspace). Verified on
the Mini: not yet.
2026-11-05 10:30:05 -08:00
LGUG2Z 6ad0554556 docs: record Monitor<P> and the four hook-shared workspace functions
docs/dev/core-model.md section 13: what Monitor<P> holds and what stays in
MonitorExt, why the two globals updates are not shared (KDE's plural one
has no border), the serde facts the tests pin (flattened map keys, the
schema order) and the hooks of promote_container, effective_layout_options,
new_floating_window and hide.

Verified: not applicable (documentation).
2026-10-31 13:19:31 -07:00
LGUG2Z c4586a9f73 refactor(windows): the monitor is komorebi-core's Monitor over WindowsPlatform
BEHAVIOUR (Windows runtime): the type of every monitor changes and the
order of the keys of its JSON with it; the content does not. Marked
because it was only type-checked and a unit test of the crate.

komorebi/src/monitor.rs no longer defines Monitor: `type Monitor =
komorebi_core::Monitor<WindowsPlatform>`. WindowsPlatform implements
MonitorPlatform: the id stays a MonitorId written as the same plain
number (the existing hmonitor_json functions), the serial number an
Option<String> (missing when read is None, as before), the fields only
Windows has are WindowsMonitorExtra {name, device_id, workspace_names},
flattened into the JSON, and known_workspace_name reads the names from
them. The three fields are monitor.extra.name, .device_id and
.workspace_names at the 56 places that read or write them (the compiler
found each), and the Monitor literals build an extra. The eight functions
that moved are gone; every other method of the old impl is a method of
MonitorExt, unchanged in body, which each caller imports.
static_config::monitor_config(&Monitor) replaces the From<&Monitor> impl
for MonitorConfig (orphan rule).

Two things the review of this revision found: a flattened map is read
through a buffer that keeps its keys as strings, so workspace_names has a
deserialize_with that parses them (a unit test in the crate pins this with
the same adapter); and the keys of the monitor's JSON now come in this
order: the common fields, then name, device_id and workspace_names. The
state fixtures and the pins compare parsed JSON, so they are unaffected;
a tool that read the text of komorebic state by position would see the
change.

Windows e2e scenarios needed: tiled, stack and float state scenarios with
komorebic state compared to e2e/lib/tests/fixtures/kfw-*.json (the
komorebi-client and the bar parse it), monitor and display tests (hot
plug, monitor reconciliator, work area changes), named workspaces
(workspace-name, ensure-named-workspaces, monitor-index-preference),
move to monitor, and the schema checks.

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS; komorebi-core tests PASS. Not run: Windows tests, e2e.
2026-10-31 13:17:51 -07:00
LGUG2Z 638ce12769 refactor(kde): the monitor is komorebi-core's Monitor over KdePlatform
komorebi-for-kde/komorebi/src/monitor.rs no longer defines Monitor:
`type Monitor = komorebi_core::Monitor<KdePlatform>`. KdePlatform
implements MonitorPlatform: the id is a u32 written as a number, the
serial number a String, no extra fields (NoExtra), the schema of the id
u32. The eight functions that moved are gone; every other method of the
old impl (the constructors new and placeholder, load_focused_workspace,
update_workspace_globals, update_workspaces_globals,
update_focused_workspace, move_container_to_workspace,
add_container_with_direction, assign_windows_to_workspaces) is a method
of the extension trait MonitorExt, unchanged in body, which each caller
imports. Monitor literals get extra: Default::default().
static_config::monitor_config(&Monitor) replaces the From<&Monitor> impl
for MonitorConfig (orphan rule). The JSON pins of Monitor and
MonitorInformation in monitor.rs pass unchanged. No behaviour change.

Verified: KDE cargo test --workspace --no-fail-fast (native, lite env):
875 passed, 0 failed. Not run: VM suites.
2026-10-31 13:17:50 -07:00
LGUG2Z 74b9992e1c feat(core): Monitor<P> with the shared half of monitor.rs
komorebi-core gets Monitor<P: MonitorPlatform> (MonitorPlatform extends
WorkspacePlatform), moved from komorebi-for-kde/komorebi/src/monitor.rs
and made generic: the id and serial_number_id are the platform's
associated types (Id with serialize_id/deserialize_id hooks so each daemon
keeps writing its id as the plain number it always did; SerialNumber), and
the fields only a platform has are P::Extra, flattened into the monitor's
JSON (NoExtra for a platform with none). The schema is named Monitor.
The workspace accessors (impl_ring_elements! is not generic) are written
out, and eight functions move with them: focused_workspace_layout,
focused_workspace_name, new_workspace_idx, ensure_workspace_count,
remove_workspaces, remove_workspace_by_idx, add_container and
focus_workspace, the last taking the name the platform last knew for a
new workspace from the known_workspace_name hook (Windows keeps its
names in the extra fields). WorkspacePlatform now needs Clone, Debug and
PartialEq of the platform marker and ContainerWindow needs Debug, because
the derives on the generic structs ask for them.

One serde fact the tests pin: a flattened map is read through a buffer
that keeps its keys as strings, so an extra field with integer keys (the
Windows workspace_names) needs a deserialize_with that parses them; the
Windows converge must carry it.

Tests with stub platforms: the JSON of a monitor with flat extra fields
and the id as a number, a monitor without extra fields, the name hook of
focus_workspace, the schema name and flat properties.

Verified: cargo test -p komorebi-core --features schemars (native): 27
passed, 0 failed; Windows clippy --workspace --locked --all-targets
-D warnings: PASS. Not run: the daemons.
2026-10-31 13:17:50 -07:00
LGUG2Z 979d9bcae2 refactor(windows): promote_container, effective_layout_options, new_floating_window and hide come from komorebi-core
BEHAVIOUR (Windows runtime, none expected; type-checked only): the four
methods are removed from WorkspaceExt and the workspace gets the crate's.
WindowsPlatform implements primary_container_idx (0 for the default
layouts, the primary column of a custom layout, failing as before when it
has none) and keeps the default unmaximize_window and
before_hide_containers, which do nothing, as these methods did nothing
here. effective_layout_options' Custom arm is the crate's fallback arm.

Windows e2e scenarios: promote (promote-focus, promote-window) on default
and custom layouts, float a stacked, monocle and maximized window
(toggle-float), hide on workspace switch (workspaces sweep), layout
options (layout_options and layout_options_rules).

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS. Not run: Windows tests, e2e.
2026-10-31 13:09:38 -07:00
LGUG2Z 763037c83c refactor(kde): promote_container, effective_layout_options, new_floating_window and hide come from komorebi-core
The four methods are removed from WorkspaceExt; the workspace gets them
from the crate. KdePlatform implements the two hooks KDE needs:
unmaximize_window (Window::unmaximize) and before_hide_containers (the
scrolling prelude that hide had inline, with the resize adjustments
returned for the crate to put back). Same behaviour: the bodies are the
ones that moved, in the same order. No behaviour change.

Verified: KDE cargo test --workspace --no-fail-fast (native, lite env):
875 passed, 0 failed (the workspace tests that exercise hide,
promote and new_floating_window included). Not run: VM suites.
2026-10-31 13:08:58 -07:00
LGUG2Z dcd707c688 feat(core): promote_container, effective_layout_options, new_floating_window and hide are shared
Four more functions of the workspace move into komorebi-core, written
from the KDE text with three hooks that have defaults: primary_container_idx
(the layout's primary position; 0 for the default layouts, Windows
overrides it for custom layouts), unmaximize_window (KDE asks the
compositor, a no-op on Windows, as new_floating_window does there today)
and before_hide_containers (the KDE scrolling prelude of hide, returning
the resize adjustments to put back). effective_layout_options needs no
hook: a layout that is not one of the defaults has no default options,
which is the Windows custom-layout arm and an unreachable pattern on KDE.
Tests with the stub platform cover promote, new_floating_window and hide.
The daemons still have their own copies; the next revisions make them use
these.

Verified: cargo test -p komorebi-core --features schemars (native): 23
passed, 0 failed. Not run: the daemons.
2026-10-31 13:02:17 -07:00
LGUG2Z ba6ad8eacd docs: propose the shared update skeleton with its hooks and the exact bodies
docs/dev/core-model.md section 12: the skeleton of Workspace::update that
can move into komorebi-core (begin_update with the Flow guard,
containers_pruned, place_monocle, maximize_in_layout,
adopt_widths_before_layout for the scrolling-in-motion condition,
monitor_rects, adjust_layout per container, place_container, end_update
returning Pass), a table of the body each daemon keeps in each hook, the
constraints that make it safe, and the unified diff of the two update
bodies at this tip as the exact record. Not implemented: it waits for the
Windows e2e gate.

Verified: not applicable (documentation).
2026-10-31 13:00:46 -07:00
LGUG2Z 20c87b0ad0 docs: record what the Workspace move landed and where the sharing stops
docs/dev/core-model.md section 11: Workspace<P> and its shared functions
are in komorebi-core and both daemons use it; the functions left in the
extension traits (remove_window, restore, new_maximized_window,
reintegrate_maximized_window, apply_wallpaper, update, the custom
layout arms) differ in what they do and not only in how they are
written, listed one by one with the difference; hide and
new_floating_window can be shared once their hooks exist. Where Monitor
stands.

Verified: not applicable (documentation).
2026-10-31 12:55:06 -07:00
LGUG2Z 948425f9ae refactor(windows): the workspace is komorebi-core's Workspace over WindowsPlatform
BEHAVIOUR (Windows runtime): the type of every workspace in the daemon
changes; by construction the code is the same. Marked because it was only
type-checked.

komorebi/src/workspace.rs no longer defines Workspace: `type Workspace =
komorebi_core::Workspace<WindowsPlatform>`, with WorkspaceLayer,
WorkspaceWindowLocation, CachedLayoutDefault and the threshold helpers
re-exported from the crate. WindowsPlatform implements WorkspacePlatform
(the window is Window, no extra state, default_padding reads
DEFAULT_CONTAINER_PADDING and DEFAULT_WORKSPACE_PADDING as Default did,
the foreground window, cursor, rule matching with the regex table and the
three scrolling lookups forward to what the file called inline;
after_floating_removed stays the default no-op, as Windows does not
refocus). The functions that moved are gone from the file; every other
method of the old impl (update, hide, restore, remove_window,
apply_wallpaper, load_static_config, border_kinds_on_show,
windows_on_show, the scrolling glue of scrolling.rs, ...) is a method of
the extension traits WorkspaceExt and WorkspaceScrolling, unchanged in
body, which each caller imports. static_config::workspace_config(&Workspace)
replaces the From<&Workspace> impl for WorkspaceConfig (orphan rule).
Workspace is built with state: Default::default() in state.rs.

Windows e2e scenarios needed (all of them touch the workspace): tiled,
stack and float state scenarios with komorebic state compared to
e2e/lib/tests/fixtures/kfw-{tiled,stack,float}.json; commands, workspaces,
stacking, scrolling, resize, borders and animation sweeps; workspace
rules and initial_window_placement rules; focus and move across
workspaces and monitors; the schema checks.

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS. Not run: Windows tests, e2e.
2026-10-31 12:53:42 -07:00
LGUG2Z c23569a337 docs: macOS commands name komorebi-macos, not komorebi
The Mac Mini run failed on -p komorebi: the daemon packages are komorebi-macos and komorebi-windows (the
single komorebi package is step 8). Corrected the command list and the note.
2026-10-31 12:53:29 -07:00
LGUG2Z 5cdb1ab33a fix(bar-core): WidgetConfig::supported as matches!
clippy::match_like_matches_macro (-D warnings, seen by native clippy on the Mac Mini) flagged the match
with a Keyboard/Media/Systray arm of cfg!(target_os = "windows") and a true arm. The same boolean is
written !matches!(self, Keyboard | Media | Systray) || cfg!(target_os = "windows"): false only for those
three variants off Windows. Behaviour identical.
Gates run: Windows clippy -D warnings PASS; native cargo clippy -p komorebi-bar-core --all-targets -D
warnings PASS; bar-core tests (3 unit + 6 oracle) PASS; macOS fake-CC check PASS.
2026-10-31 12:53:21 -07:00
LGUG2Z 0679be6621 refactor(kde): the workspace is komorebi-core's Workspace over KdePlatform
komorebi-for-kde/komorebi/src/workspace.rs no longer defines Workspace:
`type Workspace = komorebi_core::Workspace<KdePlatform>`, with
WorkspaceLayer, WorkspaceWindowLocation, CachedLayoutDefault and the
threshold helpers re-exported from the crate. KdePlatform implements
WorkspacePlatform (the window is Window, the state holds
scrolling_placed, the hooks forward to window::foreground_window_id and
cursor_position, to should_act_window with the regex table, to the three
scrolling lookups, and after_floating_removed refocuses a floating
window). The functions that moved in the previous revision are gone from
the file; every other method of the old impl (update, hide, restore,
remove_window, apply_wallpaper, load_static_config, adopt_maximized_window,
the scrolling glue of scrolling.rs, ...) is now a method of the extension
traits WorkspaceExt (workspace.rs) and WorkspaceScrolling (scrolling.rs),
unchanged in body, which each caller imports. Workspace.scrolling_placed is
state.scrolling_placed. static_config::workspace_config(&Workspace) replaces
the From<&Workspace> impl for WorkspaceConfig, which the orphan rule
forbids. The tests stay in place.

No behaviour change: same bodies, same order; serialised state and the
schema are the ones tests/schemas.rs and the fixtures pin.

Verified: KDE cargo test --workspace --no-fail-fast (native, lite env):
875 passed, 0 failed. Not run: VM suites.
2026-10-31 12:50:34 -07:00
LGUG2Z f225e51982 feat(core): Workspace<P> with the shared half of workspace.rs
komorebi-core gets Workspace<P: WorkspacePlatform>, moved from
komorebi-for-kde/komorebi/src/workspace.rs (KDE is the base), together
with WorkspaceLayer, WorkspaceWindowLocation, CachedLayoutDefault and the
two threshold helpers, and these 52 functions of its impl, whose text is
the same on both daemons (add_container_to_back/front, the container
focus and removal family, insert_container_at_idx, swap_containers,
preselect and monocle operations, new_container_for_window and
resolve_placement_index, location_from_exe, visible_windows, the
enforce_resize_* family, the window lookups, remove_floating_window and
the floating focus helpers, is_scrolling). They are generic over
P::Window (Container<P::Window>, PlatformWindowId<P>), and every private
function is pub so the daemons' own methods can call it. The accessors
the impl_ring_elements! macro made are written out.

WorkspacePlatform is the hook trait: Window (a WorkspaceWindow), State
(what only a platform keeps in a workspace; skipped in the JSON and the
schema), default_padding, foreground_window_id, cursor_position,
should_act_window and should_act_window_individual (the platform holds
the compiled regexes), the three scrolling lookups and
after_floating_removed (KDE refocuses a floating window). Default for
Workspace<P> is the KDE one with the padding from the hook. serde and
schemars bounds are on P::Window; the schema is named Workspace.

Not used by any daemon yet; the next revisions make each daemon use it.
Four tests with a stub platform cover new_container_for_window, the
focus, the JSON keys and the default.

Verified: cargo test -p komorebi-core --features schemars (native): 20
passed, 0 failed; Windows clippy --workspace --locked --all-targets
-D warnings: PASS (compiles the crate). Not run: the daemons.
2026-10-31 12:50:34 -07:00
LGUG2Z 75688cf74f docs: bar steps B0-B3 done; what to run on the Mac Mini
Marks the bar steps as executed (B4 left, why), and lists the cargo build, clippy, test and schema commands
for aarch64-darwin per revision. Not verified: any of them on a Mac.
2026-10-31 12:45:37 -07:00
LGUG2Z 7d4ea893cc refactor(bar): one komorebi-bar package with a module per platform
The macOS bar module moves from komorebi-for-mac/komorebi-bar/src/macos to komorebi-bar/src/macos (the
include_str! path follows), komorebi-bar/src/main.rs is a cfg_select! over target_os that runs
windows::main or macos::main, and komorebi-bar/Cargo.toml has what both share in [dependencies] and the
rest in per-target tables (Windows: windows, windows-core, windows-icons x2, systray-util, tokio, regex,
which, egui_extras, netdev 0.46, sysinfo 0.39, komorebi-themes without default features; macOS: objc2,
objc2-app-kit, icns, raw-window-handle, netdev 0.40, sysinfo 0.38, komorebi-themes with defaults), so each
platform keeps the versions it had. The old komorebi-bar-macos package stays as a shim that includes the
moved module. The macOS flake builds -p komorebi-bar and its source filter takes the unified package's
manifest, main.rs and src/macos; the Windows filter leaves src/macos out. The bar does not build for
Linux (no arm of the cfg_select), as before.

Gates run: Windows clippy --all-targets -D warnings PASS; macOS fake-CC check --locked --all-targets of
-p komorebi-bar and -p komorebi-bar-macos PASS (type check only); bar-core schema oracle (3 + 6) PASS; the
S/bar2 harness regenerates schema.bar.json for Windows (9091 lines) and macOS (3774) byte-identical to the
checked-in files; tools/kde-closure-check ok; CLI docs oracle identical x3; nix evaluation PASS and by
evaluation an edit of komorebi-bar/src/windows changes the Windows derivations only (the macOS side cannot
be evaluated on this Linux host). Not run: nix builds, any bar run (Windows screenshot gate and the Mac
hand check are owed).
2026-10-31 12:45:25 -07:00
LGUG2Z bdd811f2d4 refactor(bar): the macOS bar is a module of its package (move)
komorebi-for-mac/komorebi-bar/src/{bar,config,os}.rs and widgets/ move to src/macos/, main.rs to
macos/mod.rs (pub fn main); src/main.rs is a caller. Mechanical edits only: crate:: becomes
crate::macos:: (all sites), the include_str! path gets one more ../, and the unused root re-export of
komorebi_bar_core::platform is dropped.

Gates run: macOS fake-CC check of komorebi-bar-macos --locked --all-targets PASS (type check only); bar-core
schema oracle PASS; S/bar2 harness regenerates both bar schemas byte-identical to the checked-in files
(macOS 3774 lines, Windows 9091). Not run: any bar run on a Mac (the user's Mac check).
2026-10-31 12:41:55 -07:00
LGUG2Z 146cd7ff54 refactor(bar): the Windows bar is a module of the komorebi-bar package (move)
komorebi-bar/src/{bar,config,os}.rs and widgets/ move to komorebi-bar/src/windows/, main.rs to
windows/mod.rs (pub fn main); src/main.rs is a four-line caller. Mechanical edits only: crate:: becomes
crate::windows:: (all sites), the include_str! path gets one more ../, and the unused root re-export
of komorebi_bar_core::platform is dropped (the main installs the platform by its full path). This
prepares one package with a module per platform; behaviour is the same code.

Gates run: Windows clippy --all-targets -D warnings PASS; bar-core schema oracle (3 unit + 6) PASS; the
S/bar2 harness (real bar sources, regen.sh, updated to read src/windows) regenerates schema.bar.json for
Windows (9091 lines) and macOS (3774 lines) byte-identical to the checked-in files; tools/e2e-needed
says the bar is not an input of the e2e binaries. Not run: the bar itself, the screenshot gate (owed).
2026-10-31 12:41:00 -07:00
LGUG2Z a35573d8eb fix(kde): StaticConfigExt takes &Path instead of &PathBuf (clippy::ptr_arg)
The KDE twin of the macOS fix: the trait declarations of preload, postload
and reload (static_config.rs:726, :732, :735; the impls follow) took
&PathBuf, introduced by the same step 3 conversion to the extension trait.
read takes &Path since the config-crate revision; the one clone of the path
is path.to_path_buf(). No behaviour change.

Verified: native cargo clippy --locked -p komorebi --all-targets -D warnings
in komorebi-for-kde: clean (the 3 ptr_arg errors that predated the backend
work are gone); cargo test --locked -p komorebi --lib: 294 passed, 0 failed.
2026-10-31 12:39:24 -07:00
LGUG2Z b558acbe17 refactor(bar): the macOS bar uses the unified komorebi-client
komorebi-for-mac/komorebi-bar depends on komorebi-client (the one package, path ../../komorebi-client)
instead of komorebi-client-macos; same module, same API. Cargo.lock only rewires that edge.
Gates: macOS fake-CC check of komorebi-bar-macos --locked --all-targets PASS (type check only); bar-core
schema oracle (cargo test -p komorebi-bar-core: 3 unit + 6 oracle) PASS. Not run: any bar run.
2026-10-31 12:38:51 -07:00
LGUG2Z 5055e8a639 style(mac): allow clippy::collapsible_match at three nested ifs, with a reason
monitor.rs (two ifs that choose where a moved container goes, inside a match
on the layout) and static_config.rs handle_asc_file (a 40-line block under
the extension check). The lint wants the if folded into the outer match
arm as a guard; doing that restructures the arms (the else branches become
extra arms) without changing what they do, which is more edit than a lint
fix should be and cannot be run here, so each site gets an allow with a
comment instead. No behaviour change. Pre-existing on the original macOS
tip 9a58e511.

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin -p komorebi --all-targets -D warnings: the daemon lib and its tests are clean with the six hygiene and ptr_arg revisions applied (the whole-workspace run still reports newer-clippy lints that the Mini's 1.93 does not have: the bar's f32 literal fallback and examples/capture_spike.rs chunks_exact). Verified on the Mini: not yet.
2026-10-31 12:38:08 -07:00
LGUG2Z f9f47f3fb4 style(mac): sort the layout rules with sort_by_key (clippy::unnecessary_sort_by)
window_manager.rs sorted (usize, Layout) pairs by their first field with a comparator closure; sort_by_key on the same field is the same stable sort.

No behaviour change. Pre-existing on the original macOS tip 9a58e511 (reported by cargo clippy --all-targets -D warnings on the Mini, stable 1.93).

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin -p komorebi --all-targets -D warnings no longer reports this lint (the last hygiene revision records the whole run). Verified on the Mini: not yet.
2026-10-31 12:37:18 -07:00
LGUG2Z d9837200c3 style(mac): fill resize_dimensions with None in one call (clippy::manual_slice_fill)
window_manager.rs reset every entry of workspace.resize_dimensions in a for loop; fill(None) does the same.

No behaviour change. Pre-existing on the original macOS tip 9a58e511 (reported by cargo clippy --all-targets -D warnings on the Mini, stable 1.93).

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin -p komorebi --all-targets -D warnings no longer reports this lint (the last hygiene revision records the whole run). Verified on the Mini: not yet.
2026-10-31 12:37:18 -07:00
LGUG2Z 756a03cc77 style(mac): use Option::filter for the non-empty window name (clippy::manual_filter)
window.rs WindowInfo::from(&CFDictionary) spelled filter by hand with and_then; an empty name is still None.

No behaviour change. Pre-existing on the original macOS tip 9a58e511 (reported by cargo clippy --all-targets -D warnings on the Mini, stable 1.93).

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin -p komorebi --all-targets -D warnings no longer reports this lint (see the last hygiene revision for the whole run). Verified on the Mini: not yet.
2026-10-31 12:37:12 -07:00
LGUG2Z 552ab43701 style(mac): take the workspaces with mem::take instead of drain(..).collect() (clippy::drain_collect)
monitor.rs remove_workspaces moved every workspace into a new VecDeque through drain; mem::take moves the whole deque and leaves an empty one, which is the same result without the second allocation.

No behaviour change. Pre-existing on the original macOS tip 9a58e511 (reported by cargo clippy --all-targets -D warnings on the Mini, stable 1.93).

Verified: fake-CC cargo clippy --locked --target aarch64-apple-darwin -p komorebi --all-targets -D warnings no longer reports this lint (see the last hygiene revision for the whole run). Verified on the Mini: not yet.
2026-10-31 12:37:12 -07:00
LGUG2Z 1c64168759 fix(mac): StaticConfigExt takes &Path instead of &PathBuf (clippy::ptr_arg)
Fixes the 3 new lints at static_config.rs:719, :726 and :729 (the trait
declarations of preload, postload and reload; the impls follow). They were
introduced by kvtvnouo, 'refactor(mac): use StaticConfig and its family of
komorebi-config', which turned the inherent methods into the extension
trait; the original tip 9a58e511 did not have them. read gets a &Path
through the previous revision, and the one clone of the path (the
ReloadStaticConfiguration message) is path.to_path_buf(). No behaviour
change.

Verified: macOS fake-CC type-check (tools/fast-check) PASS, and fake-CC
cargo clippy -p komorebi --all-targets -D warnings no longer reports the
three. Verified on the Mini: not yet (cargo clippy --all-targets -D warnings).
2026-10-31 12:37:12 -07:00
LGUG2Z 1e10f45bb9 refactor(config): StaticConfig::read takes &Path, not &PathBuf
clippy::ptr_arg: the function only opens the file, so any path will do, and
every caller that passes a &PathBuf still compiles through deref. Needed so
the macOS StaticConfigExt methods can take &Path (next revision).

Verified: fast-check native, Windows clippy -D warnings, KDE check and lib
tests, macOS fake-CC type-check PASS. Verified on the Mini: not yet.
2026-10-31 12:36:14 -07:00
LGUG2Z a73c9e2131 docs: state of the package migration (steps 0-6), the bar steps, the owed gates
Updates docs/dev/unified-binaries.md: steps 5 and 6 done, the limits found, step 7 for the bar written as
exact steps (B0-B4, not executed; bar files untouched), and the list of heavy builds, VM, e2e and Mac
checks the coordinator owes. Not verified: any nix build.
2026-10-31 12:35:48 -07:00
LGUG2Z 19162f3367 refactor(client): one komorebi-client package that re-exports the daemon of the target OS
The root komorebi-client package (0.1.42) is the one client: src/lib.rs is a cfg_select! over target_os
that re-exports the module of the platform. The three lib.rs files move to komorebi-client/src/{windows,
linux,macos}.rs (they were made equal in socket code by the previous revision), the KDE integration tests to
tests/linux_{daemon,subscribe}.rs (#![cfg(target_os = "linux")]). The daemon crate of each platform has a
dependency key of its own (cargo allows one path per key) and the module names it (use crate::komorebi_linux
as komorebi). The old komorebi-client-linux and komorebi-client-macos packages stay as shims that include
the moved module, so the old names build until the cutover (the macOS bar and komorebic-macos still use
them). komorebic now depends on the one komorebi-client on all three platforms. The KDE and macOS flakes
build the unified client (-p komorebi-client) and take its manifest, lib.rs and their module in the source
filter; the Windows filter leaves the other platforms' modules and tests out. Windows API for komorebi-bar,
komorebi-gui and komorebic is unchanged.

Gates run: Windows clippy --all-targets -D warnings PASS (client, bar, gui, komorebic); KDE cargo test -p
komorebi-client -p komorebi-client-linux -p komorebic -p komorebi-linux: 775 passed 0 failed (the client
tests and doctests included); cargo check of komorebic-linux and komorebi-client-linux PASS; macOS fake-CC
check --locked of komorebi-client, komorebic, komorebi-client-macos, komorebi-bar-macos, komorebic-macos
--all-targets PASS (type check only); CLI docs oracle byte-identical x3; nix evaluation PASS; by evaluation an
edit of komorebi-client/src/windows.rs changes only Windows derivations, linux.rs only kfde, macos.rs
neither. Not run: nix builds, the e2e (komorebi-client is in the closure of komorebi.exe's users: Windows e2e
OWED), any macOS link or run.
2026-10-31 12:34:59 -07:00
LGUG2Z a337eca811 refactor(windows): Window implements WorkspaceWindow
BEHAVIOUR (Windows runtime): none; the four lookups of komorebi-core's
WorkspaceWindow forward to Window's own title, exe, class and path and
nothing calls them through the trait yet. Windows e2e: none needed.

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS. Not run: Windows tests, e2e.
2026-10-31 12:34:57 -07:00
LGUG2Z a05076f491 refactor(kde): Window implements WorkspaceWindow
The four lookups of komorebi-core's WorkspaceWindow forward to Window's
own title, exe, class and path. Nothing calls them through the trait yet.
No behaviour change.

Verified: KDE cargo test -p komorebi --lib --tests (native, lite env):
630 passed, 0 failed. Not run: VM suites.
2026-10-31 12:34:57 -07:00
LGUG2Z b2ba3847cb feat(core): WorkspaceWindow, what a workspace asks of a window
A supertrait of ContainerWindow with the four lookups the shared workspace
code makes (title, exe, class, path, each Option<String>), for the
functions that move into komorebi-core next. The crate's stub window
implements it and a test checks the four answers. Nothing uses it yet.

Verified: cargo test -p komorebi-core --features schemars (native): 16
passed, 0 failed. Not run: the daemons.
2026-10-31 12:32:31 -07:00
LGUG2Z e4d97c87ed refactor(windows): resolve_placement_index uses should_act_window
BEHAVIOUR (Windows runtime, none expected): window.rs gets
should_act_window and should_act_window_individual, thin forms of
should_act and should_act_individual that take one class, and
resolve_placement_index has KDE's text (one let-else over the four
lookups, then those two calls). Same checks in the same order.

Windows e2e scenarios: initial_window_placement rules (target and
rules map, single and many matching rules).

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS. Not run: Windows tests, e2e.
2026-10-31 12:31:37 -07:00
LGUG2Z 259dbb6646 refactor(kde): Window::path is a String and resolve_placement_index uses should_act_window
Groundwork for moving Workspace into komorebi-core. Window::path returns
Option<String>, as the Windows one does (the backend already holds a
String; the PathBuf and the to_string_lossy calls at its seven uses go).
window.rs gets should_act_window and should_act_window_individual, the
one-class forms of should_act and should_act_individual (KDE wraps the
class in a slice), and resolve_placement_index calls those, which is the
text the Windows side gets in the next revision. No behaviour change.

Verified: KDE cargo test -p komorebi --lib --tests (native, lite env):
630 passed, 0 failed. Not run: VM suites.
2026-10-31 12:31:36 -07:00
LGUG2Z e69346e918 refactor(client): the three komorebi-client crates have the same Connection
Windows and macOS had a Connection (messages written a line each in order); KDE had none, and Windows
opened it differently from macOS. All three now have the macOS text (open -> from_stream; KDE's with docs),
and the Windows DATA_DIR is exported like the other two. Additive on KDE and Windows, no change to what
any function does. Preparation for one komorebi-client package; the socket functions were already identical.

Gates run: Windows clippy --all-targets -D warnings PASS (client and its users); KDE cargo test -p
komorebi-client-linux (unit, integration, doctests) PASS. Not run: macOS (file untouched).
2026-10-31 12:24:30 -07:00
LGUG2Z 2b7deddca7 docs: record where the Workspace move stands and what is left, per function
docs/dev/core-model.md section 10: 58 functions (about 530 lines) are now
identical on both sides, only new_container_for_window depends on a
differing function (resolve_placement_index), and a table of every
remaining difference with the converge step or hook that removes it, plus
what ContainerWindow must grow before the first generic function
compiles.

Verified: not applicable (documentation).
2026-10-31 12:22:40 -07:00
LGUG2Z d1539a0687 refactor(komorebic): move the macOS CLI into the unified komorebic package (pure move)
komorebi-for-mac/komorebic/src/main.rs and applications.json move to komorebic/src/macos/{mod.rs,
applications.json}; only the include_str! paths change (they point into komorebi-for-mac/docs) and
main is pub. The old package komorebic-macos stays and builds from the moved file through a shim
(src/main.rs includes ../../../komorebic/src/macos/mod.rs). komorebi-for-mac/komorebic/fixtures stays
where it is: the macOS daemon's pan tests read it. The macOS flake builds komorebic (unified) instead of
komorebic-macos and its source filter takes the unified package's manifest, build.rs, main.rs and
src/macos; the Windows filter already leaves macos out.

Gates run: macOS fake-CC check --locked of -p komorebic and -p komorebic-macos PASS (type check only);
Windows clippy PASS; KDE check PASS; CLI docs oracle byte-identical x3 (the macOS harness reads
komorebic/src/macos/mod.rs now); nix evaluation PASS, and by evaluation an edit of komorebic/src/windows.rs,
linux/mod.rs or macos/mod.rs changes only its own platform's derivations. Not run: nix builds, any macOS
link or run (the user's Mac check: komorebic --help, --version, quickstart, start, stop).
2026-10-31 12:22:20 -07:00
LGUG2Z 63888cb711 refactor(windows): workspace.rs reads window ids and the focus through shared names
BEHAVIOUR (Windows runtime, minor): the same nine functions as on KDE take
PlatformWindowId (isize), read it with window.id(), and use
window::foreground_window_id() / cursor_position() (WindowsApi calls,
moved). One message changes: is_focused_window_monocle_or_maximized
failed with the Win32 error when there is no foreground window and now
says 'no foreground window', as KDE does.

Windows e2e scenarios: focus commands on stacked and monocle windows
(is_focused_window_monocle_or_maximized), float/unfloat of the focused
window, mouse-follows-focus and the click-to-pick-container path
(container_idx_from_current_point).

Verified: Windows clippy --workspace --locked --all-targets -D warnings:
PASS. Not run: Windows tests, e2e.
2026-10-31 12:21:54 -07:00