Commit Graph
100 Commits
Author SHA1 Message Date
LGUG2Z e3dd3c60de fix(scrolling): refocus after a window is closed with Hide
Closing a window sends Hide and not Destroy to many applications. The Hide
arm re-tiled without asking Windows to focus the surviving window, so no
window had the foreground and the border did not follow focus. Use the
same refocus rule as the Destroy arm.
2026-10-30 15:45:37 -07:00
LGUG2Z ae8e982380 fix(scrolling): show every window when a stack is spread out into a column
Spreading a stack out into a column left two things wrong, both seen in a
recording of toggle-column-stack:

- The window that stays in the original container was never restored. When it
  was the tab at the back it stayed cloaked, and its column was empty until
  focus reached it. Only the windows that moved to new containers were
  restored.
- Each new container took focus when it was inserted, so the strip scrolled a
  column to bring it into view, and did not scroll back once the containers
  were put in the one column again. The strip was left a column to the left,
  with an empty third of the screen. Focus now stays on the column that they
  are put in.

Test both, with windows that are hidden as stacking hides them.
2026-10-30 15:45:37 -07:00
LGUG2Z 5daca12e28 feat(scrolling): support more than one monitor
Remove the single-monitor restrictions on the Scrolling layout. Each
workspace keeps a strip of its own, and a window is seen on whichever monitor
it overlaps, so placement now looks at the other monitors: a window that
scrolled out of view past an edge that another monitor is next to is hidden
instead of parked, and a partly visible one is cut down to its own work area.

A window that comes back into view is shown again first, but only the one at
the front of its container: the others are the tabs at the back of a stack,
which are hidden because they are at the back.
2026-10-30 15:45:37 -07:00
LGUG2Z b8a444df5c docs(scrolling): describe the scrolling layout 2026-10-30 15:45:37 -07:00
LGUG2Z e8364f7b5b feat(scrolling): rest windows that scroll out of view at the edge
A window that scrolls out of view comes to rest at the edge of the work area
that it left by, with 5 pixels of it still on screen, keeping its size so that
nothing is resized to bring it back and an animation back into view is short.
Reuses the existing movement animations.

Also test the Workspace glue: widths, consume, expel, moving a column, and
that retile forgets the widths that windows were found to refuse.
2026-10-30 15:45:37 -07:00
LGUG2Z f170e8e2ac feat(scrolling): make room for windows that will not get as narrow
After windows are placed, ask each how wide it really is. A window that is
wider than its column was made to be widens the column to fit, and the columns
after it move along. A column never gets narrower again because of this, and
never wider than the screen.

What a window says about its size is only used once it can be trusted: with
synchronous window handling and no animation in flight, and for an overhang
of more than 16px, so that rounding, a terminal's cell grid, or a window that
is still moving does not widen a column for good. Adopting a width is logged
at info level.
2026-10-30 15:45:37 -07:00
LGUG2Z 7c79625ba7 docs(schema): regenerate the schemas for the scrolling layout
schema.json gets the center_focused_column layout option as a boolean or one
of Never, Always and OnOverflow, and schema.bar.json, which embeds the socket
messages, gets the new scrolling commands.
2026-10-30 15:45:37 -07:00
LGUG2Z 598390d9cb feat(scrolling): add commands and config for the scrolling layout
Focus, move, resize, retile and closing a window now go through the strip of
columns in the Scrolling layout. New commands: consume, expel,
toggle-column-stack, scrolling-layout-full-width and center-focus. A top
level scrolling section configures centering, centring a lone column, and
the minimum height of a window in a column of several.
2026-10-30 15:45:37 -07:00
LGUG2Z 8c7327fd31 feat(layouts): share the platform-free half of the scrolling glue
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.
2026-10-30 15:45:37 -07:00
LGUG2Z 3b93035d48 feat(scrolling): lay out the scrolling layout with the scrolling model
The Scrolling layout now keeps a ScrollingSpace per workspace, keyed by
container id, instead of recomputing equal-width columns from the previous
layout on every update. Column widths follow layout_options.scrolling.columns
and persist as windows come and go.
2026-10-30 15:45:37 -07:00
LGUG2Z 6c4eb621d3 feat(scrolling): add a platform-free model of a scrollable strip of columns
Ported from komorebi-for-mac (feature/moar-scrolling). The crate has no
dependencies and no knowledge of windows; it is not used by komorebi yet.
2026-10-30 15:45:37 -07:00
LGUG2Z a4e03e3d76 test(resize): cover the top edge of the lower tile of a BSP layout
Dragging the edge two stacked tiles share moves it by the same amount from
either tile, in the layout and in the window manager. A drag of the top edge
of the lower tile that moves nothing is not for want of this.
2026-10-30 15:45:37 -07:00
LGUG2Z dc9b2e9539 fix(window): uncloak the windows a killed daemon left cloaked
A daemon that is killed does not get to uncloak the windows it hid, and the
next one skips them as cloaked, so they stay out of sight and unmanaged.

