65 Commits

Author SHA1 Message Date
LGUG2Z
ff4187aecf chore(dev): begin v0.1.40-dev 2025-12-14 14:07:44 -08:00
alex-ds13
a733fecb49 fix(client): expose more useful structs 2025-11-22 12:44:48 -08:00
LGUG2Z
b613986474 feat(wm): add a splash screen for mdm devices
A little nudge for people to do the right thing, 1990s vibes.
2025-10-28 18:03:17 -07:00
LGUG2Z
e953715fef feat(wm): track virtual desktop ids on state and global state
Also moved out State and GlobalState to state.rs to match the emerging
pattern in komorebi for Mac.
2025-10-14 13:11:12 -07:00
LGUG2Z
80877cc449 refactor(rust): upgrade to edition 2024 part 1 2025-09-24 11:09:08 -07:00
LGUG2Z
e07b464b0d chore(dev): begin 0.1.39-dev 2025-09-20 12:59:09 -07:00
JustForFun88
4bb3b83d57 refactor(bar) split komorebi widget into smaller parts
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 😅
2025-07-31 17:14:39 -07:00
LGUG2Z
eec6312a51 chore(dev): begin v0.1.38-dev 2025-05-17 20:26:13 -07:00
LGUG2Z
6a10d583a6 build(cargo): propagate expensive schemars feature correctly 2025-05-11 20:00:15 -07:00
LGUG2Z
577364a556 feat(bar): hide when leaving komorebi's virtual desktop
This commit adds a new VirtualDesktopNotification which is used to
notify subscribers when the user leaves and enters the virtual desktop
associated with komorebi.

komorebi-bar consumes these notifications to minmize and restore the bar
appropriately depending on the currently focused virtual desktop.

re #1420
2025-04-28 14:33:39 -07:00
LGUG2Z
a8b02f40fd chore(dev): begin 0.1.37-dev 2025-04-13 09:38:12 -07:00
amrbashir
9f8e4b9dca feat(core): use PathExt to unify env var resolution
This new implementation allows for expanding any environment variable so
it is not limited to just `~`, `$HOME`, `$Env:USERPROFILE` and
`$Env:KOMOREBI_CONFIG_HOME`.

It expands the follwing formats:
- CMD: `%variable%`
- PowerShell: `$Env:variable`
- Bash: `$variable`

I searched throughout the code base for path and migrate any code that
might need to PathExt::replace_env.

It is possible that I might have missed a few places due to my
unfamiliarity with the code base, so if you find any, please let me
know.

Most of the paths that needed this trait, are in:

- Clap arguments, and that was handled by #[value_parse] attribute and a
  helper function.
- SocketMessage and that was handled by custom deserialization with the
  help of serde_with crate
2025-04-06 21:17:35 -07:00
LGUG2Z
2ee0bbc0c7 refactor(themes): move colour.rs to komorebi-themes 2025-04-02 13:23:31 -07:00
alex-ds13
96fdbbd1fb fix(client): re-export FloatingLayerBehaviour 2025-03-31 15:23:10 -07:00
alex-ds13
30fbc1ae73 feat(client): reexport win32_display_data
This commit reexports the `win32_display_data` crate so that any 3rd
party app that needs it can get it through the `komorebi-client` without
having to keep manually synchronizing it with the version used by komorebi.
2025-03-22 19:35:23 -07:00
LGUG2Z
edf1943157 chore(dev): begin v0.1.36-dev 2025-03-22 12:14:43 -07:00
LGUG2Z
fe9a1416e7 feat(config): allow multiple asc files
This commit allows either the single canonical applications.json file,
or multiple files which adhere to the asc scheme to be given to the
app_specific_configuration_path config option.

I thought I had already implemented this earlier, but evidently I
hadn't.

This will be useful for people who want to maintain their own
independent set of asc rules, as they can be kept in a dedicated file
which won't be overwritten by the fetch-asc command.

resolve #736
2025-03-13 19:35:14 -07:00
LGUG2Z
fe20caa56a fix(client): expose schemars feature and allow opt-out 2025-03-05 15:49:46 -08:00
LGUG2Z
1761919707 perf(client): disable schemars feature on komorebi lib dep 2025-03-03 21:49:43 -08:00
alex-ds13
0776ca1565 feat(border): cache borders on all workspaces
This commit refactors the `border_manager` with the following changes:

