Commit Graph

1562 Commits

Author SHA1 Message Date
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
Csaba
22e8a79833 feat(wm): add layout_options with ratios support
Added customizable split ratios for layouts via layout_options
configuration. Users can now specify column_ratios and row_ratios arrays
to control window sizing in various layouts.

Ratios are validated at config load time: values are clamped between 0.1
and 0.9 to prevent zero-sized windows, and arrays are automatically
truncated when their cumulative sum would reach or exceed 1.0. This
ensures there's always remaining space for additional windows.

Ratio support varies by layout:

- Columns and Rows layouts use the full arrays for each column/row width
  or height
- VerticalStack, RightMainVerticalStack, and HorizontalStack use the
  first ratio for the primary split and the remaining ratios for stack
  windows
- BSP uses the first value from each array for horizontal and vertical
  splits respectively
- Grid only supports column_ratios since row counts vary dynamically.
- UltrawideVerticalStack uses the first two column ratios for center and
  left columns.

All ratio-related values are now defined as constants in
default_layout.rs: MAX_RATIOS (5), MIN_RATIO (0.1), MAX_RATIO (0.9),
DEFAULT_RATIO (0.5), and DEFAULT_SECONDARY_RATIO (0.25 for
UltrawideVerticalStack).
2026-02-07 15:27:48 -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
Rejdukien
dbde351e22 fix(border): release resources before destroying window to prevent access violations
When a border is destroyed, the main thread was forcefully releasing D2D
resources, while the border window thread might still be trying to use
them in its message loop.

Releasing the RenderTarget on one thread while another is calling
EndDraw on it leads to a use-after-free scenario or invalid state for
the COM object, resulting in the crash.

This commit applies a fix that moves the resource cleanup logic from the
main thread to the window thread. Now, resources are only released
during the WM_DESTROY message processing, which guarantees
synchronization with other window messages like WM_PAINT.
2026-01-30 20:18:43 -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
Rejdukien
0b39551470 fix(wm): clear last error before calling GetWindowLongPtrW
Apparently there is a quirk of GetWindowLongPtr when querying styles. If
the style bits are genuinely 0, the API returns 0 but does not clear the
last error.

If a previous API call set an error, GetWindowLongPtr might define
"failure" as "return 0 AND GetLastError != 0".

Hence, it is important to clear the last/previous error before calling
GetWindowLongPtrW to ensure that we don't misinterpret a valid 0 return
value as an error.
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 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
bilogic
69086299e1 ci(github): render backticks in bug report template 2025-11-30 11:30:39 -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
dependabot[bot]
5c2767d589 chore(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 14:42:05 -08:00
LGUG2Z
ac67c41377 docs(schema): update jsonschema 2025-11-23 10:56:01 -08:00
Csaba
faed6ec535 fix(bar): update the network widget in a separate thread
This commit changes the way how the default interface and network
activity is loaded by spawning a new thread on each request. This way
the main thread is not blocked by this process.

There has been instances where getting the default interface blocked the
egui ui thread, resulting in a frozen bar.

fix #1423 #1499
2025-11-23 10:55:55 -08:00
LGUG2Z
4ebba08b7d chore(deps): bump whkd to v0.2.10 2025-11-22 12:47:11 -08:00