A cloak by komorebi reads the same as one for another virtual desktop or a
suspended app, so keep a record of the windows that are cloaked and uncloak
those that the last daemon left behind, before looking for windows.
2026-10-30 15:45:37 -07:00
LGUG2Z 0b57006053 chore(deps): update libz-sys to 1.1.31 for RUSTSEC-2026-0418
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.
2026-10-30 12:13:42 -07:00
LGUG2Z 5c8e4770dc fix(monitor): do not mistake an unplugged display for one that is still attached
Displays were matched on serial_number_id.eq(..) || device_id.eq(..), so
two displays with no serial number matched each other through None == None,
and two with no device path through the shared "UNKNOWN" device id. When
a display without either was unplugged, the one that stayed attached
"matched" it, nothing was removed, and every display change started the
3s verification again; state kept listing the display for good.

A serial number now identifies a display only when both have one and it is
not empty, and a display without a device path is told apart by its name.
The removal takes the monitors out by index instead of by id, so that two
displays sharing the id UNKNOWN are not removed together, and adding a
connected monitor no longer skips a display for sharing that id.
2026-10-30 12:13:42 -07:00
LGUG2Z 3b424dd707 fix(config): accept an integer for an initial window placement rule
PlacementTarget deserialized through String, so the integer the docs
promise ("initial_window_placement_rules": 2) made the daemon exit at
start with an untagged enum error while "2" worked. Accept integers as
well as strings.

The derived schema described an externally tagged object that neither
form matches, so describe the type by hand and regenerate both schemas.
2026-10-30 12:13:42 -07:00
LGUG2Z 837ca257d4 fix(monitor): validate the target before moving a container or workspace
move_container_to_monitor and move_workspace_to_monitor took the container
or workspace out of its place and only then looked the target monitor up,
so a monitor index that does not exist left the window on screen but in no
workspace. Check the index first so the command fails and nothing moves.
2026-10-30 12:13:42 -07:00
LGUG2Z 9b9cad997c fix(rules): keep a rule whose id another kind of rule already has
The socket handlers for manage, ignore, object-name-change, tray, layered
and title bar rules skipped a new rule when any simple rule had the same
id, whatever its kind, so ignore-rule exe foo after ignore-rule class foo
was dropped. Share one helper that compares the kind as well.
2026-10-30 12:13:42 -07:00
LGUG2Z a599e9ecc1 chore: keep the line endings LF
Everything but dependencies.json is stored with LF, which nothing said, so
a CRLF file could get in unnoticed (it did, for two files, in a round trip
that shows as a rewrite of every line of both).

* .gitattributes: normalize every text file to LF in the repository and
  check it out with LF, whatever core.autocrlf is (the Windows runner
  defaults it to true)
* rustfmt.toml: newline_style = "Unix", so cargo fmt --check fails on
  a Rust file with CRLF
