This commit adds the `unfocused_locked` color to the border_colours so
that users that don't use themes can still customize this color like
they do the others.
This commit adds a new StateQuery::Version, which allows integrators to
make decisions about how to handle different versions of komorebi's
state schema based on the version of komorebi that is running on a
user's machine.
This commit changes the way the alt-tab reconciliation is done.
It no longer uses the `workspace_reconciliator` with the sending of
notifications.
Instead there is a simple function that checks if the shown/uncloaked
window is already handled by komorebi and if it is it will check if it
is on an unfocused workspace and/or if it is an unfocused window of a
stacked container, returning the monitor/workspace index pair of said
window.
If we get this pair then we perform the reconciliation immediately by
focusing the monitor, workspace, container and window indices
corresponding to that window.
Added tests for the focus_container_by_window and
contains_managed_window functions.
test_focus_container_by_window crates two containers with different
distinct windows. The test checks to see if we are focused on the
expected container and window.
test_contains_managed_window creates two containers and checks to ensure
that when calling the function returns the expected result when checking
if a window is available in one of the containers.
Added a test for adding a new floating window. The test creates a
container with three windows and attempts to add one of the windows to
the list of floating windows, then checks to see if the first window in
the container was added to the floating window list and also checks the
list of windows and floating windows to ensure we get the expected
result.
This commit adds a --log-level flag to komorebi.exe which allows the
user to set the logging verbosity without setting the RUST_LOG
environment variable directly. If the RUST_LOG environment variable is
set, it will take precedence over the --log-level flag.
This commit adds a new option to the WorkspaceConfig object,
floating_layer_behaviour, which allows the user to either set
FloatingLayerBehaviour::Tile or FloatingLayerBehaviour::Float. Although
I prefer Float as a default, there was a good enough argument to make
Tile the default based on the fact that the Floating layer is
automatically engaged based on the focused window, and previously when
the focused window was a floating window, new windows would be tiled
unless they matched floating rules.
Added a test for sending a MonitorNotification using the
send_notification function. The test sends a MonitorNotification and
tests that the notification was recieved using event_rx.
Added a test for inserting a monitor into the cache. The test creates
a monitor and uses the insert_in_monitor_cache function to insert the
monitor into cache, and will attempt to retrieve the monitor from the
cache and check to see if it matches the expected value.
Addaded a test for channel capacity. The test will send 20 notifications
and then another notification, then check to ensure that all 20
messages match the notification we sent. The test will also check to
ensure the last notification sent wasn't received.
Added a test for the notification listener. The test will create a
window manager and setup the notification listener, then check to see if
we can send a notification and receive the notification.
Created a Mock Monitor that can be used with testing functions that call
the Win32 API.
Added a test for the attach_display_devices function. The test will
create a Mock Monitor and add the monitor to a closure that simulates a
display_provider. The test passes the display_provider into the
attach_display_devices function and checks to ensure we recieve the
monitor we passed in.
This commit raises and lowers all the floating windows so that they show
up with the smaller windows on top and the bigger windows on the bottom
when we toggle between layers.
This commit tries to focus the floating windows depending on the
direction used. It takes into account the top left corner of each window
and uses that to look for the closest top left corner in the direction
provided.
If there are no windows found in that direction, it then checks if it
can focus across monitor.
This commit changes the `floating_windows` from a `Vec<Window>` to a
`Ring<Window>` which allows us to keep track of the focused floating
window.
This combined with the existing layer switch allows us to know when we
should focus the focused container or the focused floating window.
This commit adds two new komorebic commands, move-to-last-workspace and
send-to-last-workspace, which move or send the focused window to the
last focused workspace on the focused monitor.
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.
This commit adds some dependency injection to the monitor reconciliator
module to make it easier to test the behaviour when different kinds of
data are returned from win32_display_data.
This commit adds the concept of locked container indexes to komorebi
workspaces.
When a container index is locked, it can only be displaced by manual
user actual - usually when another container is moved there, and when
this happens, that container becomes the locked container.
In the locked state, the container at the locked index should never be
displaced by new windows opening or existing windows around it being
closed.
When the total number of containers on a workspace falls below the
number of the locked index, the locked index will be removed.
A locked index can be identified by a special border color linked to the
new WindowKind::UnfocusedLocked variant.
The implementation of locked container indexes is backed by a new data
structure called a LockedDeque, which is a VecDeque with an auxiliary
HashSet which keeps track of locked indices.
A new komorebic command "toggle-lock" has been added to support
programmatic use of this feature, as well as the
LockMonitorWorkspaceContainer and UnlockMonitorWorkspaceContainer
SocketMessage variants which can be used by status bars.
This commit changes the behaviour of when floating windows are centered
by making them only center when we are on a `WorkspaceLayer::Floating`
and the window doesn't match a `floating_windows` rule and the workspace
is not a floating workspace.
This commit fixes a rare issue, seen exclusively with Acer monitors so
far, where two monitors of the same model can have an identical serial
number id.
If we encounter a system which has two connected monitors with the same
serial id number, the serial id number will be forcefully unset and
blacklisted for the rest of the session.
In this case, users must fall back to using device_id for options like
display_index_preferences.
Possibly a little overkill, but since this has been such a headache I'm
going to opt for this approach over #1368 for now.
This commit ensures that the WM_SETCURSOR message is handled by border
windows by setting the cursor to the default IDC_ARROW, which prevents
the spinning "Loading" icon from showing on hover.
Some credit is due to the user steiner5 on Discord for whining about me
not being interested in working on this while more generally complaining
about komorebi, which consequently made me want to work on this out of
spite since he's probably going to bounce off the software anyway.
Added a test for the cycle_window_in_direction function. The function is
tested by creating 3 windows and cycling in both the next a previous
direction. The test will ensure that the windows were cycled by checking
the window index to ensure it is the expected window.
Created a test for cycling the window by index. This test is similar to
the other cycle window test and performs the same steps as that one,
except it uses the test_cycle_container_index_in_direction function
instead.
This commit removes some workarounds on the `update_focused_workspace`
function that were there to fix issues related to some bugs on the
`workspace.restore()` function.
This commit fixes the bugs on the `restore` function instead. The
`update_focused_workspace` function should be used only to update a
workspace layout.
This commit ensures that when the user switches to the flooating layer
any new spawned window will be spawned floating as if the float override
was set.
This results in a workflow which makes it easier to spawn floating
windows on the fly.
This effectively reverts commit ff2aa5e51a.
This fixes the issue where borders moved to other monitors would
sometimes be removed by their initial monitor because this data wasn't
being updated.
This effectively reverts commit 5919f88b38.
Added a test for moving a workspace from one monitor to another. The
test will ensure that after calling the function, the current monitor
index is the one where the workspace was transfered to. Test also will
check the count to ensure the new workspace was added to the new monitor
and that the old monitor has one less.
Added a test for swapping monitor workspaces. The test will create two
monitors one with a workspace that has a container containing multiple
windows and another with one. The test calls the swap_monitor_workspaces
function and then checks to see if the two workspaces were successfully
swapped.
Added a test to test toggling the tiling state. After each switch the
test will test the current state to ensure that it is the expected
state.
It's very annoying and unclear when enabling the float override to open
the next window as floating to have that window appear immediately over
an existing tile.
This commit sets an explicit behaviour to center windows spawned while
the float override is active.
This commit addresses a border rendering issue when moving a window from
a higher-indexed monitor to a lower-indexed monitor.
Previously, we would do a single render pass across all monitors in
order of their indexes, destroying borders no longer needed, and
creating new borders for new windows.
This resulted in the window being moved to the lower-indexed monitor
still existing in the global border cache when that monitor's borders
were updated, but then being removed when the borders of the origin,
higher-indexed monitor were updated.
With the changes in this commit, if we encounter a situation like this,
an additional render pass will be executed to ensure that the window
will have a corresponding border created on the destination
lower-indexed monitor.
This commit ensures that a workspace float override will also be applied
when the user switches to the floating layer, and removed when the user
switches to the tiling layer. This results in a workflow which makes it
easier to spawn floating windows on the fly.
This commit ensures that if a user switches from a workspace with
managed windows to a workspace without any managed windows but only
floating windows, the focused window from the previous workspace will
lose focus as it should, and the first floating window on the new
workspace will gain focus as it should.
Added a test for removing a window from a container. The test checks to
ensure a new container is created and that the removed window from the
original container is added to the new container. Also ensures that the
old container has one less container after the function is called.
Added a test for removing a workspace. The test keeps track of the
number of workspaces and the current workspace index.
Added test for swapping containers from different monitors. The test
will create two monitors and containers with different amount of
windows. Test will verify that the swap is successful by checking that
the number of windows in the container matches the number of windows it
was created with in the previous monitor. The same will be done with the
other container.
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
Use the preferred id set by the user as the key when caching monitors.
This way if a user is having issues with the device_id on their system
they can use the serial_number_id on display_index_preferences.
If instead a user is having issues with the serial_number_id they can
make sure to use the device_id on display_index_preferences. Komorebi
will use the preferred one as a key when caching the monitors.
This PR also includes a change of the DISPLAY_INDEX_PREFERENCES from a
Mutex to RwLock.
I believe the RwLock is better since it allows multiple readers at the
same time, while the mutex blocks on all calls even if you just want to
read or compare some value.
For display index preferences (same thing applies to other existing
mutexes) most times we access it is a read-only access. We only ever
change it when applying a config or when a command is used to change it.
Every other use is a read-only use so it doesn't make sense to block on
those situations
This commit fixes an issue where the move/resize functions for floating
windows weren't properly taking into account the coordinates of
secondary monitors and were only working correctly on the main monitor
where top/left was 0/0.
Implemented drop to ensure that the socket is deleted whenever the
function goes out of scope. This will ensure that if the test fails, the
test socket file will still be removed.
Added a test for cycling to the next and previous container in a
workspace.
Added a test for transfering a window from Monitor 1 to Monitor 2
Added a test for transfering a container to another montior. Also
updated the transfer window test to transfer the window back to the
original container. Both tests will check both monitors to ensure the
expected number of containers are in both.
Previously if we had a stack on a monocle container and tried to cycle
stack or move the window within the stack or even using the focus stack
window from a bar it would focus the wrong window and temporarely show
that wrong window. This commit fixes this.
Created a test that creates the WM instance and ensures the instance is
running. The test creates a custom socket and then cleans up the socket
file after completion.
Created a test that creates a WM instance, monitor instance, and
workpace. The tests checks to ensure that the expected workspace is
focused properly.
Included recommended fixes to ensure that the focus_workspace function
is used correctly and that the test accurately checks the workspaces
length, current workspace index, and switching to an existing workspace.
This commit adds a variation of the cycle-workspace command which will
attempt to focus the next empty workspace in the given direction (with
the usual wraparound). If there are no empty workspaces available, this
command will do nothing.
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.