- Rework the way the borders are created and their pointer is sent to
  the window message handler. Now we also store the same pointer as a
  `Box<Border>` on the `border_manager`'s `BORDER_STATE`. This means
  that the borders we have are exactly the same ones that the border
  window itself is accessing so we can now store the border's info
  inside the `Border` struct and all of it will be accessible by the
  border window as well. This makes it so the "ACTUAL" border struct is
  the one created on the thread of the `Border::create()` function and
  when that thread finishes (after the border window closes) it will
  handle the drop of the border itself. However this means we need to be
  careful with our own stored `Box<Border>` since it will point to the
  same memory we can't let the compiler dropped them as usual or
  otherwise it would create heap corruption errors. So this commit
  creates a special function called `destroy_border()` to actually close
  the window border without dropping the border, since it will be later
  dropped by the thread that created it.

- Remove `BORDERS_MONITORS`, `FOCUS_STATE` and `RENDER_TARGETS` arc
  mutexes, since now this info is stored on the border itself.

- Change the `BORDER_STATE` to now map an id (container or window) to a
  `Box<Border>`.

- Change the `WINDOWS_BORDERS` to now map a window hwnd to a border id.

- Create new struct `BorderInfo` which as the border window hwnd and the
  border kind. This struct is what is now returned by the function
  `window_border()` which checks if some window as a border attached to
  it and if it does it returns this info. There is no need to clone the
  entire border. If in the future we need more info we can just add it
  to this struct.

- Change the way we clear the `BORDER_STATE`. Like mentioned before we
  need to be sure we don't drop the `Box<Border>` when removing it, so
  now we use the `.drain` function to remove all the borders as an
  iterator and we call the `destroy_border()` on each border we are
  removing.

- We now check if a border's `tracking_hwnd` has changed and if it does
  we simply update it instead of destroying the border and create a new
  one.

- Create function `delete_border` so that we can remove a border
  properly from outside the `border_manager`.

- Create function `hide_border` which spawns a new thread that searches
  if a window hwnd has a border attached to it and if it does it hides
  said border window. This function is called on every `window.hide()`.

- Create function `show_border` which spawns a new thread that searches
  if a window hwnd has a border attached to it and if it does it restores
  said border window. This function is called on every `window.restore()`.

- This commit also changes the previous `window.hide()` and
  `window.restore()` functions to be named:
  - `window.hide_with_border(hide_border: bool)`: this is the same
    function as before but adds a check at the end in case `hide_border`
    is true it calls `border_manager::hide_border()`. A new function was
    created with the same name as before `window.hide()` which by
    default calls this new function with `hide_border = true`.
  - `window.restore_with_border(restore_border: bool)`: this is the same
    function as before but adds a check at the end in case `hide_border`
    is true it calls `border_manager::hide_border()`. A new function was
    created with the same name as before `window.hide()` which by
    default calls this new function with `hide_border = true`.

- This commit creates a new function on `Container` called
  `load_focused_window_ignore_borders()` which performs the same as
  `load_focused_window()` but it ignores the borders when hiding and
  restoring the windows. This function, along with the
  `hide_with_border(false)` and `restore_with_border(false)` are used on
  all functions related to changing focus on a stack since if we let the
  borders be hidden and restored when cycling or changing focus on a
  stack the border would flicker slightly, this prevents that. Ignore
  borders when clicking on the stackbar as well.
  (P.S. there might still be other places that I forgot to use these new
  functions, but if that is the case then what will happen is a simple
  flicker of the stack border...)

- The `remove_window` from `Workspace` needs to call the
  `border_manager::delete_border()` so that wew make sure we remove that
  windows's border window as well if it exists. This is essential when
  enforcing workspace rules, otherwise the border would be left behind.

- Lastly, but not least, now that we hide the borders windows along with
  their tracking window, we no longer remove the borders when swapping
  workspaces or when toggling monocle, etc. Instead we keep all borders
  of all workspaces cached and simply hide them. They are only removed
  when their tracking window is closed or cloaked on a stack (since on a
  stack we only keep one border for all the entire stack container).
  This means that when changing between workspaces we no longer see the
  borders showing up delayed after the windows show up. Now both the
  window and it's border show up as if they are one and the same.
2025-03-03 21:15:45 -08:00
alex-ds13
2bbc269b9f feat(wm): add padding per monitor
This commit adds the ability to set container and workspace padding per
monitor.

To do so (and to simplify any future need of changing some value per
monitor), and have it pass through to each workspace a new field was added
to `Workspace` called `globals` which has a new struct called
`WorkspaceGlobals`.

`WorkspaceGlobals` includes any global values that might be needed by
the workspace.

This field is updated by the monitor for all its workspaces whenever the
config is loaded or reloaded. It is also updated on `RetileAll` and on
the function `update_focused_workspace`.

This should make sure that every time a workspace needs to use it's
`update` function, it has all the `globals` up to date!

This also means that now the `update` function from workspaces doesn't
take any argument at all, reducing all the need to get all the
`work_area`, `work_area_offset`, `window_based_work_area_offset` or
`window_based_work_area_offset_limit` simplifying the callers of this
function quite a bit.