* CI: fail when a file is stored with CRLF
* dependencies.json: the one file that was stored with CRLF
2026-10-30 12:13:42 -07:00
LGUG2Z 21a821aca0 fix(nix): get the build working again 2026-10-28 19:30:00 -07:00
LGUG2Z efe91ce332 chore(schema): regenerate the schemas 2026-10-28 15:18:11 -07:00
LGUG2Z f08aa55511 chore(deps): cargo update 2026-10-27 09:59:57 -07:00
LGUG2Z a3fac99a0f fix(wm): make resizing a tile by dragging its edge reliable
Measure mouse resizes from the rect the window had when the drag
started, work in edges instead of guessing from rect fields, resize the
container of the dragged window, and bound resizes by the resulting tile
sizes (granting as much as fits) rather than by the size of the
container being resized.
2026-10-27 09:59:57 -07:00
LGUG2Z e0709f02bf chore(deps): cargo update 2026-08-22 14:26:23 -07:00
LGUG2Z fd3d52c477 chore(deps): cargo update 2026-07-21 10:53:14 -07:00
LGUG2Z d29069398b chore(cargo): address clippy warnings 2026-07-21 10:50:26 -07:00
LGUG2Z 538053c9c8 chore(deps): cargo update 2026-06-24 14:58:47 -07:00
LGUG2Z a3b2e28dd5 feat(animations): set the ghost_movement default to false
There are a bunch of edge cases coming up with this behaviour. Setting
the default to false for now so people on the nightly can opt in as they
feel comfortable.
2026-05-04 19:09:28 -07:00
LGUG2Z 4e7d0e337c feat(wm): add monocle_focus_behaviour to gate monocle cycling
5f629e1f made directional focus cycle the monocle container in the
underlying ring. Useful on a single monitor, but undesired when focusing
across monitors — the focus stays trapped on the monocle workspace
instead of crossing the boundary.

This commit adds a new top-level monocle_focus_behaviour option with two
variants, Cycle (the post-5f629e1f behaviour) and NoOp (the pre-5f629e1f
behaviour, now the default), along with a ToggleMonocleFocusBehaviour
socket message and corresponding komorebic subcommands to flip between
them at runtime.
2026-05-04 19:09:27 -07:00
LGUG2Z e2e5dbfcae feat(wm): use ghost windows for movement animations
This commit tries to render move/resize animations on a DWM-thumbnail
"ghost" window instead of calling MoveWindow per-frame on the real HWND.

