This commit adds a new command which allows the focusing of workspaces
on monitors other than the currently focused monitor by specifying a
monitor index.
Sending this command to komorebi will make the target monitor index the
currently focused monitor.
resolve#85
This commit adds a command to let the user decide if they want windows
to be hidden with SW_HIDE or minimized with SW_MINIMIZE when workspaces
are changed or window container stacks are cycled.
After a modest amount of local testing, SW_MINIMIZE does not appear to
introduce any regressions, and given that alt-tabbing is a common
workflow on Windows, it makes sense to have minimizing be the default
setting to ease the onboarding experience for new users.
resolve#72
This commit ensures that when a window is dragged over another window container while
WindowContainerBehaviour::Append is set, the window will be removed from its current
container and appended to the target container instead of swapping the positions of the two
containers, as would be the case for WindowContainerBehaviour::Create.
re #72
This commit introduces a new command, toggle-new-window-behaviour, which
can be used to toggle how new windows on the screen will be handled.
The default setting is to add a new window in a dedicated container, but
when toggled, new windows will be stacked on top of the currently
focused window container.
This can be useful if you only want to use a certain number of columns,
and when you have enough windows on the screen for them, you can toggle
the new window behaviour to start appending to the existing column
stacks.
This commit also fixes a bug where stacked windows being closed did
cause the next window underneath in the stack to be shown.
re #72
This commit allows the resize-axis cmd on Axis::Horizontal to operate on
the Primary column of a CustomLayout.
Note that this will only operate on a CustomLayout that has met the
window count threshold to enable the tertiary column. If it has not, the
layout will render as DefaultLayout::Columns, which does not support the
resize-axis cmd.
This commit adds a command to set the resize delta used under the hood
by the resize-edge and resize-axis commands. The resize delta defaults
to 50 pixels as was hard-coded previously.
This commit adds a new command to resize by axis. Resizing is still
limited to the BSP layout. This command is intended to be bound to mouse
wheel up and down events, with different modified keys determining the
axis to operate on.
This commit bumps the version of the windows-rs and deprecates the
bindings crate in favour of using the pre-packaged APIs that are
available as of 0.22.
This commit adds two new commands to add and remove subscribers to
WindowManagerEvent and SocketMessage notifications after they have been
handled by komorebi.
Interprocess communication is achieved using Named Pipes; the
subscribing process must first create the Named Pipe, and then run the
'add-subscriber' command, specifying the pipe name as the argument
(without the pipe filesystem path prepended).
Whenever a pipe is closing or has been closed, komorebi will flag this
as a stale subscription and remove it automatically.
resolve#54
This commit adds support for loading custom layouts from yaml files, and
also moves the custom layout loading and validating logic into the
komorebi-core crate.
re #50
This commit adds a ColumnWidth for Column::Primary which can optionally
be given as a percentage of the total work area of a monitor. The
remaining columns will have their widths calculated by dividing the
remaining work area space evenly.
This commit also fixes a bug with the Promote command, which was not
calculating the primary container index of custom layouts properly, and
was also not using this value to update the focused container index at
the end of the promotion handler.
re #50
This commit introduces a number of refactors to layouts in general in
order to enable navigation across custom layouts and integrate both
default and custom layouts cleanly into komorebi and komorebic.
Layout has been renamed to DefaultLayout, and Layout is now an enum with
the variants Default and Custom, both of which implement the new traits
Arrangement (for layout calculation) and Direction (for operation
destination calculation).
CustomLayout has been simplified to wrap Vec<Column> and no longer
requires the primary column index to be explicitly defined as this can
be looked up at runtime for any valid CustomLayout.
Given the focus on ultrawide layouts for this feature, I have disabled
(and have not yet written the logic for) vertical column splits in
custom layouts.
Since CustomLayouts will be loaded from a file path, a bunch of
clap-related code generation stuff has been removed from the related
enums and structs.
Layout flipping has not yet been worked on for custom layouts.
When switching between Default and Custom layout variants, the primary
column index and the 0 element are swapped to ensure that the same
window container is always at the focal point of every layout.
Resizing/dragging to resize is in a bit of weird spot at the moment
because the logic is only implemented for DefaultLayout::BSP right now
and nothing else. I think eventually this will need to be extracted to a
Resize trait and implemented on everything.
This commit introduces a new Trait, Dimensions, which requires the
implementation of a fn calculate() -> Vec<Rect>, a fn that was
previously limited to the Layout struct.
Dimensions is now implemented both for Layout and the new CustomLayout
struct, the latter being a general adaptive fn which employs a number of
fallbacks to sane defaults when the the layout does not have the minimum
number of required windows on the screen.
The CustomLayout is mainly intended for use on ultra and superultrawide
monitors, and as such uses columns as a basic building block. There are
three Column variants: Primary, Secondary and Tertiary.
The Primary column will typically be somewhere in the middle of the
layout, and will be where a window is placed when promoted using the
komorebic command.
The Secondary column is optional, and can be used one or more times in a
layout, either splitting to accomodate a certain number of windows
horizontally or vertically, or not splitting at all.
The Tertiary window is the final window, which will typically be on the
right of a layout, which must be split either horizontally or vertically
to accomodate as many windows as necessary.
The Tertiary column will only be rendered when the threshold of windows
required to enable it has been met. Until then, the rightmost Primary or
Secondary column will expand to take its place.
If there are less windows than (or a number equal to the) columns
defined in the layout, the windows will be arranged in a basic columnar
layout until the number of windows is greater than the number of columns
defined in the layout.
At this point, although the calculation logic has been completed, work
must be done on the navigation logic before a SocketMessage variant can
be added for loading custom layouts from files.
This commit applies 'cargo fix --edition' to safely migrate the project
to Edition 2021 of Rust.
A rustfmt.toml has also be added to enforce the flattening of use
statements when running 'cargo fmt'.
This commit extracts independent functions for calculating row and
column layouts in an arbitrary work area. This should be useful in the
future for some ideas I have around custom serializable layouts.
This commit ports the CenterMain, MainAndVertStack, and
MainAndHorizontalStack layouts from LeftWM to komorebi as
UltrawideVerticalStack, VerticalStack and HorizontalStack.
These layouts are fixed-size layouts, meaning that individual containers
cannot be resized. The VerticalStack and UltrawideVerticalStack layouts
support horizontal flipping, whereas the HorizontalStack layout supports
vertical flipping.
resolve#48
This commit adds a new komorebic command to specify offsets for work
areas to be applied across all monitors. The areas covered by these
offsets will be excluded from the tiling area, and can be used for
custom task bars, Rainmeter desktop widgets etc.
When setting an offset at the top, the same offset will need to be
applied to the bottom to ensure that the tiling area is not pushed off
of the screen, but this is not necessary when applying an offset to the
bottom as the top of the work area will never go lower than 0.
resolve#46
This commit adds focusing and moving window containers using cycle
directions when the layout has not been flipped on any axis.
This naive implementation simply increments or decrements the index
number in the desired direction and does not accomodate for axis
flipping.
When the current index number is either at the beginning or the end of
the collection, further operations will loop around.
Ideally I would like an implementation which works coherently on any
LayoutFlip state, but this can be implemented at a later date if
specifically requested in the future.
re #47
This commit expands on the autosave/load functionality to allow saving
and loading layouts from any file.
Handling relative paths and paths with ~ on Windows is a little tricky
so I added a helper fn to komorebic to deal with this, ensuring all the
processing happens in komorebic before the messages get sent to komorebi
for processing.
There will still some lingering uses of ContextCompat around the
codebase which I also took the opportunity to clean up and replace with
ok_or_else + anyhow!().
windows-rs is also updated to 0.20.1 in the lockfile.
resolve#41
This commit adds two new komorebic commands to quicksave and quickload
BSP layouts with custom resize dimensions. The quicksave file is stored
at ${Env:TEMP}/komorebi.quicksave.json, and is a Vec<Option<Rect>>
serialized to JSON.
If a user tries to quickload without a quicksave file being present, an
error will be logged.
At this point there is only one quicksave file which will always be
overwritten whenever the quicksave command is called. Both commands will
only operate on the focused workspace of the focused monitor.
This means that you can quicksave a layout on one workspace, and then
quickload it onto multiple other workspaces (individually) on the same
or other monitors.
If the number of elements in the deserialized Vec is greater than the
number of containers on a workspace, the Vec will be truncated when
Workspace.update is run, and similarly if the number of elements is less
than the number of containers on a workspace, the Vec will be extended
by the difference using None values.
resolve#39
Following the changes I witnessed in the invisible window border size
following an OS update, this commit makes the invisible border offset
configurable via a new komorebic command 'invisible-borders'.
When sending a new set of invisible border offset dimensions via
komorebic, a full retile across all monitors will take place after the
new values have been set.
The default values have been set to what is currently correct for my
machine, and will likely be updated again in the same way in the future
if further changes occur in subsequent OS updates.
This commit also updates some dependencies to their latest releases, and
removes from the CI workflow a line that attempts to delete the
rustup-init.exe binary after installation which has been causing builds
to fail.
resolve#35
Applications like Spotify and Discord draw over the default invisible
borders of Windows 10, which means that when komorebi is setting their
positions, the offset is always off by the amount of pixels of the
invisible borders on each side.
This commit makes it possible to identify applications that have
overflowing borders so that they can be handled appropriately by the
window manager.
This commit also takes the opportunity to consolidate the tray and multi
window identifiers into a single vector instead of spreading them across
multiple vectors by identifier type.
resolve#32
When monitors turn on and off, they do not retain their hmonitor id,
therefore this commit introduces an initial attempt to reconcile invalid
and valid hmonitors after monitor changes based on the windows that are
assigned to them.
If a monitor has at least one window, and has been assigned a new
hmonitor id, komorebi will look up the current hmonitor of that window's
hwnd and update Monitor.id in-place.
When reconciling monitors, any monitor marked as invalid will be purged
from the window manager state.
This commit also applies some of the new clippy lints that come along
with the latest nightly release of Rust.
resolve#31
This commit adds an optional flag to allow users to select the focus
follows mouse implementation that they wish to use (komorebi or
windows). The flag defaults to komorebi.
The ahk-derive crate has been updated to enable the generation of
wrappers fns that require flags.
I pushed the ffm check up to listen_for_movements() so that we don't
even try to listen to the next event from the message loop unless
komorebi-flavoured ffm is enabled.
re #7
This commit adds a new query command to komorebic, which allows for the
current focused monitor, workspace, container and window indices to be
queried directly without having to use jq run lookups on the entire
output of the state command.
resolve#24
This commit adds two commands to allow the user to send the currently
focused container to a different workspace or monitor as a background
operation, without following the moved container to the destination
workspace or monitor.
resolve#20
Decided there should be a quick way to toggle the native ffm
functionality, it gets especially annoying when trying to click drop
downs from the system tray etc.
re #7
Woke up today and thought this would be a cool way to learn more about
deriving functionality with proc macros.
Hopefully having this wrapper/helper library will make first time
configuration for new users easier.
Silly boolean error meant that if a link was clicked in one
monitor/workspace, the browser, if not on the same workspace, would be
brought into the workspace the link was clicked in.
This was because I was checking if the focused monitor != the known
monitor && the focused workspace != the known workspace, when in fact,
we don't need both of those conditions to be true in order to switch to
where the browser is, we only need one of them to be true.
After changing the && (and) to a || (or), the behaviour is now as
expected, and clicking a link will switch to the workspace where the
browser is open.
Realised that I hadn't turned on super pedantic mode for clippy in the
komorebi-core and komorebic crates. This commit ensures the same clippy
config across all crates and applies the lint suggestions that arose as
a result of turning on the same config everywhere.
Just a little bit of clean up to make sure that the float rule data
structures match the same emerging pattern as the data structures for
other kinds of rules.
Also some refactoring of Window.should_manage to ensure stricter scoping
where locks are gained on global static variables.
Following on from 8ffe6f78b7, this commit
introduces a command to add rules to forcibly manage windows that don't
get picked up by the rough heuristics that are able to target most
windows for management in Window.should_manage.
Since there is again no overlap (or at least, no undesired overlap)
between executable names and classes, I'll keep both class and exe names
in a single lookup vec.
re #16
Added commands to forcibly manage and unmanage windows if they don't get
picked up for tiling automatically. This commit adds support for running
those operations on the currently focused window, but if there is a need
to specify a hwnd to operate on, that could be added pretty easily too
in the future, though I'd like to keep the complexity of looking up and
passing hwnds to a command out of the CLI if possible.
This commit also fixes an issue with restoring floating windows. I'm not
sure what happened, but at some point, for me at least,
WindowsApi::top_visible_window started returning explorer.exe all the
time, so I've switched this out for WindowsApi::foreground_window.
I have a feeling I was using TopWindow before, thinking it was
GetForegroundWindow, which it isn't, and it wasn't reliable, so I
created the top_visible_window abstraction on top of it, which also
turned out to be unreliable. Anyway, it's working now.
I think the next step will be to create a manage-rule command to
compliment the float-rule command which users can use to handle edge
cases with their apps in their configuration.
re #16