Created a test to test toggle monocle when a container doesn't exist in
the monitor. The test ensures that we receive an error when attempting
to call toggle monocle when a monitor doesn't contain a container.
Created a test to test trying to float a nonexistent window. The test
ensures that we receive an error when trying to float a window in an
empty container
Created a test to test cycling windows in an empty container. The test
ensures that when attempting to cycle windows in an empty container it
will push out an error.
Created a test that tests removing a nonexistent window from a
container. The test creates a monitor containing an empty container and
attempts to remove a window from the container. The test ensures that
the result is an error when calling remove_window_from_container.
This commit adds the option to set 'work_area_offset' per workspace. If
no workspace work area offset is set for that workspace it will instead
use the value of the globals.work_area_offset for that workspace.
This commit adds a command to set the work area offset of a workspace
given a monitor index and a workspace index.
This PR significantly refactors the komorebi bar rendering logic,
simplifying state management, and addressing some found bugs. The
primary motivation was to make the codebase more readable and
maintainable.
Key Changes:
- Allocation Reduction: Removed most per-frame structure allocations.
- Runtime Matching Elimination: Replaced runtime pattern matching with
pre-selected function pointers determined at initialization. Widget
validations and configurations are now performed during widget
creation rather than per-frame checks. For example, widget enablement
is now handled by an Option that wraps each ..Bar structure. If a
widget is enabled, its structure is present; otherwise, it is None.
This eliminates the need for runtime enabled checks.
- Widget Modularity: Code is split into smaller parts, reducing
complexity.
Bug Fixes:
- Corrected icon sizing for floating windows following regular
containers, ensuring icons revert correctly from icon_size to
text_size.
- There was also another bug with a floating window positioned above a
monocle container, but I forgot the details 😅
There are currently a number of commands that do not update the previously focused workspace
correctly. The previous method relied on handling each case, this change makes it so that
last_focused_workspace is always updated whenever the focus is changed.
- Removed command filtering logic from the shortcuts UI.
- All hotkey bindings are now shown regardless of command.
- Improved UI with hint text for the filter input.
Key Changes
- Added `locked: bool` field directly to the `Container` struct.
- Removed `locked_containers` from `Workspace`.
- Updated `komorebi_bar` to access `locked` directly
from `Container`.
Insert and swap operations respects `locked` container
indexes in the sequence
Following discussing in #1475, and considering the default of the
komorebi widget in komorebi-bar, this commit updates the default
StackbarLabel from Process to Title.
resolve#1475
This commit ensures that unstack_all is called on a workspace before
attempting to proceed with stack_all to avoid stacking loops that can
occur when there are multiple pre-existing stacks already created on the
workspace.
This commit ensures that the WM_SETCURSOR message is handled by stackbar
windows by setting the cursor to the default IDC_ARROW, which prevents
the spinning "Loading" icon from showing on hover.
re #1456
This commit adds a new DefaultLayout::Scrolling variant, along with a
new LayoutOptions configuration which will initially be used to allow
the user to declaratively specify the number of visible columns for the
Scrolling layout, and a new komorebic "scrolling-layout-columns" command
to allow the user to modify this value for the focused workspace at
runtime.
The Scrolling layout is inspired by the Niri scrolling window manager,
presenting a workspace as an infinite scrollable horizontal strip with a
viewport which includes the focused window + N other windows in columns.
There is no support for splitting columns into multiple rows.
This layout can currently only be applied to single-monitor setups as
the scrolling would result in layout calculations which push the windows
in the columns moving out of the viewport onto adjacent monitors.
This implementation in the current state is enough to be useable for me
personally, but if others want to iterate on this, make it handle
hiding/restoring windows correctly when scrolling the viewport so that
adjacent monitors don't get impacted etc., patches are always welcome.
resolve#1434
Created a test for swapping a container with a container that doesn't
exist, which ensures that we receive an error and that the contents of
the container is still available when attempting to swap a container
with a non-existent one.
A bug was discovered where the origin container was being removed even
though the swap_container function would return an error.
@LGUGZ discovered that the issue was due to the origin container being
removed before verifying that both containers exist. The fix that @LGUGZ
came up with is included.
Created a test for focusing on a monitor that doesn't exist, which
ensures that we receive an error and that we are still focused on the
current monitor when attempting to focus a non-existent monitor.
Created a test for swapping workspaces with a monitor that doesn't
exist, which ensures that we receive an error and that none of the
workspaces were moved when attempting to swap workspaces with a monitor
that doesn't exist.
PR #1439 authored and submitted by @JustForFun88
I understand this PR combines two areas of work — refactoring the
Applications widget and introducing a new icon caching system —
which would ideally be submitted separately.
Originally, I only intended to reduce allocations and simplify icon
loading in `applications.rs`, but as I worked through it, it became
clear that a more general-purpose caching system was needed. One
improvement led to another ... 😄
Apologies for bundling these changes together. If needed, I’m happy to
split this PR into smaller, focused ones.
Key Changes
- Introduced `IconsCache` with unified in-memory image & texture
management.
- Added `ImageIcon` and `ImageIconId` (based on path or HWND) for
caching and reuse.
- `Icon::Image` now wraps `ImageIcon`, decoupled from direct `RgbaImage`
usage.
- Extracted app launch logic into `UserCommand` with built-in cooldown.
- Simplified config parsing and UI hover rendering in `App`.
- Replaced legacy `ICON_CACHE` in
`KomorebiNotificationStateContainerInformation`
→ Now uses the shared `ImageIcon::try_load(hwnd, ..)` with caching and fallback.
Motivation
- Reduce redundant image copies and avoid repeated pixel-to-texture
conversions.
- Cleanly separate concerns for launching and icon handling.
- Reuse icons across `Applications`, Komorebi windows, and potentially
more in the future.
Tested
- Works on Windows 11.
- Verified path/exe/HWND icon loading and fallback.
This commit ensures that the user can't get into a weird state by
attempting to float a monocle container. If a user attempts to call
toggle-float on a monocle container, a warning will be logged and the
command will be ignored.
This commit adds a new StateQuery variant, FocusedContainerKind, which
will will return None if there is not focused container on the current
workspace (ie. it is empty), Single if the focused container contains a
single window, or Stack if the focused container contains more than one
window.
This commit makes it possible to send commands from the bar by using the
mouse/touchpad/touchscreen.
Komorebi or custom commands can be sent by clicking on the mouse's
primary, secondary, middle, back or forward buttons.
As the primary single click is already used by widgets, only primary
double clicks can send commands. This limitation is due to Egui also
triggering 2 single clicks before a double click is triggered. Egui does
not have an implementation for stopping event propagation out of the box
and would be too much work to include.
Similarly, commands can be sent on every "tick" of mouse scrolling,
touchpad or touchscreen swiping in any of the 4 directions. This "tick"
can be adjusted to fit user's preference.
This is due to the fact, that Egui does not have an event for when a
mouse "tick" occurs. It instead gives a number of points that the user
scrolled/swiped on each frame.
PR: #1403
Created a test for the transfer_window function.
The tests attempts to transfer a window to a monitor that doesn't exist,
and checks to see if we return an error. The test successfully gets an
error but there is a bug where the window isn't in the contiainer after
a failed transfer. I wrote a note comment to explain the bug just in
case we need to reference back to it.
Created a test for moving the focused workspace to a monitor that hasn't
been created. The test ensures that we receive an error when moving a
workspace to a monitor that doesn't exist.