The source is cloaked via IApplicationView::SetCloak, the thumbnail is
animated via DwmUpdateThumbnailProperties on a layered host owned by a
single "ghost owner" thread, the border for the source follows the
lerped rect via a new WM_ANIMATE_RECT message handled on the border's
own WndProc thread (preserving today's per-frame border tracking), and
the real SetWindowPos happens once at the end of the animation.

Apps repaint exactly once per animation instead of N times, which is a
substantial win for heavy renderers (browsers, IDEs, Office). For
non-Chromium sources the source is also pre-positioned to target_rect
before the thumbnail is registered so the captured texture is target-
sized and downscales to native 1:1 at the end of the animation rather
than upscaling to a stretched/blurry final frame.

Chromium-shell sources  skip the pre-paint step: their
NativeWindowOcclusionTrackerWin reads DWMWA_CLOAKED and treats any cloak
value as hidden, suspending the renderer; WM_SIZE while cloaked produces
no new frame and the post-uncloak swap chain shows stale or black
content.

For those apps we keep the source cloaked at start_rect for the whole
animation and do the SetWindowPos in post_render after uncloak, where
the visibility flip is what wakes Viz back up.

A short ease-in opacity crossfade in post_render masks the texture
transition for the Chromium path and gives slow renderers time to
present their first post-resize frame before the overlay is removed.
2026-05-03 16:09:28 -07:00
LGUG2Z 937b28a7d9 chore(dev): begin 0.1.42-dev 2026-05-03 16:06:46 -07:00
LGUG2Z e9a541d12b chore(deps): bump flavours 2026-05-01 17:10:20 -07:00
LGUG2Z 588d22a9d2 chore(cargo): address clippy warnings 2026-05-01 15:17:33 -07:00
LGUG2Z 53ad7a2224 chore(deps): cargo update 2026-05-01 14:59:04 -07:00
LGUG2Z 26b1464381 fix(borders): prevent use-after-free take 4
This commit fixes a cross-thread use-after-free crash with exception
code 0xc000041d (FATAL_USER_CALLBACK_EXCEPTION), identified via WinDbg
analysis of a minidump where rax=0xfeeefeeefeeefeee at the crash site in
d2d1!HwndPresenter::Present - the Windows heap freed-memory fill pattern
confirming Direct2D dereferenced a previously freed object.

The root cause was a data race between the border manager thread and the
border's own message loop thread. Border::create() spawns a dedicated
thread (Thread B) for the HWND message loop and sends Box<Border> back
to the border manager thread (Thread A) via a channel. After this point
both threads accessed Border::render_target concurrently without any
synchronisation:

Thread A called update_brushes() directly on the Box<Border>, replacing
render_target with a new ID2D1HwndRenderTarget and dropping the old one.
Dropping the old RenderTarget decremented the COM refcount to zero,
causing D2D to free its internal HwndPresenter.

Thread B was concurrently mid-render in a WM_PAINT or
EVENT_OBJECT_LOCATIONCHANGE handler, holding a reference to that same
old render target obtained via the GWLP_USERDATA raw pointer. Calling
EndDraw() after HwndPresenter was freed produced the crash. The process
uptime of two seconds in the dump confirmed this happened during startup
workspace initialisation, when a ForceUpdate notification triggered
update_brushes() while the newly-shown border window was processing its
first WM_PAINT.

The fix routes all brush update requests through the border's own
message loop by posting a custom WM_UPDATE_BRUSHES (WM_USER + 1) message
instead of calling update_brushes() cross-thread. The three call sites
in the border manager that previously called border.update_brushes()?
directly now call border.request_brush_update(), which posts the message
via PostMessageW. The WndProc handler for WM_UPDATE_BRUSHES calls
update_brushes() and invalidate() entirely on Thread B, eliminating the
race.

A secondary bug in destroy() was also fixed: it was clearing
GWLP_USERDATA before posting WM_CLOSE, which caused WM_DESTROY's null-
pointer guard to skip the render_target = None cleanup. This left the
ID2D1HwndRenderTarget alive past HWND destruction, and D2D freed its
HwndPresenter during WM_NCDESTROY while the COM wrapper still held a
reference - a second path to the same crash for any message queued
between WM_NCDESTROY and WM_QUIT. The premature GWLP_USERDATA clear has
been removed; WM_DESTROY already handles it correctly after releasing
the render target.
2026-03-29 19:09:13 -07:00
LGUG2Z 8a1447f543 docs(schema): update jsonschema 2026-03-22 16:11:43 -07:00
LGUG2Z 53c81c4596 fix(wm): factor in monocle mode for work area offset rules 2026-03-22 16:11:43 -07:00
LGUG2Z 011bcb8bd4 refactor(clippy): apply lints 2026-03-22 16:11:43 -07:00
LGUG2Z dce3c91c22 chore(deps): various dependency bumps 2026-03-22 16:11:43 -07:00
LGUG2Z a9a1e68169 chore(git): add procdump.exe to gitignore 2026-03-21 13:39:50 -07:00
LGUG2Z 529d93595e chore(deps): cargo update 2026-03-21 12:38:45 -07:00
LGUG2Z 5f629e1f1a feat(wm): cycle monocle container when focusing in direction
This commit implements something I've found myself wanting while working
on the Macbook.

When I have a monocle container active, I want to quickly be able to
switch back and forth with an adjacent window in the underlying layout
without having to toggle monocle mode off and back on again.

This is now accomplished by using focus left/down to promote the
previous window in the Ring to monocle, and by using focus right/down to
focus the next window in the Ring to monocle.

Borders were being funny so I just ended up nuking them whenever we
cycle.
2026-03-08 19:49:50 -07:00
LGUG2Z 0f1854db8b ci(github): re-enable sunday cron jobs 2026-03-01 21:33:51 -08:00
LGUG2Z 6ca49d4301 chore(deps): cargo update 2026-02-20 16:58:40 -08:00
LGUG2Z 5b6fab0044 chore(dev): begin v0.1.41-dev 2026-02-20 16:56:51 -08:00
LGUG2Z bed314b866 chore(release): v0.1.40 2026-02-14 12:52:25 -08:00
LGUG2Z 5d7a0ea9ad chore(deps): cargo update 2026-02-12 20:35:29 -08:00
LGUG2Z 1dad13106a refactor(layouts): add darwin feature gate and expand win32 feature gate
This commit builds on the newly introduced komorebi-layouts crate to
make it suitable for wholesale adoption in komorebi for Mac.
2026-02-07 15:28:40 -08:00
LGUG2Z 0b5141e7a4 refactor(layouts): extract independent komorebi-layouts crate
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.
2026-02-07 15:28:40 -08:00
LGUG2Z 5946caaf92 docs(quickstart): enable fewer widgets in the bar's example config 2026-02-06 17:06:36 -08:00
LGUG2Z 01d73b7d19 fix(borders): prevent use-after-free take 3
This commit attempts tofixfixes a use-after-free bug in the
border_manager that was causing crashes with exception code 0xc000041d
(FATAL_USER_CALLBACK_EXCEPTION) when borders were being destroyed during
config updates.

The root cause was a race condition between the main thread destroying a
border window and the border's window thread still processing queued
window messages (EVENT_OBJECT_LOCATIONCHANGE, WM_PAINT).

The crash occurred when these callbacks invoked render_target.EndDraw(),
which internally calls HwndPresenter::Present() to present the rendered
frame to the HWND. By this point, the HWND and its associated Direct2D
surfaces had been freed by WM_DESTROY, resulting in Direct2D attempting
to dereference freed memory (0xbaadf00dbaadf00d - debug heap poison
value).

The previous attempts at fixing this issue (bdef1448, dbde351e)
addressed symptoms but not the fundamental race condition. bdef1448
attempted to release resources on the main thread before destruction,
but this created a cross-thread race. dbde351e moved resource cleanup to
WM_DESTROY, but this still allowed EVENT_OBJECT_LOCATIONCHANGE/WM_PAINT
handlers to check `render_target.is_some()`, context-switch to
WM_DESTROY which clears it, then context-switch back and call EndDraw()
on a now-invalid reference.

This commit attempts to eliminate the race condition by introducing an
atomic destruction flag that serves as a memory barrier between the
destruction path and the rendering paths:

- Added `is_destroying: Arc<AtomicBool>` field to the Border struct
- In destroy(): Sets the flag with Release ordering, sleeps 10ms to
  allow in-flight operations to complete, then proceeds with cleanup
- In EVENT_OBJECT_LOCATIONCHANGE and WM_PAINT: Checks the flag with
  Acquire ordering both at handler entry and immediately before calling
  BeginDraw/EndDraw, exiting early if destruction is in progress

The Acquire/Release memory ordering creates a synchronizes-with
relationship that ensures:

1. When the destruction flag is set, all subsequent handler checks will
   see it (no stale cached values)
2. Handlers that pass the first check but race with destruction will be
   caught by the second check before touching D2D resources
3. The 10ms sleep window allows any handler already past both checks to
   complete its EndDraw() before resources are freed

This is a lock-free solution with zero overhead on the hot rendering
path (atomic loads are nearly free) and provides defense-in-depth with
multiple barriers against the use-after-free condition.
2026-02-06 16:57:06 -08:00
LGUG2Z 9d16197825 chore(deps): cargo update 2026-02-06 16:57:06 -08:00
LGUG2Z fed09689b8 chore(deps): cargo update 2026-02-04 08:43:43 -08:00
LGUG2Z c0b298c9de docs(readme): add link to komorebi for mac repo 2026-01-30 20:18:57 -08:00
LGUG2Z 5fd7017b71 fix(wm): prevent dupes when enforcing ws rules
This commit ensures that we check if a window is already managed in any
workspaces even after checking known_hwnds, because windows moved as
part of the earlier ensure_workspace_rules call can slip through the
cracks.
2026-01-30 20:18:57 -08:00
LGUG2Z 95838fc896 build(just): add target for running procdump 2026-01-13 08:26:23 -08:00
LGUG2Z bdef1448e1 fix(borders): prevent use-after-free in border destruction
This commit fixes a use-after-free bug in the border_manager that was
causing crashes with exception code 0xc000041d when borders were being
destroyed during workspace/monitor changes.

The root cause was a race condition between the main thread destroying a
border window and the border's window thread still processing queued
window messages (WM_PAINT, EVENT_OBJECT_LOCATIONCHANGE). The crash
occurred when these callbacks invoked render_target.EndDraw(), which
internally calls HwndPresenter::Present() to present the rendered frame
to the HWND. By this point, the HWND and its associated DirectX surfaces
had already been freed, resulting in Direct2D attempting to dereference
freed memory (0xFEEEFEEEFEEEFEEE - Windows heap poison value).

The issue stemmed from two problems in destroy_border():

1. Direct2D resources (render_target and brushes) were not being
   released before closing the window. These COM objects hold internal
   pointers to the HWND and its DirectX swap chain/surfaces. When
   close_window() was called, Windows began tearing down these resources
   while the Direct2D objects still held dangling pointers to them.

2. GWLP_USERDATA was not being cleared before closing the window. This
   meant that any messages already queued in the window's message queue
   could still retrieve the border_pointer and attempt to render using
   the now-invalid Direct2D resources.

This commit addresses both issues:

- In destroy_border() (mod.rs): Explicitly set render_target to None and
  clear the brushes HashMap before calling destroy(). This ensures that
  Direct2D COM objects are properly released while the HWND is still
  valid, preventing EndDraw() from accessing freed HWND resources.

- In destroy() (border.rs): Clear GWLP_USERDATA before calling
  close_window(). This ensures that any pending window messages will see
  a null pointer and exit early from the callbacks (which already have
  null pointer checks in place).

These changes create two layers of defense against the race condition:
the callbacks won't access the border_pointer (it's null), and even if
they somehow did, the render_target would be None so no rendering
operations would occur.

