Use the same `add_container_with_direction` function on
`move_container_to_workspace` as it is being used on
`move_container_to_monitor` or `move_container_in_direction`.
This way we bring parity between all methods and make it easier to
change the way a container is added on a monitor workspace when taking
the move direction into consideration.
This commit fixes an issue where when trying to move floating windows or
windows on a floating workspace across boundaries to another monitor
using the `move_container_in_direction` it wouldn't move the floating
windows physically, although it moved them internally on komorebi,
resulting in weird and wrong behavior.
This commit creates a new method on `Monitor` to
`add_container_with_direction` which takes a move direction and then
uses the same logic that was previously on the
`move_container_in_direction` function.
It changes the `move_container_to_monitor` function to take an optional
move direction which if it is some will have this function call the new
method `add_container_with_direction` instead of just `add_container`.
Lastly the `move_container_in_direction` function now when it realizes
the move will be across monitors simply calls the
`move_container_to_monitor` with the direction that was initially given
to it.
These changes require that all callers of `move_container_to_monitor`
add an direction option, instead of passing `None` on all of them, a new
helper function was created, named `direction_from_monitor_idx` which
calculates the direction a move will have from the currently focused
monitor and the target monitor return `None` if they are the same or
returning `Some(direction)` if not. This way now all commands that call
a move across monitor will use the logic to check from the direction if
it should add the container on front or end.
This commit introduces a distinction between ignored applications
(previously identified with float_rules) and floating applications.
All instances of "float_" with the initial meaning of "ignored" have
been renamed with backwards compatibility aliases.
Floating applications will be managed under Workspace.floating_windows
if identified using a rule, and this allows them to now be moved across
workspaces.
A new border type has been added for floating applications, and the
colour can be configured via theme.floating_border.
This interactively rebased commit contains changes from the following
individual commits:
17ea1e6869
feat(wm): separate floating and ignored apps
8b344496e6
feat(wm): allow ws moves of floating apps
7d8e2ad814
refactor(wm): float_rules > ignore_rules w/ compat
d68346a640
fix(borders): no redraws on floating win title change
a93e937772
fix(borders): update on floating win drag
68e9365dda
fix(borders): send notif on ignored hwnd events
This commit builds on c3f135703e and
1080159e68 to add layout-specific edge
index awareness to all default layouts.
This is most useful for UltrawideVerticalStack and
RightMostVerticalStack, which have a lot of edge cases due to the
positioning of the 0th index changing with the number of containers on a
workspace.
This commit introduces a new configuration option,
cross_boundary_behaviour, which allows the user to decide if they want
Focus and Move operations to operate across Workspace or Monitor
boundaries.
The default behaviour in komorebi has always been Monitor. Setting this
to Workspace will make komorebi act a little like PaperWM, where
"komorebic focus left" and "komorebic focus right" will switch to the
next or previous workspace respectively if the currently focused window
as at either the left or right monitor boundary.
resolve#959
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.
This commit introduce state snapshot checks in the border manager, which
will ensure that we don't even attempt to acquire any mutex locks if the
state hasn't changed.
This commit adds the monitor_reconciliator module which uses a tightly
bounded channel (cap: 1) to handle monitor connection and disconnection
events, as well as resolution and work area change events.
Before, all this logic lived in a the WindowManager.reconcile_monitors
function, which ran on pretty much every process_event iteration, and
sometimes led to undesirable behaviour, but now the logic is split up to
only run when the appropriate notifications are dispatched from the
hidden window which listens for monitor and display-related events.
The monitor cache has been moved out of WindowManager and into the
monitor_reconciliator module, and in addition to the previous behaviour
of attempting to cache monitors which had been identified as
disconnected, now when the static configuration file is loaded, if the
user has set display_index_preferences, the device IDs will be used to
pre-populate the cache for the event where a known monitor is connected
later in a session.
The monitor cache itself now uses the unique device ID as a key rather
than the hmonitor which is known to be inconsistent.
This commit also delegates all display monitor-related Win32 calls to
the "win32-display-data" crate, which was extracted from the larger
"brightness" crate for its use in komorebi.
As a result of these changes, "device" and "device_id" on Monitor have
been changed from Option<String> to String types, as failures in
retrieving these values with directly attached monitors has not been
possible to reproduce. However, it remains to be seen if this will
adversely impact users who use display docks which may prevent display
monitor device IDs from being read and stored by the operating system.
WindowManagerEvent::DisplayChange has been removed in favour of
the monitor_reconciliator::Notification enum, as these events are no
longer being handled in process_events.
Attempts are now made to eagerly update hmonitors both within the
monitor_reconciliator loop on DisplayConnectionChange notifications and
when failing to find a matching hmonitor in functions like
monitor_idx_from_current_pos and monitor_idx_from_window.
This commit updates the initial design of single_window_work_area_offset
to window_based_work_area_offset where the user can set
window_based_work_area_offset_limit to determine the limit of windows on
the screen that this offset should apply to.
By default this is 1, and in the most extreme case of someone using a
super ultrawide monitor this might be 2.
This commit adds a new monitor configuration option, single_window_work_area_offset, which will
apply to a monitor when only a single window is open on a workspace. This is implemented as a Rect
to enable its use on both horizontally and vertically positioned monitors. This option will be
particularly useful for ultrawide monitor users, where a single window taking up the full width of
the work area can often hinder usability.
resolve#434
This commit introduces the stackbar feature through careful extracting
and refactoring of code from the Komorebi-UI hard-fork.
Unfortunately on the fork, this feature was not implemented using atomic
commits, which resulted in the implementation here being more of a
"reinterpretation" than a lift-and-shit of the referenced code.
Nevertheless, this commit represents a working version of the stackbar
feature.
resolve#681
This commit includes backwards-compatible renames of
active_window_border_offset and active_window_border_width to
border_offset and border_width respectively.
Since the invisible window border adjustments were removed in #678, the
invisible window borders set by the OS can now also be adjusted via
border_offset and border_width, which is the primary reason for the
rename.
invisible_borders has been marked as deprecated and the previously
deprecated alt_focus_hack option has been removed.
This makes the borders pixel-perfect, and border_overflow can be
disabled on all applications.
Unfortunately this also means we lose the corner rounding, so that may
need to be done differently or the offsets refined in some way to
address that.
This commit splits the komorebi crate into a mixed binary and library
crate.
All types and logic related to window management have been moved under
lib.rs, and are imported from there for use in main.rs, which is now
only responsible for starting and running the window manager process.
In preparation for exposing a new komorebi-client crate in the future,
serde::Deserialize has been derived on Notification and any struct that
may appear in a notification receievd by a process that has subscribed
to event updates.
re #659
This commit begins to build on some of the knowledge shared by EBNull in
allowing users to specify monitor index preferences using physical
device identifiers. This does not presently go all the way to EDIDs, but
the display model and what I believe is a port identifier on the display
adapter(s) can be used to uniquely identify a display in most use cases.
However, I believe I may have unfortunately run into a bug in either
windows-rs or Rust itself, as when the code calling EnumDisplayDevices
is called, it always fails when running a release build, and always
succeeds when running a debug build. This needs to be investigated
further.
re #612
- Avoids unnecessary string allocation when tracing paths
- Replaces `mut path & path.push()` with `path.join()`
- Avoids unncessary cloning of paths where applicable
- Use `dunce` crate to remove `UNC` prefix
- Improve performance of resolving `~` by avoiding unnecessary string allocations
- Resolve `~`, `$Env:USERPROFILE` and `$HOME` consistenly between different code paths
- Use `PathBuf` instead of `String` for paths in CLI args
I may have missed a couple of places but I think I covered 90% of path handling in the codebase
This commit replaces all usages of MONITORINFO with MONITORINFOEX in
order to retrieve a name for each connected display device.
This display device name makes for easier deduping during monitor
reconciliation, so that matching display monitor names can simply have
their hmonitor id updated instead of trying to figure out which id
corresponds to which monitor by looking at the windows currently visible
on each.
fix#267
This commit introduces the 'notification-schema' command to generate a
JSON schema of the Notification struct which gets sent when notifying
subscribers of updates.
This commit adds a new komorebic command to move the entire focused
workspace and all managed windows and containers to a target monitor
index. Windows that have been excluded from management using various
rules will not be moved as they are not tracked in the window manager
state.
resolve#88
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 expands the reconcile_monitors fn to also update resolution
and work area sizes if they are different from what is stored in the
window manager state.
Another WindowManagerEvent has been added as a polling mechanism for
monitor-related changes (scaling, dpi, resolution etc.), and this will
now also trigger the reconcile_monitors fn in the existing event
pre-processing block.
resolve#36
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
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 removes the unnecessary eyre dependency and instead uses the
relevant imports from color-eyre.
Additionally, after reading the eyre readme a little more closely, I
have switched out .compat() for the ok_or() combinator function as
suggested here: https://github.com/yaahc/eyre#compatibility-with-anyhow.
Windows that have been maximized do not retain their maximized state
across workspaces as workspaces are built on top of sending SW_HIDE and
SW_SHOW events which at various points of the event loop end up
overriding SW_SHOWMAXIMIZED and SW_SHOWMAXIMIZE.
To handle this use case, I have added a new 'komorebic toggle-maximize'
command which sends SW_MAXIMIZE for a window and keeps a record of the
window in the focused workspace in the same way that monocle windows are
tracked.
In this way, komorebi can know when switching to a workspace if it has
to restore a window to a native maximized state.
Some additional edge cases are caught in this commit in showing and
hiding workspaces, to also account for floating windows and monocle
containers.
resolve#12
This commit adds a new command, 'komorebic.exe new-workspace', which
will append a new, empty workspace, to the list of workspaces on the
currently focused monitor, and then switch focus to it.
Also took the opportunity to clean up some unnecessary unwraps in
komorebic/src/main.rs.
resolve#4
This commit introduces the getset crate to reduce a lot of the
boilerplate, especially in workspace.rs, around different variations of
getters. Hopefully this will make the codebase easier to navigate for
contributors in the future.
Also trying to avoid pinning to patch versions and minor versions
wherever possible.
Using macros to generate common type-specific Ring element accessors.
Should make codebase navigation a little easier my making logic-heavy
functions more visible in impl blocks.
Added a query command to komorebic to return the WindowManager struct
serialized to JSON to help with debugging and maybe help others to build
tools like stackline for yabai in the future.
Allow the number of workspaces for a given monitor to be pre-created, so
that configuration options can be sent (name, padding, layout) before
the workspace has ever been activated.
This commit fixes issues with toggling on and off Monocle and Floating
Window mode by ensuring that the relevant windows are always at the top
of the Z order, and in the latter case, ensuring that the top visible
window is used to search the local floating window state of the process.
After some experimenting I seem to have been able to adjust to remove
all of the invisible window borders by default, so if desired, a user
can now have no gaps at all.
Also upgraded to the latest version of the windows-rs crate since I saw
it was available. Thankfully no breaking changes.