Skip to content

Commit

Permalink
feat(wm): move all windows on ws layer toggle
Browse files Browse the repository at this point in the history
This commit makes it so when you toggle between workspace layers it
moves all windows of that layer to the top of the z-order.

So if you move to `Floating` layer, then all floating windows are moved
to the top, and if you go back to the `Tiling` layer, all tiled
containers are moved to the top.
  • Loading branch information
alex-ds13 authored and LGUG2Z committed Feb 27, 2025
1 parent dadc407 commit 4031fbf
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
18 changes: 16 additions & 2 deletions komorebi/src/border_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::core::BorderImplementation;
use crate::core::BorderStyle;
use crate::core::WindowKind;
use crate::ring::Ring;
use crate::workspace::WorkspaceLayer;
use crate::workspace_reconciliator::ALT_TAB_HWND;
use crate::Colour;
use crate::Rgb;
Expand Down Expand Up @@ -166,6 +167,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
let mut previous_pending_move_op = None;
let mut previous_is_paused = false;
let mut previous_notification: Option<Notification> = None;
let mut previous_layer = WorkspaceLayer::default();

'receiver: for notification in receiver {
// Check the wm state every time we receive a notification
Expand All @@ -182,6 +184,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
.iter()
.map(|w| w.hwnd)
.collect::<Vec<_>>();
let workspace_layer = *state.monitors.elements()[focused_monitor_idx].workspaces()
[focused_workspace_idx]
.layer();
let foreground_window = WindowsApi::foreground_window().unwrap_or_default();

drop(state);
Expand Down Expand Up @@ -507,9 +512,13 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
}
};

let layer_changed = previous_layer != workspace_layer;

let should_invalidate = match last_focus_state {
None => true,
Some(last_focus_state) => last_focus_state != new_focus_state,
Some(last_focus_state) => {
(last_focus_state != new_focus_state) || layer_changed
}
};

if new_border || should_invalidate {
Expand Down Expand Up @@ -561,9 +570,13 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result

let rect = WindowsApi::window_rect(window.hwnd)?;

let layer_changed = previous_layer != workspace_layer;

let should_invalidate = match last_focus_state {
None => true,
Some(last_focus_state) => last_focus_state != new_focus_state,
Some(last_focus_state) => {
last_focus_state != new_focus_state || layer_changed
}
};

if new_border {
Expand All @@ -587,6 +600,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
previous_pending_move_op = pending_move_op;
previous_is_paused = is_paused;
previous_notification = Some(notification);
previous_layer = workspace_layer;
}

Ok(())
Expand Down
29 changes: 25 additions & 4 deletions komorebi/src/process_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,24 +1049,45 @@ impl WindowManager {
let mouse_follows_focus = self.mouse_follows_focus;
let workspace = self.focused_workspace_mut()?;

let mut to_focus = None;
match workspace.layer() {
WorkspaceLayer::Tiling => {
workspace.set_layer(WorkspaceLayer::Floating);

if let Some(first) = workspace.floating_windows().first() {
first.focus(mouse_follows_focus)?;
for (i, window) in workspace.floating_windows().iter().enumerate() {
if i == 0 {
to_focus = Some(*window);
}
window.raise()?;
}

for container in workspace.containers() {
if let Some(window) = container.focused_window() {
window.lower()?;
}
}
}
WorkspaceLayer::Floating => {
workspace.set_layer(WorkspaceLayer::Tiling);

if let Some(container) = workspace.focused_container() {
let focused_container_idx = workspace.focused_container_idx();
for (i, container) in workspace.containers_mut().iter_mut().enumerate() {
if let Some(window) = container.focused_window() {
window.focus(mouse_follows_focus)?;
if i == focused_container_idx {
to_focus = Some(*window);
}
window.raise()?;
}
}

for window in workspace.floating_windows() {
window.lower()?;
}
}
};
if let Some(window) = to_focus {
window.focus(mouse_follows_focus)?;
}
}
SocketMessage::Stop => {
self.stop(false)?;
Expand Down
24 changes: 24 additions & 0 deletions komorebi/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,30 @@ impl Window {
self.update_style(&style)
}

/// Raise the window to the top of the Z order, but do not activate or focus
/// it. Use raise_and_focus_window to activate and focus a window.
/// It also checks if there is a border attached to this window and if it is
/// it raises it as well.
pub fn raise(self) -> Result<()> {
WindowsApi::raise_window(self.hwnd)?;
if let Some(border) = crate::border_manager::window_border(self.hwnd) {
WindowsApi::raise_window(border.hwnd)?;
}
Ok(())
}

/// Lower the window to the bottom of the Z order, but do not activate or focus
/// it.
/// It also checks if there is a border attached to this window and if it is
/// it lowers it as well.
pub fn lower(self) -> Result<()> {
WindowsApi::lower_window(self.hwnd)?;
if let Some(border) = crate::border_manager::window_border(self.hwnd) {
WindowsApi::lower_window(border.hwnd)?;
}
Ok(())
}

#[tracing::instrument(fields(exe, title), skip(debug))]
pub fn should_manage(
self,
Expand Down
27 changes: 24 additions & 3 deletions komorebi/src/windows_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
use windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
use windows::Win32::UI::WindowsAndMessaging::HDEVNOTIFY;
use windows::Win32::UI::WindowsAndMessaging::HWND_BOTTOM;
use windows::Win32::UI::WindowsAndMessaging::HWND_TOP;
use windows::Win32::UI::WindowsAndMessaging::LWA_ALPHA;
use windows::Win32::UI::WindowsAndMessaging::REGISTER_NOTIFICATION_FLAGS;
Expand Down Expand Up @@ -477,10 +478,13 @@ impl WindowsApi {
unsafe { BringWindowToTop(HWND(as_ptr!(hwnd))) }.process()
}

// Raise the window to the top of the Z order, but do not activate or focus
// it. Use raise_and_focus_window to activate and focus a window.
/// Raise the window to the top of the Z order, but do not activate or focus
/// it. Use raise_and_focus_window to activate and focus a window.
pub fn raise_window(hwnd: isize) -> Result<()> {
let flags = SetWindowPosition::NO_MOVE | SetWindowPosition::NO_ACTIVATE;
let flags = SetWindowPosition::NO_MOVE
| SetWindowPosition::NO_SIZE
| SetWindowPosition::NO_ACTIVATE
| SetWindowPosition::SHOW_WINDOW;

let position = HWND_TOP;
Self::set_window_pos(
Expand All @@ -491,6 +495,23 @@ impl WindowsApi {
)
}

/// Lower the window to the bottom of the Z order, but do not activate or focus
/// it.
pub fn lower_window(hwnd: isize) -> Result<()> {
let flags = SetWindowPosition::NO_MOVE
| SetWindowPosition::NO_SIZE
| SetWindowPosition::NO_ACTIVATE
| SetWindowPosition::SHOW_WINDOW;

let position = HWND_BOTTOM;
Self::set_window_pos(
HWND(as_ptr!(hwnd)),
&Rect::default(),
position,
flags.bits(),
)
}

pub fn set_border_pos(hwnd: isize, layout: &Rect, position: isize) -> Result<()> {
let flags = {
SetWindowPosition::NO_SEND_CHANGING
Expand Down

0 comments on commit 4031fbf

Please sign in to comment.