I think this is the root cause of a lot of crash tickets that people are
mistakenly attributing to specific applications which lack
reproducibility across different users/machines, i.e. #1626, #1624.
2026-01-13 08:26:23 -08:00
LGUG2Z ab528f799d chore(deps): cargo update 2026-01-13 08:26:22 -08:00
LGUG2Z 8805fafa99 feat(bar): make explicit monitor config optional
This commit makes the monitor configuration option for the komorebi-bar
optional, defaulting to index 0.
2026-01-04 19:15:24 -08:00
LGUG2Z 1219c3d118 refactor(bar): inline defaults in schemars attrs 2026-01-04 19:08:41 -08:00
LGUG2Z b792328676 fix(splash): show mdm workspace tenant name instead of mdm url
The WorkspaceTenantName is populated far more consistently than MdmUrl.

This commit switches to extracting that instead and passing it on to the
MDM splash screen so that users on non-corporate devices who may have
unintentionally enrolled themselves into BYOD MDM by logging into an
account a clicking "Yes" on some dark pattern pop-up have a clear
indication of why they are seeing the splash, and can take the
appropriate steps to remove the MDM profile from their system if
desired.
2026-01-04 07:33:32 -08:00
LGUG2Z a7380db47c docs(readme): add debugging instructions for people who don't know they've been mdm'd 2026-01-04 07:15:59 -08:00
LGUG2Z 086993a7c0 fix(cli): respect --bar flag in start even when no config is resolved
I think this got broken as part of the automatic Rust version syntax
upgrades which joined two if clauses together with && which should have
been kept separate.