Lastly this commit has also (sort of accidentaly) fixed an existing bug
with the `move_workspace_to_monitor` function.

This was previous removing the workspace from a monitor, but wasn't
changing it's `focused_workspace_idx`, meaning that komorebi would get
all messed up after that command. For example, the `border_manager`
would get stuck and the komorebi-bar would crash.

Now, the `remove_focused_workspace` function also focuses the previous
workspace (which in turn will create a new workspace in case the removed
workspace was the last workspace).
2025-02-23 09:52:33 -08:00
LGUG2Z
9d41a293f6 feat(wm): add tiling and floating ws layers
This commit introduces an implementation of workspace layers to
komorebi.

Workspace layers change the kinds of windows that certain commands
operate on. This implementation features two variants,
WorkspaceLayer::Tiling and WorkspaceLayer::Floating.

The default behaviour until now has been WorkspaceLayer::Tiling.

When the user sets WorkspaceLayer::Floating, either through the
'toggle-workspace-layer' command or the new bar widget, the 'move',
'focus', 'cycle-focus' and 'resize-axis' commands will operate on
floating windows, if the currently focused window is a floating window.

As I don't have 'cycle-focus' bound to anything, 'focus up' and 'focus
down' double as incrementing and decrementing cycle focus commands,
iterating focus through the floating windows assigned to a workspace.

Floating windows in komorebi belong to specific workspaces, therefore
commands such as 'move' and 'resize-axis' will restrict movement and
resizing to the bounds of their workspace's work area (or more
accurately, the work area of the monitor that the workspace belongs to,
as floating windows are never constrained by workspace-specific work
area restrictions).
2025-02-22 15:57:22 -08:00
alex-ds13
c62405bfaa fix(bar): restore + reposition on monitor reconnect 2025-02-20 19:54:05 -08:00
LGUG2Z
c903cdbb75 chore(dev): begin v0.1.35-dev 2025-02-20 19:31:27 -08:00
pro470
e629baec0a feat(client): expose custom layout column enum
This now allows integrators to deal with custom layout data.
2025-02-14 15:32:32 -08:00
alex-ds13
86bbcac5ae feat(client): add more re-exports for integrations
This commit is a squashed commit of all the individual commits that made
up PR #1267 - adding various derives and re-exports aimed at improving
the komorebi integration surface for third party applications.
2025-02-07 15:53:38 -08:00
alex-ds13
5c3c3659b5 feat(wm): notify subscribers of monitor events
This commit allows notifying the subscribers of any monitor events like
display connection change or work area change.
2025-01-24 11:48:29 -08:00
Csaba
4123c9a0e2 refactor(bar): resolve env vars with pathext
This commit introduces a new PathExt trait with a fn replace_env which
can ensure all environemnt variables are loaded for a PathBuf.

As part of the initial rollout this is used in komorebi-bar to look up
environment variables for the configuration switcher widget.

resolve #1131
2025-01-24 11:44:13 -08:00
LGUG2Z
b451df0379 chore(dev): begin v0.1.34-dev 2025-01-11 15:06:50 -08:00
LGUG2Z
5a8f48c6b9 chore(dev): begin v0.1.33-dev 2025-01-03 18:20:23 -08:00
alex-ds13
9463c75f12 feat(client): create send_batch helper
This commit adds a helper function `send_batch` to komorebi-client that
allows sending multiple messages in a batch.

3rd party users of this library could already do this themselves but it
is nice to have this helper to simplify it.
2024-12-14 08:59:29 -08:00
LGUG2Z
6c07863b81 chore(dev): begin v0.1.32-dev 2024-12-14 08:53:42 -08:00
alex-ds13
01367f59e2 fix(client): add write-timeout to prevent blocking 2024-11-29 08:11:36 -08:00
thearturca
449ccac645 refactor(animation): new animations engine
This commit is comprised of the following interactively rebased commits
from PR #1002 by @thearturca.

1a184a4442
refactor(animation): move animations to its own mod

First step for more rusty version animations. The goal is to make
animations more generic so its easier to add new animations to komorebi!

d3ac6b72c2
refactor(animation): reduce mutex calls on `ANIMATION_STYLE`

8a42b738fe
refactor(animation): introduce `Lerp` trait

e449861c10
refactor(animation): generalized ANIMATION_MANAGER

Instead of a isize key for the ANIMATION_MANAGER HashMap, now we use a
String key. For window move animation, the key would be
`window_move:{hwnd}`.

This allows us to use single manager for more types of animations.

67b2a7a284
feat(animation): introduce `AnimationPrefix` enum

8290f143a6
feat(animation): introduce `RenderDispatcher` trait

2400d757fe
feat(animation): implement window transparency animation