Now, if the user gives the --bar flag to the start command, and a static
config file is not resolved, or if the static config file does not have
a bar_configurations stanza, it will fallthrough to the default
PowerShell snippet to try and start komorebi-bar without an explicit
--config flag.
2026-01-03 16:55:59 -08:00
LGUG2Z 51e1337f40 fix(wm): consider window count when calculating scrolling column width
This commit fixes the stupidest of stupid bugs. Column width
calculations on the Scrolling layout should take the number of windows
into account, especially when lower than the configured column count.
2026-01-01 13:07:18 -08:00
LGUG2Z 6cef8d9ef6 refactor(schema): simplify defaults in static_config 2025-12-31 13:04:34 -08:00
LGUG2Z 6e36b81669 build(nix): add flake.nix for cross-compilation from darwin and linux
I was getting really tired of having to switch between display inputs to
different platform-specific machines to be able to make and test changes
on komorebi for Windows and komorebi for Mac.

With this commit, the `flake.nix` provides a Nix devShell and crane
build for users to make and validate changes with `cargo check`, `cargo
clippy` and `cargo build` with the Windows MSVC toolchain on Linux and
macOS.
2025-12-28 17:24:41 -08:00
LGUG2Z 0758c7d900 refactor(theme): centralize theme-related code in komorebi-themes
Getting tired of making little changes in both this and the komorebi for
Mac repo - I think eventually either komorebi-themes will live in its
own repo or komorebi for Mac will be integrated here.

But for now, at least everything is defined in komorebi-themes and I
don't have to redefine any theme-related stuff in komorebi for Mac.
2025-12-27 21:58:39 -08:00
LGUG2Z f77a303b30 docs(schema): ensure every enum variant has a renderable title 2025-12-27 20:34:31 -08:00
LGUG2Z 3a81f7babb docs(schema): ensure all public-facing bar config opts have docstrings 2025-12-27 13:40:45 -08:00
LGUG2Z 3d8778a7d6 docs(schema): ensure all public-facing static config opts have docstrings 2025-12-27 12:58:46 -08:00
LGUG2Z a42e809ade docs(config): encode defaults of unwrapped options into schema
This commit ensures that the various default values that the different
Option<T> config properties can be unwrapped to are encoded by schemars
so that they can be picked up by docgen.
2025-12-26 18:16:55 -08:00
LGUG2Z 66c5766848 feat(cli): add custom output fir for docgen cmd 2025-12-26 10:26:00 -08:00
LGUG2Z ac56590791 chore(clippy): address warnings 2025-12-23 17:19:00 -08:00
LGUG2Z 4d67f5fed3 build(just): update schemagen and add schemapub 2025-12-22 20:45:44 -08:00
LGUG2Z c91224295f docs(schema): avoid duplicating display format enums in bar 2025-12-22 19:30:29 -08:00
LGUG2Z 4b1e3bd448 docs(schema): add deprecations and improve formatting 2025-12-21 21:56:17 -08:00
LGUG2Z 1cb8ed7f10 chore(deps): bump schemars to 1.1 2025-12-21 16:26:25 -08:00
LGUG2Z 90271f1f99 docs(schema): clarify that 'theme' take priority over 'border_colours' 2025-12-20 21:12:56 -08:00
LGUG2Z 9fde9ed6f8 chore(deps): cargo update 2025-12-20 11:40:31 -08:00
LGUG2Z ce4479eb9f chore(deps): cargo update 2025-12-16 18:05:51 -08:00
LGUG2Z f3b7f5ac42 chore(clippy): odd unused_assignment failures in rust 1.92.0 2025-12-14 20:00:18 -08:00
LGUG2Z 382896dfd2 docs(readme): add detailed instructions for students w/ mdm devices 2025-12-14 14:16:48 -08:00
LGUG2Z ff4187aecf chore(dev): begin v0.1.40-dev 2025-12-14 14:07:44 -08:00
LGUG2Z 8f982e45d1 chore(release): v0.1.39 2025-12-09 17:06:14 -08:00
LGUG2Z 309bfdfee1 chore(deps): update dependencies.json 2025-12-09 16:55:47 -08:00
LGUG2Z a0239faea0 refactor(cli): use "args" var name uniformly 2025-12-07 19:09:56 -08:00
LGUG2Z 999dd5d20d chore(deps): cargo update 2025-12-06 14:02:52 -08:00
LGUG2Z 4114b10b05 chore(deps): cargo update 2025-11-25 09:00:14 -08:00
LGUG2Z 71402fe01b docs(wm): update splash for students 2025-11-25 08:59:35 -08:00
LGUG2Z ac67c41377 docs(schema): update jsonschema 2025-11-23 10:56:01 -08:00
LGUG2Z 4ebba08b7d chore(deps): bump whkd to v0.2.10 2025-11-22 12:47:11 -08:00
LGUG2Z df2adde13d feat(wm): remove scrolling layout column fallbacks
This commit removes the fallback to the columns layout when the number
of columns on the scrolling layout is less than 3.
2025-11-18 16:00:28 -08:00
LGUG2Z a77b3e774a fix(docs): replace deprecated aliases in komorebi.bar.example.json
This commit ensures that we are using show_total_activity and
show_activity instead of show_total_data_transmitted and
show_network_activity in the komorebi.bar.example.json file which is
populated for users in the quickstart command.