This commit also fixes graceful shutdown of animations by disabling them
before exit and wait for all remaining animations for 20 seconds.

44189d8382
refactor(animation): move generation of `animation key` to `RenderDispatcher`

e502cb3ffb
refactor(animation): rename `animation` mod to `engine`

Linter was upset about this:
> error: module has the same name as its containing module

369107f5e0
feat(config): adds per animation configuration options

Originally static config only allowed global config for animations.

Since this refactor introduces the abilty to add more type of
animations, this change allows us to configure `enabled`, `duration` and
`style` state per animation type.

Now each of them take either the raw value or a JSON object where keys
are the animation types and values are desired config value. Also adds
support for per animation configuration for komorebic commands.
2024-11-25 20:42:56 -08:00
LGUG2Z
d55d356b37 chore(dev): begin v0.1.31-dev 2024-11-04 07:58:49 -08:00
LGUG2Z
b612066367 feat(config): add support for v2 asc json
This commit adds support for a v2 format of the application specific
configuration file, centralizing on JSON to maximize the knowledge
crossover for people already familiar with the types used in
komorebi.json.

The biggest difference besides the format change is that matchers must
be used explicitly for every kind of rule, rather than being able to
specify options on a default rule. This is a bit more verbose, but
ultimately allows for significantly more flexibility.
2024-10-14 16:50:03 -07:00
LGUG2Z
5da72e10df feat(client): add subscribe_with_options
This commit adds a new method, subscribe_with_options to
komorebi-client.

The first option introduced is to tell komorebi to only send
notifications when the window manager state has been changed during the
processing of an event.

This new subscription option is now used with komorebi-bar to improve
rendering and update performance.
2024-10-13 15:07:31 -07:00
LGUG2Z
a1f1be0afe chore(dev): begin v0.1.30-dev 2024-09-28 11:50:25 -07:00
LGUG2Z
360d0915a1 refactor(deps): unify versions across workspace pkgs 2024-09-19 21:33:03 -07:00
LGUG2Z
df19d06333 feat(cli): generate json schemas locally
This commit updates the various komorebic json schema generation
commands to generate the schemas locally, without requiring a running
instance of komorebi to communicate with over IPC.
2024-09-18 10:59:25 -07:00
LGUG2Z
b69db863f1 feat(themes): update bar on komorebi.json reload
This commit ensures that whenever komorebi.json is updated, komorebi-bar
will try to apply whichever theme is set in that file by the user (if
one is set).

Similarly, if a theme is not set in komorebi.bar.json, komorebi-bar will
load the theme set in komorebi.json (if one is set).

A new configuration "bar_accent" has been added to the KomorebiTheme
struct to make this process as uniform as possible.
2024-09-15 10:34:37 -07:00
LGUG2Z
821a124771 fix(wm): socket cleanup on exit
This commit ensures that Shutdown signals will be sent to subscriber
sockets and that "komorebi.sock" will be cleaned up on exit.

Alongside these changes, komorebi_client::send_message no longer retries
so that integrators can receive feedback via io::Result errors when
komorebi is not running.
2024-08-12 19:07:33 -07:00
LGUG2Z
81451cb17a refactor(client): use public interface exclusively
This commit demotes the komorebi-core crate to a module (core) inside of
the komorebi lib, resulting in the komorebi-client crate lib becoming
the single public interface for programming in Rust against komorebi.

komorebic and komorebi-gui now consume komorebi-client exclusively as
the means for sending and receiving messages to and from komorebi, so
that anyone wishing to integrate with komorebi will have all of the same
functionality to them as I do.
2024-07-15 17:11:35 -07:00
LGUG2Z
7653495e31 chore(dev): begin v0.1.29-dev 2024-07-15 17:11:35 -07:00
LGUG2Z
0cdce8fc2a chore(release): v0.1.28 2024-07-15 08:59:42 -07:00
LGUG2Z
9a65a4ae92 chore(dev): begin v0.1.28-dev 2024-06-20 20:26:07 -07:00
LGUG2Z
a511cbd263 chore(release): v0.1.27 2024-06-19 14:52:54 -07:00
LGUG2Z
03fdbea5cd refactor(ahk): remove derive-ahk and references
This commit finally sunsets the derive-ahk proc macro and the
ahk-library cli command.

There is now a dedicated, stripped down komorebi.ahk example on the docs
website which mirrors the contents and style of the sample whkdrc:
https://lgug2z.github.io/komorebi/common-workflows/autohotkey.html
2024-05-23 22:57:27 -07:00
LGUG2Z
e46a0757e3 chore(dev): begin v0.1.27-dev 2024-05-23 16:53:57 -07:00
LGUG2Z
3556f38469 chore(release): v0.1.26 2024-05-22 15:36:20 -07:00