JSONSchema is not smart enough to resolve aliases for backwards compat,
which results in confusing behaviour for new users trying to edit this
file.

fix #1596
2025-11-14 08:02:04 -08:00
LGUG2Z c8c4c3507c chore(deps): handle egui-related upgrades 2025-11-12 16:20:19 -08:00
LGUG2Z df38facf9e feat(wm): make promote-swap reversible
This commit makes the komorebic promote-swap command reversible by
storing the previous container index in the Workspace state.

If the current container index is the same as the layout's primary
index, and there is a previous promotion swap container index available,
the two containers at those indices will be swapped, effectively making
a second call to promote-swap an undo.
2025-11-04 13:18:35 -08:00
LGUG2Z 416dd94670 feat(wm): promote containers by swapping indices
This commit adds a new SocketMessage variant PromoteSwap and
corresponding komorebic promote-swap command.

PromoteSwap will also promote the focused window container to the
largest tile in the layout, but instead of removing the focused
container x from the Ring and inserting it into position 0, possibly
changing the positions of other windows between 0 and x, the indices x
and 0 in the Ring will be swapped directly.
2025-11-04 08:02:07 -08:00
LGUG2Z d0ae92ca3a feat(wm): add visual feedback for preselection
This commit adds visual feedback in the form of a ghost tile for
preselections made by the preselect-direction command.

A container with the id "PRESELECT" will be added to the workspace, and
replaced when the next manage-able window is spawned.

A new command, cancel-preselect, has been added to remove both the
preselection index and the ghost tile if the user changes their mind.
2025-11-02 11:06:39 -08:00
LGUG2Z 3491dc7590 docs(readme): add note for people looking for komorebi for mac 2025-10-31 19:26:25 -07:00
LGUG2Z adbb6c1cb0 feat(wm): add direction preselection
This commit adds a new feature to preselect the direction of the next
spawned window with a corresponding komorebic preselect-direction
command which takes an OperationDirection.

If the OperationDirection is valid from the current position, it will be
stored in the Workspace state, and then read, applied, and deleted when
the next manage-able window is spawned.

Direction preselection does not (yet?) support the Grid layout.
2025-10-31 15:08:57 -07:00
LGUG2Z 1a42c64620 feat(cli): add feedback to the license cmd 2025-10-29 08:48:25 -07:00