From 612940c4ce1c30c576a44cdabd5a0d592e2d7de6 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 23 Jul 2024 23:32:18 +0200 Subject: [PATCH 01/35] feat: detect if window moved or resized --- .../events/handle_window_moved_or_resized.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized.rs b/packages/wm/src/common/events/handle_window_moved_or_resized.rs index e155205cc..506f34ffd 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized.rs @@ -23,7 +23,6 @@ pub fn handle_window_moved_or_resized( if let Some(WindowContainer::TilingWindow(window)) = found_window { // TODO: Log window details. - info!("Tiling window moved/resized"); let parent = window.parent().context("No parent.")?; @@ -34,11 +33,21 @@ pub fn handle_window_moved_or_resized( return Ok(()); } - let new_position = window.native().refresh_frame_position()?; - let old_position = window.to_rect()?; + let new_rect = window.native().refresh_frame_position()?; + let old_rect = window.to_rect()?; - let width_delta = new_position.width() - old_position.width(); - let height_delta = new_position.height() - old_position.height(); + let width_delta = new_rect.width() - old_rect.width(); + let height_delta = new_rect.height() - old_rect.height(); + + let window_moved = match (width_delta, height_delta) { + (0, 0) => true, + _ => false, + }; + + match window_moved { + true => info!("Tiling window moved"), + false => info!("Tiling window resized"), + } resize_window( window.clone().into(), From 561df525294d12fc0d5edcab026613b623b16600 Mon Sep 17 00:00:00 2001 From: Luca Date: Sat, 27 Jul 2024 01:28:28 +0200 Subject: [PATCH 02/35] feat: utility functions & get window under mouse position --- .../events/handle_window_moved_or_resized.rs | 119 +++++++++++++++--- packages/wm/src/common/platform/platform.rs | 23 +++- packages/wm/src/common/rect.rs | 6 + packages/wm/src/wm.rs | 2 +- 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized.rs b/packages/wm/src/common/events/handle_window_moved_or_resized.rs index 506f34ffd..ee6809c87 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized.rs @@ -1,13 +1,23 @@ +use std::collections::VecDeque; + use anyhow::Context; -use tracing::info; +use tracing::{debug, info}; +use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; use crate::{ - common::{platform::NativeWindow, LengthValue}, + common::{ + platform::{MouseMoveEvent, NativeWindow, Platform}, + LengthValue, Point, Rect, + }, containers::{ traits::{CommonGetters, PositionGetters}, - WindowContainer, + Container, WindowContainer, + }, + user_config::UserConfig, + windows::{ + commands::resize_window, traits::WindowGetters, NonTilingWindow, + TilingWindow, }, - windows::{commands::resize_window, traits::WindowGetters}, wm_state::WmState, }; @@ -18,6 +28,7 @@ use crate::{ pub fn handle_window_moved_or_resized( native_window: NativeWindow, state: &mut WmState, + config: &UserConfig, ) -> anyhow::Result<()> { let found_window = state.window_from_native(&native_window); @@ -39,23 +50,101 @@ pub fn handle_window_moved_or_resized( let width_delta = new_rect.width() - old_rect.width(); let height_delta = new_rect.height() - old_rect.height(); - let window_moved = match (width_delta, height_delta) { + let has_window_moved = match (width_delta, height_delta) { (0, 0) => true, _ => false, }; - match window_moved { - true => info!("Tiling window moved"), - false => info!("Tiling window resized"), - } + return match has_window_moved { + true => window_moved(window, state, config), + false => window_resized(window, state, width_delta, height_delta), + }; + } + + Ok(()) +} + +/// Handles window move events +fn window_moved( + moved_window: TilingWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + info!("Tiling window moved"); - resize_window( - window.clone().into(), - Some(LengthValue::from_px(width_delta)), - Some(LengthValue::from_px(height_delta)), - state, - )?; + let workspace = + moved_window.workspace().context("Couldn't find a workspace")?; + + let mouse_position = Platform::mouse_position()?; + + let children_at_mouse_position: Vec<_> = workspace + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => { + Some(tiling) + } + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + info!("{:?}", frame); + info!("{:?}", mouse_position); + frame.unwrap().contains_point(&mouse_position) + }) + .filter(|window| window.id() != moved_window.id()) + .collect(); + + if children_at_mouse_position.is_empty() { + return Ok(()) } + let window_under_cursor = children_at_mouse_position.into_iter().next().unwrap(); + + // let should_split = match window_under_cursor { + // Some(WindowContainer::TilingWindow(window)) => { + // match window.parent().context("Couldn't find parent")? { + // crate::containers::Container::Split(_) => ShouldSplit::No, + // _ => { + // todo!() + // } + // } + // } + // Some(WindowContainer::NonTilingWindow(window)) => { + // let rect = window + // .native() + // .frame_position() + // .context("couldn't get the window frame")?; + // + // if rect.width() > rect.height() { + // ShouldSplit::Vertically + // } else { + // ShouldSplit::Horizontally + // } + // } + // None => return Ok(()), + // }; + Ok(()) } + +enum ShouldSplit { + Vertically, + Horizontally, + No, +} + +/// Handles window resize events +fn window_resized( + window: TilingWindow, + state: &mut WmState, + width_delta: i32, + height_delta: i32, +) -> anyhow::Result<()> { + info!("Tiling window resized"); + resize_window( + window.clone().into(), + Some(LengthValue::from_px(width_delta)), + Some(LengthValue::from_px(height_delta)), + state, + ) +} diff --git a/packages/wm/src/common/platform/platform.rs b/packages/wm/src/common/platform/platform.rs index 3a267681c..d75392ec6 100644 --- a/packages/wm/src/common/platform/platform.rs +++ b/packages/wm/src/common/platform/platform.rs @@ -5,6 +5,7 @@ use std::{ }; use anyhow::{bail, Context}; +use tracing::{field::debug, info}; use windows::{ core::{w, PCWSTR}, Win32::{ @@ -18,9 +19,9 @@ use windows::{ SHELLEXECUTEINFOW, }, WindowsAndMessaging::{ - CreateWindowExW, DispatchMessageW, GetAncestor, GetDesktopWindow, - GetForegroundWindow, GetMessageW, MessageBoxW, PeekMessageW, - PostThreadMessageW, RegisterClassW, SetCursorPos, + CreateWindowExW, DispatchMessageW, GetAncestor, GetCursorPos, + GetDesktopWindow, GetForegroundWindow, GetMessageW, MessageBoxW, + PeekMessageW, PostThreadMessageW, RegisterClassW, SetCursorPos, SystemParametersInfoW, TranslateMessage, WindowFromPoint, ANIMATIONINFO, CS_HREDRAW, CS_VREDRAW, CW_USEDEFAULT, GA_ROOT, MB_ICONERROR, MB_OK, MSG, PM_REMOVE, SPI_GETANIMATION, @@ -135,7 +136,7 @@ impl Platform { Ok(()) } - // Find the window at the specified point in screen space. + /// Find the window at the specified point in screen space. pub fn window_from_point(point: &Point) -> anyhow::Result { let point = POINT { x: point.x, @@ -143,9 +144,23 @@ impl Platform { }; let handle = unsafe { WindowFromPoint(point) }; + dbg!(handle); Ok(NativeWindow::new(handle.0)) } + /// gets the mouse position in screen space. + pub fn mouse_position() -> anyhow::Result { + let mut point = POINT { x: 0, y: 0 }; + unsafe { + GetCursorPos(&mut point)?; + }; + + Ok(Point { + x: point.x, + y: point.y, + }) + } + /// Creates a hidden message window. /// /// Returns a handle to the created window. diff --git a/packages/wm/src/common/rect.rs b/packages/wm/src/common/rect.rs index 8b1da6f9a..e8c46f178 100644 --- a/packages/wm/src/common/rect.rs +++ b/packages/wm/src/common/rect.rs @@ -148,4 +148,10 @@ impl Rect { !(self.y() + self.height() <= other.y() || other.y() + other.height() <= self.y()) } + + pub fn contains_point(&self, point: &Point) -> bool { + let is_in_x = point.x >= self.left && point.x <= self.right; + let is_in_y = point.y >= self.top && point.y <= self.bottom; + return is_in_x && is_in_y; + } } diff --git a/packages/wm/src/wm.rs b/packages/wm/src/wm.rs index 030750d6f..173fe20f7 100644 --- a/packages/wm/src/wm.rs +++ b/packages/wm/src/wm.rs @@ -82,7 +82,7 @@ impl WindowManager { handle_window_minimize_ended(window, state, config) } PlatformEvent::WindowMovedOrResized(window) => { - handle_window_moved_or_resized(window, state) + handle_window_moved_or_resized(window, state, config) } PlatformEvent::WindowShown(window) => { handle_window_shown(window, state, config) From 28eb5d1d55abc09effcbbaaab8a17b1d8ec8963d Mon Sep 17 00:00:00 2001 From: Luca Date: Sat, 27 Jul 2024 01:57:42 +0200 Subject: [PATCH 03/35] feat: log --- .../events/handle_window_moved_or_resized.rs | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized.rs b/packages/wm/src/common/events/handle_window_moved_or_resized.rs index ee6809c87..961e6c7b3 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized.rs @@ -10,6 +10,7 @@ use crate::{ LengthValue, Point, Rect, }, containers::{ + commands::move_container_within_tree, traits::{CommonGetters, PositionGetters}, Container, WindowContainer, }, @@ -72,57 +73,52 @@ fn window_moved( ) -> anyhow::Result<()> { info!("Tiling window moved"); - let workspace = - moved_window.workspace().context("Couldn't find a workspace")?; + let workspace = moved_window + .workspace() + .context("Couldn't find a workspace")?; let mouse_position = Platform::mouse_position()?; let children_at_mouse_position: Vec<_> = workspace .descendants() .filter_map(|container| match container { - Container::TilingWindow(tiling) => { - Some(tiling) - } + Container::TilingWindow(tiling) => Some(tiling), _ => None, }) .filter(|c| { - let frame = c.to_rect(); - info!("{:?}", frame); - info!("{:?}", mouse_position); - frame.unwrap().contains_point(&mouse_position) + let frame = c.to_rect(); + info!("{:?}", frame); + info!("{:?}", mouse_position); + frame.unwrap().contains_point(&mouse_position) }) - .filter(|window| window.id() != moved_window.id()) + .filter(|window| window.id() != moved_window.id()) .collect(); if children_at_mouse_position.is_empty() { - return Ok(()) + return Ok(()); } - let window_under_cursor = children_at_mouse_position.into_iter().next().unwrap(); - - // let should_split = match window_under_cursor { - // Some(WindowContainer::TilingWindow(window)) => { - // match window.parent().context("Couldn't find parent")? { - // crate::containers::Container::Split(_) => ShouldSplit::No, - // _ => { - // todo!() - // } - // } - // } - // Some(WindowContainer::NonTilingWindow(window)) => { - // let rect = window - // .native() - // .frame_position() - // .context("couldn't get the window frame")?; - // - // if rect.width() > rect.height() { - // ShouldSplit::Vertically - // } else { - // ShouldSplit::Horizontally - // } - // } - // None => return Ok(()), - // }; + let window_under_cursor = + children_at_mouse_position.into_iter().next().unwrap(); + + info!( + "Swapping {} with {}", + moved_window + .native() + .process_name() + .unwrap_or("".to_string()), + window_under_cursor + .native() + .process_name() + .unwrap_or("".to_string()) + ); + + // move_container_within_tree( + // Container::TilingWindow(moved_window), + // Container::TilingWindow(window_under_cursor), + // 0, + // state, + // ); Ok(()) } From ad9c39641c5785913501248d90d1c65c845f8d13 Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 28 Jul 2024 20:35:55 +0200 Subject: [PATCH 04/35] feature: moving window with mouse WIP --- .../events/handle_window_location_changed.rs | 2 +- .../src/common/events/handle_window_moved.rs | 310 ++++++++++++++++++ .../events/handle_window_moved_or_resized.rs | 71 +--- packages/wm/src/common/events/mod.rs | 1 + packages/wm/src/common/platform/platform.rs | 1 - .../commands/move_container_within_tree.rs | 28 +- .../src/monitors/commands/remove_monitor.rs | 2 +- .../commands/move_window_in_direction.rs | 10 +- .../commands/move_window_to_workspace.rs | 4 +- .../windows/commands/update_window_state.rs | 4 +- .../commands/move_workspace_in_direction.rs | 2 +- 11 files changed, 347 insertions(+), 88 deletions(-) create mode 100644 packages/wm/src/common/events/handle_window_moved.rs diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 7941a9cbc..fcf341486 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -120,7 +120,7 @@ pub fn handle_window_location_changed( move_container_within_tree( window.into(), updated_workspace.clone().into(), - updated_workspace.child_count(), + Some(updated_workspace.child_count()), state, )?; } diff --git a/packages/wm/src/common/events/handle_window_moved.rs b/packages/wm/src/common/events/handle_window_moved.rs new file mode 100644 index 000000000..c9caf4395 --- /dev/null +++ b/packages/wm/src/common/events/handle_window_moved.rs @@ -0,0 +1,310 @@ +use std::{collections::VecDeque, io::Split}; + +use anyhow::Context; +use tracing::{debug, info}; +use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; + +use crate::{ + common::{ + commands::platform_sync, + platform::{MouseMoveEvent, NativeWindow, Platform}, + LengthValue, Point, Rect, TilingDirection, + }, + containers::{ + commands::{ + attach_container, detach_container, move_container_within_tree, + }, + traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, + Container, SplitContainer, WindowContainer, + }, + user_config::UserConfig, + windows::{ + commands::resize_window, traits::WindowGetters, NonTilingWindow, + TilingWindow, + }, + wm_event::WmEvent, + wm_state::WmState, +}; + +/// Handles window move events +pub fn window_moved( + moved_window: TilingWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + info!("Tiling window moved"); + + let workspace = moved_window + .workspace() + .context("Couldn't find a workspace")?; + + let mouse_position = Platform::mouse_position()?; + + let children_at_mouse_position: Vec<_> = workspace + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + info!("{:?}", frame); + info!("{:?}", mouse_position); + frame.unwrap().contains_point(&mouse_position) + }) + .filter(|window| window.id() != moved_window.id()) + .collect(); + + if children_at_mouse_position.is_empty() { + return Ok(()); + } + + let window_under_cursor = + children_at_mouse_position.into_iter().next().unwrap(); + + info!( + "Swapping {} with {}", + moved_window + .native() + .process_name() + .unwrap_or("".to_string()), + window_under_cursor + .native() + .process_name() + .unwrap_or("".to_string()) + ); + + let tiling_direction = get_split_direction(&window_under_cursor)?; + let new_window_position = get_new_window_position( + &mouse_position, + &window_under_cursor, + &tiling_direction, + )?; + + info!("{:?} {:?}", tiling_direction, new_window_position); + + let parent = window_under_cursor.parent().unwrap(); + + match &parent { + // If the parent is a workspace we only need to add the window to it or + // to create a VerticalSplitDirection + Container::Workspace(_) => { + let current_tiling_direction = TilingDirection::Horizontal; + move_window_to_target( + state, + config, + moved_window, + window_under_cursor, + &parent, + current_tiling_direction, + tiling_direction, + new_window_position, + )?; + } + // If the parent is a split we need to check the current split + // direction add the window to it or create a VerticalSplitDirection + Container::Split(split) => { + let current_tiling_direction = split.tiling_direction(); + move_window_to_target( + state, + config, + moved_window, + window_under_cursor, + &parent, + current_tiling_direction, + tiling_direction, + new_window_position, + )?; + } + _ => {} + } + + state.pending_sync.containers_to_redraw.push(parent); + + // info!("{:#?}", workspace); + + Ok(()) +} + +fn move_window_to_target( + state: &mut WmState, + config: &UserConfig, + moved_window: TilingWindow, + target_window: TilingWindow, + target_window_parent: &Container, + current_tiling_direction: TilingDirection, + new_tiling_direction: TilingDirection, + new_window_position: DropPosition, +) -> anyhow::Result<()> { + + let target_window_index = target_window_parent + .children() + .iter() + .position(|c| { + c.as_tiling_window().unwrap().id() == target_window.id() + }) + .context("Window index not found")?; + + if new_tiling_direction == TilingDirection::Horizontal { + if current_tiling_direction == TilingDirection::Horizontal { + let target_index = match new_window_position { + DropPosition::Start => Some(target_window_index), + DropPosition::End => None, + }; + + move_container_within_tree( + Container::TilingWindow(moved_window.clone()), + target_window_parent.clone(), + target_index, + state, + )?; + } else { + if current_tiling_direction == TilingDirection::Vertical { + let target_index = match new_window_position { + DropPosition::Start => Some(target_window_index), + DropPosition::End => None, + }; + + move_container_within_tree( + Container::TilingWindow(moved_window.clone()), + target_window_parent.clone(), + target_index, + state, + )?; + } else { + create_split_horizontal_direction( + state, + config, + moved_window, + target_window, + new_window_position, + &target_window_parent, + )?; + } + } + } else { + create_split_vertical_direction( + state, + config, + moved_window, + target_window, + new_window_position, + &target_window_parent, + )?; + } + Ok(()) +} + +fn create_split_vertical_direction( + state: &mut WmState, + config: &UserConfig, + moved_window: TilingWindow, + target_window: TilingWindow, + dropped_position: DropPosition, + parent: &Container, +) -> anyhow::Result<()> { + let target_index = match dropped_position { + DropPosition::Start => Some(0), + DropPosition::End => None, + }; + + let split_container = Container::Split(SplitContainer::new( + TilingDirection::Vertical, + config.value.gaps.inner_gap.clone(), + )); + attach_container(&split_container, &parent, None)?; + + move_container_within_tree( + Container::TilingWindow(target_window), + split_container.clone(), + None, + state, + )?; + move_container_within_tree( + Container::TilingWindow(moved_window), + split_container, + target_index, + state, + )?; + Ok(()) +} + +fn create_split_horizontal_direction( + state: &mut WmState, + config: &UserConfig, + moved_window: TilingWindow, + target_window: TilingWindow, + dropped_position: DropPosition, + parent: &Container, +) -> anyhow::Result<()> { + let target_index = match dropped_position { + // The split container is freshly created and will contain only 1 + // container + DropPosition::Start => Some(0), + DropPosition::End => None, + }; + + let split_container = Container::Split(SplitContainer::new( + TilingDirection::Horizontal, + config.value.gaps.inner_gap.clone(), + )); + attach_container(&split_container, &parent, None)?; + + move_container_within_tree( + Container::TilingWindow(target_window), + split_container.clone(), + None, + state, + )?; + move_container_within_tree( + Container::TilingWindow(moved_window), + split_container, + target_index, + state, + )?; + Ok(()) +} + +#[derive(Debug)] +enum DropPosition { + Start, + End, +} + +fn get_new_window_position( + mouse_position: &Point, + window: &TilingWindow, + tiling_direction: &TilingDirection, +) -> anyhow::Result { + let rect = window.to_rect()?; + + match tiling_direction { + TilingDirection::Vertical => { + let middle = rect.top + (rect.height() / 2); + if mouse_position.y < middle { + Ok(DropPosition::Start) + } else { + Ok(DropPosition::End) + } + } + TilingDirection::Horizontal => { + let middle = rect.left + (rect.width() / 2); + if mouse_position.x < middle { + Ok(DropPosition::Start) + } else { + Ok(DropPosition::End) + } + } + } +} +fn get_split_direction( + window: &TilingWindow, +) -> anyhow::Result { + let rect = window.to_rect()?; + + if rect.height() > rect.width() { + Ok(TilingDirection::Vertical) + } else { + Ok(TilingDirection::Horizontal) + } +} diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized.rs b/packages/wm/src/common/events/handle_window_moved_or_resized.rs index 961e6c7b3..a909da5b5 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized.rs @@ -6,11 +6,15 @@ use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; use crate::{ common::{ + commands::platform_sync, + events::handle_window_moved::window_moved, platform::{MouseMoveEvent, NativeWindow, Platform}, LengthValue, Point, Rect, }, containers::{ - commands::move_container_within_tree, + commands::{ + attach_container, detach_container, move_container_within_tree, + }, traits::{CommonGetters, PositionGetters}, Container, WindowContainer, }, @@ -19,6 +23,7 @@ use crate::{ commands::resize_window, traits::WindowGetters, NonTilingWindow, TilingWindow, }, + wm_event::WmEvent, wm_state::WmState, }; @@ -65,70 +70,6 @@ pub fn handle_window_moved_or_resized( Ok(()) } -/// Handles window move events -fn window_moved( - moved_window: TilingWindow, - state: &mut WmState, - config: &UserConfig, -) -> anyhow::Result<()> { - info!("Tiling window moved"); - - let workspace = moved_window - .workspace() - .context("Couldn't find a workspace")?; - - let mouse_position = Platform::mouse_position()?; - - let children_at_mouse_position: Vec<_> = workspace - .descendants() - .filter_map(|container| match container { - Container::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - info!("{:?}", frame); - info!("{:?}", mouse_position); - frame.unwrap().contains_point(&mouse_position) - }) - .filter(|window| window.id() != moved_window.id()) - .collect(); - - if children_at_mouse_position.is_empty() { - return Ok(()); - } - - let window_under_cursor = - children_at_mouse_position.into_iter().next().unwrap(); - - info!( - "Swapping {} with {}", - moved_window - .native() - .process_name() - .unwrap_or("".to_string()), - window_under_cursor - .native() - .process_name() - .unwrap_or("".to_string()) - ); - - // move_container_within_tree( - // Container::TilingWindow(moved_window), - // Container::TilingWindow(window_under_cursor), - // 0, - // state, - // ); - - Ok(()) -} - -enum ShouldSplit { - Vertically, - Horizontally, - No, -} - /// Handles window resize events fn window_resized( window: TilingWindow, diff --git a/packages/wm/src/common/events/mod.rs b/packages/wm/src/common/events/mod.rs index a882022f2..217e4aee2 100644 --- a/packages/wm/src/common/events/mod.rs +++ b/packages/wm/src/common/events/mod.rs @@ -6,6 +6,7 @@ mod handle_window_hidden; mod handle_window_location_changed; mod handle_window_minimize_ended; mod handle_window_minimized; +mod handle_window_moved; mod handle_window_moved_or_resized; mod handle_window_shown; mod handle_window_title_changed; diff --git a/packages/wm/src/common/platform/platform.rs b/packages/wm/src/common/platform/platform.rs index d75392ec6..884ec95ed 100644 --- a/packages/wm/src/common/platform/platform.rs +++ b/packages/wm/src/common/platform/platform.rs @@ -144,7 +144,6 @@ impl Platform { }; let handle = unsafe { WindowFromPoint(point) }; - dbg!(handle); Ok(NativeWindow::new(handle.0)) } diff --git a/packages/wm/src/containers/commands/move_container_within_tree.rs b/packages/wm/src/containers/commands/move_container_within_tree.rs index 128378b93..7e8953ba2 100644 --- a/packages/wm/src/containers/commands/move_container_within_tree.rs +++ b/packages/wm/src/containers/commands/move_container_within_tree.rs @@ -27,7 +27,7 @@ use crate::{ pub fn move_container_within_tree( container_to_move: Container, target_parent: Container, - target_index: usize, + target_index: Option, state: &WmState, ) -> anyhow::Result<()> { // Create iterator of parent, grandparent, and great-grandparent. @@ -43,14 +43,16 @@ pub fn move_container_within_tree( // If the container is already a child of the target parent, then shift // it to the target index. if container_to_move.parent().context("No parent.")? == target_parent { - target_parent - .borrow_children_mut() - .shift_to_index(target_index, container_to_move.clone()); - - if container_to_move.has_focus(None) { - state.emit_event(WmEvent::FocusedContainerMoved { - focused_container: container_to_move.to_dto()?, - }); + if let Some(target_index) = target_index { + target_parent + .borrow_children_mut() + .shift_to_index(target_index, container_to_move.clone()); + + if container_to_move.has_focus(None) { + state.emit_event(WmEvent::FocusedContainerMoved { + focused_container: container_to_move.to_dto()?, + }); + } } return Ok(()); @@ -59,6 +61,12 @@ pub fn move_container_within_tree( // Handle case where target parent is the LCA. For example, when swapping // sibling containers or moving a container to a direct ancestor. if target_parent == lowest_common_ancestor { + let target_index = if let Some(index) = target_index{ + index + }else { + return Ok(()); + }; + return move_to_lowest_common_ancestor( container_to_move, lowest_common_ancestor, @@ -102,7 +110,7 @@ pub fn move_container_within_tree( attach_container( &container_to_move.clone(), &target_parent.clone(), - Some(target_index), + target_index, )?; // Set `container_to_move` as focused descendant within target subtree if diff --git a/packages/wm/src/monitors/commands/remove_monitor.rs b/packages/wm/src/monitors/commands/remove_monitor.rs index ebca19445..6e345c0e2 100644 --- a/packages/wm/src/monitors/commands/remove_monitor.rs +++ b/packages/wm/src/monitors/commands/remove_monitor.rs @@ -44,7 +44,7 @@ pub fn remove_monitor( move_container_within_tree( workspace.clone().into(), target_monitor.clone().into(), - target_monitor.child_count(), + Some(target_monitor.child_count()), state, )?; diff --git a/packages/wm/src/windows/commands/move_window_in_direction.rs b/packages/wm/src/windows/commands/move_window_in_direction.rs index fc6cd14fa..acbd14fc8 100644 --- a/packages/wm/src/windows/commands/move_window_in_direction.rs +++ b/packages/wm/src/windows/commands/move_window_in_direction.rs @@ -155,7 +155,7 @@ fn move_to_sibling_container( move_container_within_tree( window_to_move.clone().into(), parent, - sibling_window.index(), + Some(sibling_window.index()), state, )?; @@ -190,7 +190,7 @@ fn move_to_sibling_container( move_container_within_tree( window_to_move.into(), target_parent.clone().into(), - target_index, + Some(target_index), state, )?; @@ -247,7 +247,7 @@ fn move_to_workspace_in_direction( move_container_within_tree( window_to_move.clone().into(), workspace.clone().into(), - target_index, + Some(target_index), state, )?; @@ -321,7 +321,7 @@ fn invert_workspace_tiling_direction( move_container_within_tree( window_to_move.clone().into(), workspace.clone().into(), - target_index, + Some(target_index), state, )?; @@ -369,7 +369,7 @@ fn insert_into_ancestor( move_container_within_tree( window_to_move.clone().into(), target_ancestor.clone().into(), - target_index, + Some(target_index), state, )?; diff --git a/packages/wm/src/windows/commands/move_window_to_workspace.rs b/packages/wm/src/windows/commands/move_window_to_workspace.rs index 065053603..4f5067db0 100644 --- a/packages/wm/src/windows/commands/move_window_to_workspace.rs +++ b/packages/wm/src/windows/commands/move_window_to_workspace.rs @@ -93,7 +93,7 @@ pub fn move_window_to_workspace( move_container_within_tree( window.clone().into(), insertion_sibling.clone().parent().context("No parent.")?, - insertion_sibling.index() + 1, + Some(insertion_sibling.index() + 1), state, )?; } @@ -102,7 +102,7 @@ pub fn move_window_to_workspace( move_container_within_tree( window.clone().into(), target_workspace.clone().into(), - target_workspace.child_count(), + Some(target_workspace.child_count()), state, )?; } diff --git a/packages/wm/src/windows/commands/update_window_state.rs b/packages/wm/src/windows/commands/update_window_state.rs index 7ff70e07d..6d77c05ed 100644 --- a/packages/wm/src/windows/commands/update_window_state.rs +++ b/packages/wm/src/windows/commands/update_window_state.rs @@ -80,7 +80,7 @@ fn set_tiling( move_container_within_tree( tiling_window.clone().into(), target_parent.clone(), - target_index, + Some(target_index), state, )?; @@ -137,7 +137,7 @@ fn set_non_tiling( move_container_within_tree( window.clone().into(), workspace.clone().into(), - workspace.child_count(), + Some(workspace.child_count()), state, )?; } diff --git a/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs b/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs index b1ca5c36a..443730583 100644 --- a/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs +++ b/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs @@ -28,7 +28,7 @@ pub fn move_workspace_in_direction( move_container_within_tree( workspace.clone().into(), target_monitor.clone().into(), - target_monitor.child_count(), + Some(target_monitor.child_count()), state, )?; From 0508c089d9494f630d394b8cafae810d9a984d5c Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 28 Jul 2024 21:01:59 +0200 Subject: [PATCH 05/35] fix: window moving logic --- .../src/common/events/handle_window_moved.rs | 65 +++++++++---------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved.rs b/packages/wm/src/common/events/handle_window_moved.rs index c9caf4395..625dc6700 100644 --- a/packages/wm/src/common/events/handle_window_moved.rs +++ b/packages/wm/src/common/events/handle_window_moved.rs @@ -136,17 +136,21 @@ fn move_window_to_target( new_tiling_direction: TilingDirection, new_window_position: DropPosition, ) -> anyhow::Result<()> { - let target_window_index = target_window_parent .children() .iter() .position(|c| { - c.as_tiling_window().unwrap().id() == target_window.id() + if let Some(tiling_window) = c.as_tiling_window() { + tiling_window.id() == target_window.id() + } else { + false + } }) .context("Window index not found")?; - if new_tiling_direction == TilingDirection::Horizontal { - if current_tiling_direction == TilingDirection::Horizontal { + match (new_tiling_direction, current_tiling_direction) { + (TilingDirection::Horizontal, TilingDirection::Horizontal) + | (TilingDirection::Vertical, TilingDirection::Vertical) => { let target_index = match new_window_position { DropPosition::Start => Some(target_window_index), DropPosition::End => None, @@ -158,40 +162,29 @@ fn move_window_to_target( target_index, state, )?; - } else { - if current_tiling_direction == TilingDirection::Vertical { - let target_index = match new_window_position { - DropPosition::Start => Some(target_window_index), - DropPosition::End => None, - }; - - move_container_within_tree( - Container::TilingWindow(moved_window.clone()), - target_window_parent.clone(), - target_index, - state, - )?; - } else { - create_split_horizontal_direction( - state, - config, - moved_window, - target_window, - new_window_position, - &target_window_parent, - )?; - } } - } else { - create_split_vertical_direction( - state, - config, - moved_window, - target_window, - new_window_position, - &target_window_parent, - )?; + (TilingDirection::Horizontal, TilingDirection::Vertical) => { + create_split_horizontal_direction( + state, + config, + moved_window, + target_window, + new_window_position, + &target_window_parent, + )?; + } + (TilingDirection::Vertical, TilingDirection::Horizontal) => { + create_split_vertical_direction( + state, + config, + moved_window, + target_window, + new_window_position, + &target_window_parent, + )?; + } } + Ok(()) } From be9679ed0574773dd06ed816af0eccb46df7d050 Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 28 Jul 2024 21:07:47 +0200 Subject: [PATCH 06/35] refactor: removed duplicated code --- .../src/common/events/handle_window_moved.rs | 47 +++---------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved.rs b/packages/wm/src/common/events/handle_window_moved.rs index 625dc6700..e49173315 100644 --- a/packages/wm/src/common/events/handle_window_moved.rs +++ b/packages/wm/src/common/events/handle_window_moved.rs @@ -164,7 +164,8 @@ fn move_window_to_target( )?; } (TilingDirection::Horizontal, TilingDirection::Vertical) => { - create_split_horizontal_direction( + create_split_container( + TilingDirection::Horizontal, state, config, moved_window, @@ -174,7 +175,8 @@ fn move_window_to_target( )?; } (TilingDirection::Vertical, TilingDirection::Horizontal) => { - create_split_vertical_direction( + create_split_container( + TilingDirection::Vertical, state, config, moved_window, @@ -188,7 +190,8 @@ fn move_window_to_target( Ok(()) } -fn create_split_vertical_direction( +fn create_split_container( + tiling_direction: TilingDirection, state: &mut WmState, config: &UserConfig, moved_window: TilingWindow, @@ -202,43 +205,7 @@ fn create_split_vertical_direction( }; let split_container = Container::Split(SplitContainer::new( - TilingDirection::Vertical, - config.value.gaps.inner_gap.clone(), - )); - attach_container(&split_container, &parent, None)?; - - move_container_within_tree( - Container::TilingWindow(target_window), - split_container.clone(), - None, - state, - )?; - move_container_within_tree( - Container::TilingWindow(moved_window), - split_container, - target_index, - state, - )?; - Ok(()) -} - -fn create_split_horizontal_direction( - state: &mut WmState, - config: &UserConfig, - moved_window: TilingWindow, - target_window: TilingWindow, - dropped_position: DropPosition, - parent: &Container, -) -> anyhow::Result<()> { - let target_index = match dropped_position { - // The split container is freshly created and will contain only 1 - // container - DropPosition::Start => Some(0), - DropPosition::End => None, - }; - - let split_container = Container::Split(SplitContainer::new( - TilingDirection::Horizontal, + tiling_direction, config.value.gaps.inner_gap.clone(), )); attach_container(&split_container, &parent, None)?; From b9c0ad151646758fbcabd83f6e3568d494783b2b Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 28 Jul 2024 21:21:52 +0200 Subject: [PATCH 07/35] feature: added window move start event --- ...ow_moved.rs => handle_window_moved_end.rs} | 2 +- ... => handle_window_moved_or_resized_end.rs} | 10 +-- .../handle_window_moved_or_resized_start.rs | 86 +++++++++++++++++++ .../events/handle_window_moved_start.rs | 37 ++++++++ packages/wm/src/common/events/mod.rs | 9 +- .../wm/src/common/platform/event_listener.rs | 3 +- .../src/common/platform/window_event_hook.rs | 8 +- packages/wm/src/wm.rs | 10 ++- 8 files changed, 150 insertions(+), 15 deletions(-) rename packages/wm/src/common/events/{handle_window_moved.rs => handle_window_moved_end.rs} (99%) rename packages/wm/src/common/events/{handle_window_moved_or_resized.rs => handle_window_moved_or_resized_end.rs} (89%) create mode 100644 packages/wm/src/common/events/handle_window_moved_or_resized_start.rs create mode 100644 packages/wm/src/common/events/handle_window_moved_start.rs diff --git a/packages/wm/src/common/events/handle_window_moved.rs b/packages/wm/src/common/events/handle_window_moved_end.rs similarity index 99% rename from packages/wm/src/common/events/handle_window_moved.rs rename to packages/wm/src/common/events/handle_window_moved_end.rs index e49173315..3150e699f 100644 --- a/packages/wm/src/common/events/handle_window_moved.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -27,7 +27,7 @@ use crate::{ }; /// Handles window move events -pub fn window_moved( +pub fn window_moved_end( moved_window: TilingWindow, state: &mut WmState, config: &UserConfig, diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs similarity index 89% rename from packages/wm/src/common/events/handle_window_moved_or_resized.rs rename to packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index a909da5b5..d6471b950 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -7,7 +7,7 @@ use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; use crate::{ common::{ commands::platform_sync, - events::handle_window_moved::window_moved, + events::handle_window_moved_end::window_moved_end, platform::{MouseMoveEvent, NativeWindow, Platform}, LengthValue, Point, Rect, }, @@ -31,7 +31,7 @@ use crate::{ /// by the user (e.g. via the window's drag handles). /// /// This resizes the window if it's a tiling window. -pub fn handle_window_moved_or_resized( +pub fn handle_window_moved_or_resized_end( native_window: NativeWindow, state: &mut WmState, config: &UserConfig, @@ -62,8 +62,8 @@ pub fn handle_window_moved_or_resized( }; return match has_window_moved { - true => window_moved(window, state, config), - false => window_resized(window, state, width_delta, height_delta), + true => window_moved_end(window, state, config), + false => window_resized_start(window, state, width_delta, height_delta), }; } @@ -71,7 +71,7 @@ pub fn handle_window_moved_or_resized( } /// Handles window resize events -fn window_resized( +fn window_resized_start( window: TilingWindow, state: &mut WmState, width_delta: i32, diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs new file mode 100644 index 000000000..4bace206e --- /dev/null +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -0,0 +1,86 @@ +use std::collections::VecDeque; + +use anyhow::Context; +use tracing::{debug, info}; +use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; + +use crate::{ + common::{ + commands::platform_sync, + events::{ + handle_window_moved_start::window_moved_start, + }, + platform::{MouseMoveEvent, NativeWindow, Platform}, + LengthValue, Point, Rect, + }, + containers::{ + commands::{ + attach_container, detach_container, move_container_within_tree, + }, + traits::{CommonGetters, PositionGetters}, + Container, WindowContainer, + }, + user_config::UserConfig, + windows::{ + commands::resize_window, traits::WindowGetters, NonTilingWindow, + TilingWindow, + }, + wm_event::WmEvent, + wm_state::WmState, +}; + +/// Handles the event for when a window is finished being moved or resized +/// by the user (e.g. via the window's drag handles). +/// +/// This resizes the window if it's a tiling window. +pub fn handle_window_moved_or_resized_start( + native_window: NativeWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + let found_window = state.window_from_native(&native_window); + + if let Some(WindowContainer::TilingWindow(window)) = found_window { + // TODO: Log window details. + + let parent = window.parent().context("No parent.")?; + + // Snap window to its original position if it's the only window in the + // workspace. + if parent.is_workspace() && window.tiling_siblings().count() == 0 { + state.pending_sync.containers_to_redraw.push(window.into()); + return Ok(()); + } + + let new_rect = window.native().refresh_frame_position()?; + let old_rect = window.to_rect()?; + + let width_delta = new_rect.width() - old_rect.width(); + let height_delta = new_rect.height() - old_rect.height(); + + let has_window_moved = match (width_delta, height_delta) { + (0, 0) => true, + _ => false, + }; + + return match has_window_moved { + true => window_moved_start(window, state, config), + false => { + window_resized_start(window, state, width_delta, height_delta) + } + }; + } + + Ok(()) +} + +/// Handles window resize events +fn window_resized_start( + window: TilingWindow, + state: &mut WmState, + width_delta: i32, + height_delta: i32, +) -> anyhow::Result<()> { + info!("Tiling window resize start"); + Ok(()) +} diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs new file mode 100644 index 000000000..6abd0616a --- /dev/null +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -0,0 +1,37 @@ +use std::{collections::VecDeque, io::Split}; + +use anyhow::Context; +use tracing::{debug, info}; +use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; + +use crate::{ + common::{ + commands::platform_sync, + LengthValue, + platform::{MouseMoveEvent, NativeWindow, Platform}, Point, Rect, TilingDirection, + }, + containers::{ + commands::{ + attach_container, detach_container, move_container_within_tree, + }, + Container, + SplitContainer, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, WindowContainer, + }, + user_config::UserConfig, + windows::{ + commands::resize_window, NonTilingWindow, TilingWindow, + traits::WindowGetters, + }, + wm_event::WmEvent, + wm_state::WmState, +}; + +/// Handles window move events +pub fn window_moved_start( + moved_window: TilingWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + info!("Tiling window move start"); + Ok(()) +} diff --git a/packages/wm/src/common/events/mod.rs b/packages/wm/src/common/events/mod.rs index 217e4aee2..2fb315544 100644 --- a/packages/wm/src/common/events/mod.rs +++ b/packages/wm/src/common/events/mod.rs @@ -6,10 +6,12 @@ mod handle_window_hidden; mod handle_window_location_changed; mod handle_window_minimize_ended; mod handle_window_minimized; -mod handle_window_moved; -mod handle_window_moved_or_resized; +mod handle_window_moved_end; +mod handle_window_moved_or_resized_end; mod handle_window_shown; mod handle_window_title_changed; +mod handle_window_moved_start; +mod handle_window_moved_or_resized_start; pub use handle_display_settings_changed::*; pub use handle_mouse_move::*; @@ -19,6 +21,7 @@ pub use handle_window_hidden::*; pub use handle_window_location_changed::*; pub use handle_window_minimize_ended::*; pub use handle_window_minimized::*; -pub use handle_window_moved_or_resized::*; +pub use handle_window_moved_or_resized_end::*; +pub use handle_window_moved_or_resized_start::*; pub use handle_window_shown::*; pub use handle_window_title_changed::*; diff --git a/packages/wm/src/common/platform/event_listener.rs b/packages/wm/src/common/platform/event_listener.rs index f8e0cec10..0a5dbd833 100644 --- a/packages/wm/src/common/platform/event_listener.rs +++ b/packages/wm/src/common/platform/event_listener.rs @@ -17,7 +17,8 @@ pub enum PlatformEvent { WindowLocationChanged(NativeWindow), WindowMinimized(NativeWindow), WindowMinimizeEnded(NativeWindow), - WindowMovedOrResized(NativeWindow), + WindowMovedOrResizedEnd(NativeWindow), + WindowMovedOrResizedStart(NativeWindow), WindowShown(NativeWindow), WindowTitleChanged(NativeWindow), } diff --git a/packages/wm/src/common/platform/window_event_hook.rs b/packages/wm/src/common/platform/window_event_hook.rs index b144f53ac..c6d170700 100644 --- a/packages/wm/src/common/platform/window_event_hook.rs +++ b/packages/wm/src/common/platform/window_event_hook.rs @@ -12,7 +12,7 @@ use windows::Win32::{ EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_SHOW, EVENT_OBJECT_UNCLOAKED, EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, - EVENT_SYSTEM_MOVESIZEEND, OBJID_WINDOW, WINEVENT_OUTOFCONTEXT, + EVENT_SYSTEM_MOVESIZEEND,EVENT_SYSTEM_MOVESIZESTART, OBJID_WINDOW, WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS, }, }, @@ -63,6 +63,7 @@ impl WindowEventHook { (EVENT_OBJECT_DESTROY, EVENT_OBJECT_HIDE), (EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MINIMIZEEND), (EVENT_SYSTEM_MOVESIZEEND, EVENT_SYSTEM_MOVESIZEEND), + (EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZESTART), (EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND), (EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_NAMECHANGE), (EVENT_OBJECT_CLOAKED, EVENT_OBJECT_UNCLOAKED), @@ -122,7 +123,10 @@ impl WindowEventHook { PlatformEvent::WindowMinimizeEnded(window) } EVENT_SYSTEM_MOVESIZEEND => { - PlatformEvent::WindowMovedOrResized(window) + PlatformEvent::WindowMovedOrResizedEnd(window) + } + EVENT_SYSTEM_MOVESIZESTART => { + PlatformEvent::WindowMovedOrResizedStart(window) } EVENT_OBJECT_SHOW | EVENT_OBJECT_UNCLOAKED => { PlatformEvent::WindowShown(window) diff --git a/packages/wm/src/wm.rs b/packages/wm/src/wm.rs index 173fe20f7..39d9b6912 100644 --- a/packages/wm/src/wm.rs +++ b/packages/wm/src/wm.rs @@ -11,7 +11,8 @@ use crate::{ handle_window_destroyed, handle_window_focused, handle_window_hidden, handle_window_location_changed, handle_window_minimize_ended, handle_window_minimized, - handle_window_moved_or_resized, handle_window_shown, + handle_window_moved_or_resized_end, + handle_window_moved_or_resized_start, handle_window_shown, handle_window_title_changed, }, platform::PlatformEvent, @@ -81,8 +82,11 @@ impl WindowManager { PlatformEvent::WindowMinimizeEnded(window) => { handle_window_minimize_ended(window, state, config) } - PlatformEvent::WindowMovedOrResized(window) => { - handle_window_moved_or_resized(window, state, config) + PlatformEvent::WindowMovedOrResizedEnd(window) => { + handle_window_moved_or_resized_end(window, state, config) + } + PlatformEvent::WindowMovedOrResizedStart(window) => { + handle_window_moved_or_resized_start(window, state, config) } PlatformEvent::WindowShown(window) => { handle_window_shown(window, state, config) From 37ddc091b3a5842c0d0b7144180e585a5fed04aa Mon Sep 17 00:00:00 2001 From: Luca Date: Sun, 28 Jul 2024 23:15:55 +0200 Subject: [PATCH 08/35] feat: When drag start, sets window to floating --- .../common/events/handle_window_moved_end.rs | 47 ++++++++++--------- .../handle_window_moved_or_resized_end.rs | 30 +++++++++--- .../events/handle_window_moved_start.rs | 31 +++++++++--- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 3150e699f..645ea590b 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -1,38 +1,28 @@ -use std::{collections::VecDeque, io::Split}; - use anyhow::Context; -use tracing::{debug, info}; -use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; +use tracing::info; use crate::{ - common::{ - commands::platform_sync, - platform::{MouseMoveEvent, NativeWindow, Platform}, - LengthValue, Point, Rect, TilingDirection, - }, + common::{platform::Platform, Point, TilingDirection}, containers::{ - commands::{ - attach_container, detach_container, move_container_within_tree, - }, + commands::{attach_container, move_container_within_tree}, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, SplitContainer, WindowContainer, + Container, SplitContainer, }, user_config::UserConfig, windows::{ - commands::resize_window, traits::WindowGetters, NonTilingWindow, - TilingWindow, + commands::update_window_state, traits::WindowGetters, NonTilingWindow, + TilingWindow, WindowState, }, - wm_event::WmEvent, wm_state::WmState, }; /// Handles window move events pub fn window_moved_end( - moved_window: TilingWindow, + moved_window: NonTilingWindow, state: &mut WmState, config: &UserConfig, ) -> anyhow::Result<()> { - info!("Tiling window moved"); + info!("Tiling window moved end"); let workspace = moved_window .workspace() @@ -118,18 +108,15 @@ pub fn window_moved_end( } _ => {} } - state.pending_sync.containers_to_redraw.push(parent); - // info!("{:#?}", workspace); - Ok(()) } fn move_window_to_target( state: &mut WmState, config: &UserConfig, - moved_window: TilingWindow, + moved_window: NonTilingWindow, target_window: TilingWindow, target_window_parent: &Container, current_tiling_direction: TilingDirection, @@ -148,6 +135,22 @@ fn move_window_to_target( }) .context("Window index not found")?; + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Tiling, + state, + config, + )?; + + let moved_window = state + .windows() + .iter() + .find(|w| w.id() == moved_window.id()) + .context("couldn't find the new tiled window")? + .as_tiling_window() + .context("window is not a tiled window")? + .clone(); + match (new_tiling_direction, current_tiling_direction) { (TilingDirection::Horizontal, TilingDirection::Horizontal) | (TilingDirection::Vertical, TilingDirection::Vertical) => { diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index d6471b950..e34348084 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -37,8 +37,9 @@ pub fn handle_window_moved_or_resized_end( config: &UserConfig, ) -> anyhow::Result<()> { let found_window = state.window_from_native(&native_window); + info!("{:#?}", found_window); - if let Some(WindowContainer::TilingWindow(window)) = found_window { + if let Some(WindowContainer::NonTilingWindow(window)) = found_window { // TODO: Log window details. let parent = window.parent().context("No parent.")?; @@ -61,17 +62,34 @@ pub fn handle_window_moved_or_resized_end( _ => false, }; - return match has_window_moved { - true => window_moved_end(window, state, config), - false => window_resized_start(window, state, width_delta, height_delta), - }; + if has_window_moved { + window_moved_end(window, state, config)?; + } + } else if let Some(WindowContainer::TilingWindow(window)) = found_window + { + let parent = window.parent().context("No parent.")?; + + // Snap window to its original position if it's the only window in the + // workspace. + if parent.is_workspace() && window.tiling_siblings().count() == 0 { + state.pending_sync.containers_to_redraw.push(window.into()); + return Ok(()); + } + + let new_rect = window.native().refresh_frame_position()?; + let old_rect = window.to_rect()?; + + let width_delta = new_rect.width() - old_rect.width(); + let height_delta = new_rect.height() - old_rect.height(); + + window_resized_end(window, state, width_delta, height_delta)?; } Ok(()) } /// Handles window resize events -fn window_resized_start( +fn window_resized_end( window: TilingWindow, state: &mut WmState, width_delta: i32, diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index 6abd0616a..3802c5032 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -7,20 +7,21 @@ use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; use crate::{ common::{ commands::platform_sync, - LengthValue, - platform::{MouseMoveEvent, NativeWindow, Platform}, Point, Rect, TilingDirection, + platform::{MouseMoveEvent, NativeWindow, Platform}, + LengthValue, Point, Rect, TilingDirection, }, containers::{ commands::{ attach_container, detach_container, move_container_within_tree, }, - Container, - SplitContainer, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, WindowContainer, + traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, + Container, SplitContainer, WindowContainer, }, - user_config::UserConfig, + user_config::{FloatingStateConfig, UserConfig}, windows::{ - commands::resize_window, NonTilingWindow, TilingWindow, + commands::{resize_window, update_window_state}, traits::WindowGetters, + NonTilingWindow, TilingWindow, WindowState, }, wm_event::WmEvent, wm_state::WmState, @@ -32,6 +33,22 @@ pub fn window_moved_start( state: &mut WmState, config: &UserConfig, ) -> anyhow::Result<()> { - info!("Tiling window move start"); + info!("Tiling window moved start"); + let moved_window_parent = moved_window + .parent() + .context("Tiling window has no parent")?; + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Floating(FloatingStateConfig { + centered: true, + shown_on_top: true, + }), + state, + config, + )?; + state + .pending_sync + .containers_to_redraw + .push(moved_window_parent); Ok(()) } From d3f0c465dc1bb979a45e9fb5afe6e9d992a69562 Mon Sep 17 00:00:00 2001 From: Luca Date: Mon, 29 Jul 2024 00:18:30 +0200 Subject: [PATCH 09/35] fix: bug when moving window to a target on the right side --- .../common/events/handle_window_moved_end.rs | 42 ++++++++++--------- .../handle_window_moved_or_resized_end.rs | 42 +++++++------------ 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 645ea590b..57be51542 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -1,6 +1,5 @@ use anyhow::Context; use tracing::info; - use crate::{ common::{platform::Platform, Point, TilingDirection}, containers::{ @@ -15,6 +14,7 @@ use crate::{ }, wm_state::WmState, }; +use crate::containers::commands::detach_container; /// Handles window move events pub fn window_moved_end( @@ -123,17 +123,17 @@ fn move_window_to_target( new_tiling_direction: TilingDirection, new_window_position: DropPosition, ) -> anyhow::Result<()> { - let target_window_index = target_window_parent - .children() - .iter() - .position(|c| { - if let Some(tiling_window) = c.as_tiling_window() { - tiling_window.id() == target_window.id() - } else { - false - } - }) - .context("Window index not found")?; + + // TODO: We can optimize that for sure by not detaching and attaching the window + // Little trick to get the right index + detach_container(Container::NonTilingWindow(moved_window.clone()))?; + let target_window_index = target_window.index(); + attach_container(&Container::NonTilingWindow(moved_window.clone()), target_window_parent, None)?; + + let target_index = match new_window_position { + DropPosition::Start => Some(target_window_index), + DropPosition::End => Some(target_window_index + 1), + }; update_window_state( moved_window.as_window_container().unwrap(), @@ -142,6 +142,7 @@ fn move_window_to_target( config, )?; + let moved_window = state .windows() .iter() @@ -151,13 +152,11 @@ fn move_window_to_target( .context("window is not a tiled window")? .clone(); + match (new_tiling_direction, current_tiling_direction) { (TilingDirection::Horizontal, TilingDirection::Horizontal) | (TilingDirection::Vertical, TilingDirection::Vertical) => { - let target_index = match new_window_position { - DropPosition::Start => Some(target_window_index), - DropPosition::End => None, - }; + info!("Target window index {}", target_window_index); move_container_within_tree( Container::TilingWindow(moved_window.clone()), @@ -175,6 +174,7 @@ fn move_window_to_target( target_window, new_window_position, &target_window_parent, + target_index, )?; } (TilingDirection::Vertical, TilingDirection::Horizontal) => { @@ -186,6 +186,7 @@ fn move_window_to_target( target_window, new_window_position, &target_window_parent, + target_index, )?; } } @@ -201,17 +202,18 @@ fn create_split_container( target_window: TilingWindow, dropped_position: DropPosition, parent: &Container, + split_container_index: Option, ) -> anyhow::Result<()> { - let target_index = match dropped_position { + let target_index_inside_split_container = match dropped_position { DropPosition::Start => Some(0), - DropPosition::End => None, + DropPosition::End => Some(1), }; let split_container = Container::Split(SplitContainer::new( tiling_direction, config.value.gaps.inner_gap.clone(), )); - attach_container(&split_container, &parent, None)?; + attach_container(&split_container, &parent, split_container_index)?; move_container_within_tree( Container::TilingWindow(target_window), @@ -222,7 +224,7 @@ fn create_split_container( move_container_within_tree( Container::TilingWindow(moved_window), split_container, - target_index, + target_index_inside_split_container, state, )?; Ok(()) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index e34348084..4f62557d1 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -37,9 +37,7 @@ pub fn handle_window_moved_or_resized_end( config: &UserConfig, ) -> anyhow::Result<()> { let found_window = state.window_from_native(&native_window); - info!("{:#?}", found_window); - - if let Some(WindowContainer::NonTilingWindow(window)) = found_window { + if let Some(window) = found_window{ // TODO: Log window details. let parent = window.parent().context("No parent.")?; @@ -57,34 +55,22 @@ pub fn handle_window_moved_or_resized_end( let width_delta = new_rect.width() - old_rect.width(); let height_delta = new_rect.height() - old_rect.height(); - let has_window_moved = match (width_delta, height_delta) { - (0, 0) => true, - _ => false, - }; - - if has_window_moved { - window_moved_end(window, state, config)?; - } - } else if let Some(WindowContainer::TilingWindow(window)) = found_window - { - let parent = window.parent().context("No parent.")?; - - // Snap window to its original position if it's the only window in the - // workspace. - if parent.is_workspace() && window.tiling_siblings().count() == 0 { - state.pending_sync.containers_to_redraw.push(window.into()); - return Ok(()); + if let WindowContainer::NonTilingWindow(window) = window { + let has_window_moved = match (width_delta, height_delta) { + (0, 0) => true, + _ => false, + }; + + if has_window_moved { + window_moved_end(window, state, config)?; + } + } else if let WindowContainer::TilingWindow(window) = window + { + window_resized_end(window, state, width_delta, height_delta)?; } - - let new_rect = window.native().refresh_frame_position()?; - let old_rect = window.to_rect()?; - - let width_delta = new_rect.width() - old_rect.width(); - let height_delta = new_rect.height() - old_rect.height(); - - window_resized_end(window, state, width_delta, height_delta)?; } + Ok(()) } From ec7a335708d99e2c5c10918b13427a24c920841a Mon Sep 17 00:00:00 2001 From: Luca Date: Mon, 29 Jul 2024 22:24:46 +0200 Subject: [PATCH 10/35] feat: Added a way to know if a floating window was created by dragging --- packages/wm/src/app_command.rs | 2 ++ packages/wm/src/common/events/handle_window_moved_end.rs | 9 ++++++--- .../wm/src/common/events/handle_window_moved_start.rs | 4 +++- packages/wm/src/user_config.rs | 4 ++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/wm/src/app_command.rs b/packages/wm/src/app_command.rs index fa4d5341d..b00f88309 100644 --- a/packages/wm/src/app_command.rs +++ b/packages/wm/src/app_command.rs @@ -404,6 +404,7 @@ impl InvokeCommand { centered: centered.unwrap_or(floating_defaults.centered), shown_on_top: shown_on_top .unwrap_or(floating_defaults.shown_on_top), + is_tiling_drag: false, }), state, config, @@ -478,6 +479,7 @@ impl InvokeCommand { centered: centered.unwrap_or(floating_defaults.centered), shown_on_top: shown_on_top .unwrap_or(floating_defaults.shown_on_top), + is_tiling_drag: false, }); update_window_state( diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 57be51542..f78b66a1e 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -15,6 +15,7 @@ use crate::{ wm_state::WmState, }; use crate::containers::commands::detach_container; +use crate::user_config::FloatingStateConfig; /// Handles window move events pub fn window_moved_end( @@ -22,7 +23,11 @@ pub fn window_moved_end( state: &mut WmState, config: &UserConfig, ) -> anyhow::Result<()> { - info!("Tiling window moved end"); + // We continue only if it's a temporary Floating window + if matches!(moved_window.state(), WindowState::Floating(FloatingStateConfig{is_tiling_drag: false,..})){ + return Ok(()); + } + info!("Tiling window drag end"); let workspace = moved_window .workspace() @@ -38,8 +43,6 @@ pub fn window_moved_end( }) .filter(|c| { let frame = c.to_rect(); - info!("{:?}", frame); - info!("{:?}", mouse_position); frame.unwrap().contains_point(&mouse_position) }) .filter(|window| window.id() != moved_window.id()) diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index 3802c5032..2fa721e12 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -33,15 +33,17 @@ pub fn window_moved_start( state: &mut WmState, config: &UserConfig, ) -> anyhow::Result<()> { - info!("Tiling window moved start"); + info!("Tiling window drag start"); let moved_window_parent = moved_window .parent() .context("Tiling window has no parent")?; + update_window_state( moved_window.as_window_container().unwrap(), WindowState::Floating(FloatingStateConfig { centered: true, shown_on_top: true, + is_tiling_drag: true, }), state, config, diff --git a/packages/wm/src/user_config.rs b/packages/wm/src/user_config.rs index fc1523deb..d84466afa 100644 --- a/packages/wm/src/user_config.rs +++ b/packages/wm/src/user_config.rs @@ -436,6 +436,10 @@ pub struct FloatingStateConfig { /// Whether to show floating windows as always on top. #[serde(default = "default_bool::")] pub shown_on_top: bool, + + /// Whether the floating window was created with a drag. + #[serde(default = "default_bool::")] + pub is_tiling_drag: bool, } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] From 63caa2a6453c79ac9fd353494ccbb6634531f718 Mon Sep 17 00:00:00 2001 From: Luca Date: Mon, 29 Jul 2024 22:40:53 +0200 Subject: [PATCH 11/35] fix: revert changes and fixed imports --- .../events/handle_window_location_changed.rs | 2 +- .../common/events/handle_window_moved_end.rs | 14 ++++---- .../handle_window_moved_or_resized_end.rs | 24 ++++--------- .../handle_window_moved_or_resized_start.rs | 35 ++++--------------- .../events/handle_window_moved_start.rs | 25 ++----------- packages/wm/src/common/platform/platform.rs | 1 - .../commands/move_container_within_tree.rs | 12 ++----- .../src/monitors/commands/remove_monitor.rs | 2 +- .../commands/move_window_in_direction.rs | 10 +++--- .../commands/move_window_to_workspace.rs | 4 +-- .../windows/commands/update_window_state.rs | 4 +-- .../commands/move_workspace_in_direction.rs | 2 +- 12 files changed, 37 insertions(+), 98 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index fcf341486..7941a9cbc 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -120,7 +120,7 @@ pub fn handle_window_location_changed( move_container_within_tree( window.into(), updated_workspace.clone().into(), - Some(updated_workspace.child_count()), + updated_workspace.child_count(), state, )?; } diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index f78b66a1e..6d0e01c9a 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -134,8 +134,8 @@ fn move_window_to_target( attach_container(&Container::NonTilingWindow(moved_window.clone()), target_window_parent, None)?; let target_index = match new_window_position { - DropPosition::Start => Some(target_window_index), - DropPosition::End => Some(target_window_index + 1), + DropPosition::Start => target_window_index, + DropPosition::End => target_window_index + 1, }; update_window_state( @@ -205,23 +205,23 @@ fn create_split_container( target_window: TilingWindow, dropped_position: DropPosition, parent: &Container, - split_container_index: Option, + split_container_index: usize, ) -> anyhow::Result<()> { let target_index_inside_split_container = match dropped_position { - DropPosition::Start => Some(0), - DropPosition::End => Some(1), + DropPosition::Start => 0, + DropPosition::End => 1, }; let split_container = Container::Split(SplitContainer::new( tiling_direction, config.value.gaps.inner_gap.clone(), )); - attach_container(&split_container, &parent, split_container_index)?; + attach_container(&split_container, &parent, Some(split_container_index))?; move_container_within_tree( Container::TilingWindow(target_window), split_container.clone(), - None, + 0, state, )?; move_container_within_tree( diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index 4f62557d1..f55926d9d 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -1,29 +1,19 @@ -use std::collections::VecDeque; - use anyhow::Context; -use tracing::{debug, info}; -use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; +use tracing::info; use crate::{ common::{ - commands::platform_sync, events::handle_window_moved_end::window_moved_end, - platform::{MouseMoveEvent, NativeWindow, Platform}, - LengthValue, Point, Rect, + platform::NativeWindow, LengthValue, }, containers::{ - commands::{ - attach_container, detach_container, move_container_within_tree, - }, traits::{CommonGetters, PositionGetters}, - Container, WindowContainer, + WindowContainer, }, user_config::UserConfig, windows::{ - commands::resize_window, traits::WindowGetters, NonTilingWindow, - TilingWindow, + commands::resize_window, traits::WindowGetters, TilingWindow, }, - wm_event::WmEvent, wm_state::WmState, }; @@ -37,7 +27,7 @@ pub fn handle_window_moved_or_resized_end( config: &UserConfig, ) -> anyhow::Result<()> { let found_window = state.window_from_native(&native_window); - if let Some(window) = found_window{ + if let Some(window) = found_window { // TODO: Log window details. let parent = window.parent().context("No parent.")?; @@ -64,13 +54,11 @@ pub fn handle_window_moved_or_resized_end( if has_window_moved { window_moved_end(window, state, config)?; } - } else if let WindowContainer::TilingWindow(window) = window - { + } else if let WindowContainer::TilingWindow(window) = window { window_resized_end(window, state, width_delta, height_delta)?; } } - Ok(()) } diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index 4bace206e..231e99567 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -1,31 +1,17 @@ -use std::collections::VecDeque; - use anyhow::Context; -use tracing::{debug, info}; -use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; +use tracing::info; use crate::{ common::{ - commands::platform_sync, - events::{ - handle_window_moved_start::window_moved_start, - }, - platform::{MouseMoveEvent, NativeWindow, Platform}, - LengthValue, Point, Rect, + events::handle_window_moved_start::window_moved_start, + platform::NativeWindow, }, containers::{ - commands::{ - attach_container, detach_container, move_container_within_tree, - }, traits::{CommonGetters, PositionGetters}, - Container, WindowContainer, + WindowContainer, }, user_config::UserConfig, - windows::{ - commands::resize_window, traits::WindowGetters, NonTilingWindow, - TilingWindow, - }, - wm_event::WmEvent, + windows::traits::WindowGetters, wm_state::WmState, }; @@ -65,9 +51,7 @@ pub fn handle_window_moved_or_resized_start( return match has_window_moved { true => window_moved_start(window, state, config), - false => { - window_resized_start(window, state, width_delta, height_delta) - } + false => window_resized_start(), }; } @@ -75,12 +59,7 @@ pub fn handle_window_moved_or_resized_start( } /// Handles window resize events -fn window_resized_start( - window: TilingWindow, - state: &mut WmState, - width_delta: i32, - height_delta: i32, -) -> anyhow::Result<()> { +fn window_resized_start() -> anyhow::Result<()> { info!("Tiling window resize start"); Ok(()) } diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index 2fa721e12..19c2f4603 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -1,29 +1,10 @@ -use std::{collections::VecDeque, io::Split}; - use anyhow::Context; -use tracing::{debug, info}; -use windows::Win32::{Foundation, UI::WindowsAndMessaging::GetCursorPos}; +use tracing::info; use crate::{ - common::{ - commands::platform_sync, - platform::{MouseMoveEvent, NativeWindow, Platform}, - LengthValue, Point, Rect, TilingDirection, - }, - containers::{ - commands::{ - attach_container, detach_container, move_container_within_tree, - }, - traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, SplitContainer, WindowContainer, - }, + containers::traits::CommonGetters, user_config::{FloatingStateConfig, UserConfig}, - windows::{ - commands::{resize_window, update_window_state}, - traits::WindowGetters, - NonTilingWindow, TilingWindow, WindowState, - }, - wm_event::WmEvent, + windows::{commands::update_window_state, TilingWindow, WindowState}, wm_state::WmState, }; diff --git a/packages/wm/src/common/platform/platform.rs b/packages/wm/src/common/platform/platform.rs index 884ec95ed..fa2de98f4 100644 --- a/packages/wm/src/common/platform/platform.rs +++ b/packages/wm/src/common/platform/platform.rs @@ -5,7 +5,6 @@ use std::{ }; use anyhow::{bail, Context}; -use tracing::{field::debug, info}; use windows::{ core::{w, PCWSTR}, Win32::{ diff --git a/packages/wm/src/containers/commands/move_container_within_tree.rs b/packages/wm/src/containers/commands/move_container_within_tree.rs index 7e8953ba2..3c487f44d 100644 --- a/packages/wm/src/containers/commands/move_container_within_tree.rs +++ b/packages/wm/src/containers/commands/move_container_within_tree.rs @@ -27,7 +27,7 @@ use crate::{ pub fn move_container_within_tree( container_to_move: Container, target_parent: Container, - target_index: Option, + target_index: usize, state: &WmState, ) -> anyhow::Result<()> { // Create iterator of parent, grandparent, and great-grandparent. @@ -43,7 +43,6 @@ pub fn move_container_within_tree( // If the container is already a child of the target parent, then shift // it to the target index. if container_to_move.parent().context("No parent.")? == target_parent { - if let Some(target_index) = target_index { target_parent .borrow_children_mut() .shift_to_index(target_index, container_to_move.clone()); @@ -53,7 +52,6 @@ pub fn move_container_within_tree( focused_container: container_to_move.to_dto()?, }); } - } return Ok(()); } @@ -61,12 +59,6 @@ pub fn move_container_within_tree( // Handle case where target parent is the LCA. For example, when swapping // sibling containers or moving a container to a direct ancestor. if target_parent == lowest_common_ancestor { - let target_index = if let Some(index) = target_index{ - index - }else { - return Ok(()); - }; - return move_to_lowest_common_ancestor( container_to_move, lowest_common_ancestor, @@ -110,7 +102,7 @@ pub fn move_container_within_tree( attach_container( &container_to_move.clone(), &target_parent.clone(), - target_index, + Some(target_index), )?; // Set `container_to_move` as focused descendant within target subtree if diff --git a/packages/wm/src/monitors/commands/remove_monitor.rs b/packages/wm/src/monitors/commands/remove_monitor.rs index 6e345c0e2..ebca19445 100644 --- a/packages/wm/src/monitors/commands/remove_monitor.rs +++ b/packages/wm/src/monitors/commands/remove_monitor.rs @@ -44,7 +44,7 @@ pub fn remove_monitor( move_container_within_tree( workspace.clone().into(), target_monitor.clone().into(), - Some(target_monitor.child_count()), + target_monitor.child_count(), state, )?; diff --git a/packages/wm/src/windows/commands/move_window_in_direction.rs b/packages/wm/src/windows/commands/move_window_in_direction.rs index acbd14fc8..fc6cd14fa 100644 --- a/packages/wm/src/windows/commands/move_window_in_direction.rs +++ b/packages/wm/src/windows/commands/move_window_in_direction.rs @@ -155,7 +155,7 @@ fn move_to_sibling_container( move_container_within_tree( window_to_move.clone().into(), parent, - Some(sibling_window.index()), + sibling_window.index(), state, )?; @@ -190,7 +190,7 @@ fn move_to_sibling_container( move_container_within_tree( window_to_move.into(), target_parent.clone().into(), - Some(target_index), + target_index, state, )?; @@ -247,7 +247,7 @@ fn move_to_workspace_in_direction( move_container_within_tree( window_to_move.clone().into(), workspace.clone().into(), - Some(target_index), + target_index, state, )?; @@ -321,7 +321,7 @@ fn invert_workspace_tiling_direction( move_container_within_tree( window_to_move.clone().into(), workspace.clone().into(), - Some(target_index), + target_index, state, )?; @@ -369,7 +369,7 @@ fn insert_into_ancestor( move_container_within_tree( window_to_move.clone().into(), target_ancestor.clone().into(), - Some(target_index), + target_index, state, )?; diff --git a/packages/wm/src/windows/commands/move_window_to_workspace.rs b/packages/wm/src/windows/commands/move_window_to_workspace.rs index 4f5067db0..065053603 100644 --- a/packages/wm/src/windows/commands/move_window_to_workspace.rs +++ b/packages/wm/src/windows/commands/move_window_to_workspace.rs @@ -93,7 +93,7 @@ pub fn move_window_to_workspace( move_container_within_tree( window.clone().into(), insertion_sibling.clone().parent().context("No parent.")?, - Some(insertion_sibling.index() + 1), + insertion_sibling.index() + 1, state, )?; } @@ -102,7 +102,7 @@ pub fn move_window_to_workspace( move_container_within_tree( window.clone().into(), target_workspace.clone().into(), - Some(target_workspace.child_count()), + target_workspace.child_count(), state, )?; } diff --git a/packages/wm/src/windows/commands/update_window_state.rs b/packages/wm/src/windows/commands/update_window_state.rs index 6d77c05ed..7ff70e07d 100644 --- a/packages/wm/src/windows/commands/update_window_state.rs +++ b/packages/wm/src/windows/commands/update_window_state.rs @@ -80,7 +80,7 @@ fn set_tiling( move_container_within_tree( tiling_window.clone().into(), target_parent.clone(), - Some(target_index), + target_index, state, )?; @@ -137,7 +137,7 @@ fn set_non_tiling( move_container_within_tree( window.clone().into(), workspace.clone().into(), - Some(workspace.child_count()), + workspace.child_count(), state, )?; } diff --git a/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs b/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs index 443730583..b1ca5c36a 100644 --- a/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs +++ b/packages/wm/src/workspaces/commands/move_workspace_in_direction.rs @@ -28,7 +28,7 @@ pub fn move_workspace_in_direction( move_container_within_tree( workspace.clone().into(), target_monitor.clone().into(), - Some(target_monitor.child_count()), + target_monitor.child_count(), state, )?; From 26e3709b6504d93771aade21a92b33a34f269abb Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 18:01:43 +0200 Subject: [PATCH 12/35] comment: todo --- .../src/common/events/handle_window_moved_or_resized_start.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index 231e99567..dd0b6ecd4 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -41,6 +41,8 @@ pub fn handle_window_moved_or_resized_start( let new_rect = window.native().refresh_frame_position()?; let old_rect = window.to_rect()?; + + // TODO: This method to check if the window was resized or moved doesn't work. We need to find an alternative let width_delta = new_rect.width() - old_rect.width(); let height_delta = new_rect.height() - old_rect.height(); From 3fb3d57c5b26ceafb4c4e39d340f721e3e0f5934 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 18:05:31 +0200 Subject: [PATCH 13/35] feat: check state of floating window --- packages/wm/src/common/events/handle_window_moved_end.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 6d0e01c9a..4594f3706 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -24,7 +24,13 @@ pub fn window_moved_end( config: &UserConfig, ) -> anyhow::Result<()> { // We continue only if it's a temporary Floating window - if matches!(moved_window.state(), WindowState::Floating(FloatingStateConfig{is_tiling_drag: false,..})){ + if matches!( + moved_window.state(), + WindowState::Floating(FloatingStateConfig { + is_tiling_drag: false, + .. + }) + ) { return Ok(()); } info!("Tiling window drag end"); From 3ef0155cc124a7f14a12987432ab2c6fbc7979e6 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 18:28:13 +0200 Subject: [PATCH 14/35] refactor --- .../common/events/handle_window_moved_end.rs | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 4594f3706..d68f30dfb 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -16,6 +16,7 @@ use crate::{ }; use crate::containers::commands::detach_container; use crate::user_config::FloatingStateConfig; +use crate::workspaces::Workspace; /// Handles window move events pub fn window_moved_end( @@ -33,7 +34,7 @@ pub fn window_moved_end( ) { return Ok(()); } - info!("Tiling window drag end"); + info!("Tiling window drag end event"); let workspace = moved_window .workspace() @@ -41,36 +42,19 @@ pub fn window_moved_end( let mouse_position = Platform::mouse_position()?; - let children_at_mouse_position: Vec<_> = workspace - .descendants() - .filter_map(|container| match container { - Container::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - frame.unwrap().contains_point(&mouse_position) - }) - .filter(|window| window.id() != moved_window.id()) - .collect(); - - if children_at_mouse_position.is_empty() { - return Ok(()); - } - - let window_under_cursor = - children_at_mouse_position.into_iter().next().unwrap(); + let window_under_cursor = match get_window_at_mouse_pos(&moved_window, workspace, &mouse_position) { + Some(value) => value, + None => return Ok(()), + }; info!( - "Swapping {} with {}", + "Moved window: {:?} \n Target window: {:?}", moved_window .native() - .process_name() - .unwrap_or("".to_string()), + .process_name(), window_under_cursor .native() - .process_name() - .unwrap_or("".to_string()) + .process_name(), ); let tiling_direction = get_split_direction(&window_under_cursor)?; @@ -86,7 +70,7 @@ pub fn window_moved_end( match &parent { // If the parent is a workspace we only need to add the window to it or - // to create a VerticalSplitDirection + // to create a Vertical split container Container::Workspace(_) => { let current_tiling_direction = TilingDirection::Horizontal; move_window_to_target( @@ -101,7 +85,7 @@ pub fn window_moved_end( )?; } // If the parent is a split we need to check the current split - // direction add the window to it or create a VerticalSplitDirection + // direction add the window to it or create a [Vertical/Horizontal] split container Container::Split(split) => { let current_tiling_direction = split.tiling_direction(); move_window_to_target( @@ -122,6 +106,28 @@ pub fn window_moved_end( Ok(()) } +/// Return the window under the mouse position excluding the dragged window +fn get_window_at_mouse_pos(exclude_window: &NonTilingWindow, workspace: Workspace, mouse_position: &Point) -> Option { + let children_at_mouse_position: Vec<_> = workspace + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&mouse_position) + }) + .filter(|window| window.id() != exclude_window.id()) + .collect(); + + if children_at_mouse_position.is_empty() { + return None; + } + + children_at_mouse_position.into_iter().next() +} + fn move_window_to_target( state: &mut WmState, config: &UserConfig, @@ -245,6 +251,9 @@ enum DropPosition { End, } +/// Returns the closest position of the mouse over the window +/// +/// Example: Mouse x pos: 3, Window width: 5, Result: [DropPosition::End] fn get_new_window_position( mouse_position: &Point, window: &TilingWindow, @@ -271,6 +280,8 @@ fn get_new_window_position( } } } + +/// Returns the TilingDirection based on the window size fn get_split_direction( window: &TilingWindow, ) -> anyhow::Result { From 141422999ca0105f93bb4d9d980ddbecb6fccc7c Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 19:25:47 +0200 Subject: [PATCH 15/35] fix: bug of moving window when alone in split --- .../common/events/handle_window_moved_end.rs | 17 ++++++++++------- .../events/handle_window_moved_start.rs | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index d68f30dfb..7214e81c6 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -15,6 +15,7 @@ use crate::{ wm_state::WmState, }; use crate::containers::commands::detach_container; +use crate::containers::RootContainer; use crate::user_config::FloatingStateConfig; use crate::workspaces::Workspace; @@ -36,13 +37,11 @@ pub fn window_moved_end( } info!("Tiling window drag end event"); - let workspace = moved_window - .workspace() - .context("Couldn't find a workspace")?; + let root_container = state.root_container.clone(); let mouse_position = Platform::mouse_position()?; - let window_under_cursor = match get_window_at_mouse_pos(&moved_window, workspace, &mouse_position) { + let window_under_cursor = match get_tiling_window_at_mouse_pos(&moved_window, root_container, &mouse_position) { Some(value) => value, None => return Ok(()), }; @@ -107,8 +106,8 @@ pub fn window_moved_end( } /// Return the window under the mouse position excluding the dragged window -fn get_window_at_mouse_pos(exclude_window: &NonTilingWindow, workspace: Workspace, mouse_position: &Point) -> Option { - let children_at_mouse_position: Vec<_> = workspace +fn get_tiling_window_at_mouse_pos(exclude_window: &NonTilingWindow, root_container: RootContainer, mouse_position: &Point) -> Option { + let children_at_mouse_position: Vec<_> = root_container .descendants() .filter_map(|container| match container { Container::TilingWindow(tiling) => Some(tiling), @@ -141,9 +140,13 @@ fn move_window_to_target( // TODO: We can optimize that for sure by not detaching and attaching the window // Little trick to get the right index + let test_parent = moved_window.parent().unwrap(); + dbg!(&test_parent); detach_container(Container::NonTilingWindow(moved_window.clone()))?; + dbg!(&test_parent); let target_window_index = target_window.index(); attach_container(&Container::NonTilingWindow(moved_window.clone()), target_window_parent, None)?; + dbg!(&test_parent); let target_index = match new_window_position { DropPosition::Start => target_window_index, @@ -252,7 +255,7 @@ enum DropPosition { } /// Returns the closest position of the mouse over the window -/// +/// /// Example: Mouse x pos: 3, Window width: 5, Result: [DropPosition::End] fn get_new_window_position( mouse_position: &Point, diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index 19c2f4603..b2415c5ae 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -2,7 +2,11 @@ use anyhow::Context; use tracing::info; use crate::{ - containers::traits::CommonGetters, + containers::{ + commands::{attach_container, detach_container}, + traits::CommonGetters, + Container, + }, user_config::{FloatingStateConfig, UserConfig}, windows::{commands::update_window_state, TilingWindow, WindowState}, wm_state::WmState, @@ -19,6 +23,19 @@ pub fn window_moved_start( .parent() .context("Tiling window has no parent")?; + if let Some(Container::Split(split)) = moved_window.parent() { + if split.child_count() == 1 { + let split_parent = split.parent().unwrap(); + let split_index = split.index(); + detach_container(Container::TilingWindow(moved_window.clone()))?; + attach_container( + &Container::TilingWindow(moved_window.clone()), + &split_parent, + Some(split_index), + )?; + } + } + update_window_state( moved_window.as_window_container().unwrap(), WindowState::Floating(FloatingStateConfig { From 74ff51ea6f5833f99d712fef26573b31f23445a9 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 21:45:21 +0200 Subject: [PATCH 16/35] fix: bug window not splitting in the right place --- .../common/events/handle_window_moved_end.rs | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 7214e81c6..967bc3cc9 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -137,22 +137,6 @@ fn move_window_to_target( new_tiling_direction: TilingDirection, new_window_position: DropPosition, ) -> anyhow::Result<()> { - - // TODO: We can optimize that for sure by not detaching and attaching the window - // Little trick to get the right index - let test_parent = moved_window.parent().unwrap(); - dbg!(&test_parent); - detach_container(Container::NonTilingWindow(moved_window.clone()))?; - dbg!(&test_parent); - let target_window_index = target_window.index(); - attach_container(&Container::NonTilingWindow(moved_window.clone()), target_window_parent, None)?; - dbg!(&test_parent); - - let target_index = match new_window_position { - DropPosition::Start => target_window_index, - DropPosition::End => target_window_index + 1, - }; - update_window_state( moved_window.as_window_container().unwrap(), WindowState::Tiling, @@ -160,16 +144,25 @@ fn move_window_to_target( config, )?; - let moved_window = state - .windows() - .iter() - .find(|w| w.id() == moved_window.id()) - .context("couldn't find the new tiled window")? - .as_tiling_window() - .context("window is not a tiled window")? - .clone(); + .windows() + .iter() + .find(|w| w.id() == moved_window.id()) + .context("couldn't find the new tiled window")? + .as_tiling_window() + .context("window is not a tiled window")? + .clone(); + + // TODO: We can optimize that for sure by not detaching and attaching the window + // Little trick to get the right index + detach_container(Container::TilingWindow(moved_window.clone()))?; + let target_window_index = target_window.index(); + attach_container(&Container::TilingWindow(moved_window.clone()), target_window_parent, None)?; + let target_index = match new_window_position { + DropPosition::Start => target_window_index, + DropPosition::End => target_window_index + 1, + }; match (new_tiling_direction, current_tiling_direction) { (TilingDirection::Horizontal, TilingDirection::Horizontal) From fc77d479eeffda32f25e94541834bb66edef9054 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 30 Jul 2024 22:11:32 +0200 Subject: [PATCH 17/35] fix: bug when dragged on no window --- .../wm/src/common/events/handle_window_moved_end.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 967bc3cc9..d67a6a47a 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -43,7 +43,10 @@ pub fn window_moved_end( let window_under_cursor = match get_tiling_window_at_mouse_pos(&moved_window, root_container, &mouse_position) { Some(value) => value, - None => return Ok(()), + None => { + update_window_state(moved_window.as_window_container().unwrap(), WindowState::Tiling, state, config)?; + return Ok(()); + }, }; info!( @@ -76,7 +79,7 @@ pub fn window_moved_end( state, config, moved_window, - window_under_cursor, + window_under_cursor.clone(), &parent, current_tiling_direction, tiling_direction, @@ -91,7 +94,7 @@ pub fn window_moved_end( state, config, moved_window, - window_under_cursor, + window_under_cursor.clone(), &parent, current_tiling_direction, tiling_direction, @@ -100,7 +103,7 @@ pub fn window_moved_end( } _ => {} } - state.pending_sync.containers_to_redraw.push(parent); + state.pending_sync.containers_to_redraw.push(Container::Workspace(window_under_cursor.workspace().unwrap())); Ok(()) } @@ -169,6 +172,7 @@ fn move_window_to_target( | (TilingDirection::Vertical, TilingDirection::Vertical) => { info!("Target window index {}", target_window_index); + dbg!(&target_window_parent); move_container_within_tree( Container::TilingWindow(moved_window.clone()), target_window_parent.clone(), From e26388602b0f7392837227b599a82accd5acfa54 Mon Sep 17 00:00:00 2001 From: Luca Date: Wed, 31 Jul 2024 18:58:51 +0200 Subject: [PATCH 18/35] feat: Deleting split when only 1 container in it --- .../events/handle_window_moved_start.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index b2415c5ae..88fd6f331 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -24,15 +24,20 @@ pub fn window_moved_start( .context("Tiling window has no parent")?; if let Some(Container::Split(split)) = moved_window.parent() { - if split.child_count() == 1 { + if split.child_count() == 2 { let split_parent = split.parent().unwrap(); let split_index = split.index(); - detach_container(Container::TilingWindow(moved_window.clone()))?; - attach_container( - &Container::TilingWindow(moved_window.clone()), - &split_parent, - Some(split_index), - )?; + let children = split.children(); + + // Looping in reversed order to reattach them in the right order + for child in children.into_iter().rev(){ + detach_container(child.clone())?; + attach_container( + &child, + &split_parent, + Some(split_index), + )?; + } } } From 3e988e8fd5c081f5afcd418243b2cb8750d57b1a Mon Sep 17 00:00:00 2001 From: Luca Date: Wed, 31 Jul 2024 22:08:04 +0200 Subject: [PATCH 19/35] feat: resizing with the mouse works as before --- .../events/handle_window_location_changed.rs | 102 +++++++++++++- .../common/events/handle_window_moved_end.rs | 131 ++++++++++-------- .../events/handle_window_moved_start.rs | 47 ++----- .../wm/src/windows/commands/manage_window.rs | 3 + packages/wm/src/windows/mod.rs | 1 + packages/wm/src/windows/non_tiling_window.rs | 5 + packages/wm/src/windows/tiling_window.rs | 5 + .../wm/src/windows/traits/window_getters.rs | 13 ++ packages/wm/src/windows/window_operation.rs | 14 ++ 9 files changed, 225 insertions(+), 96 deletions(-) create mode 100644 packages/wm/src/windows/window_operation.rs diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 7941a9cbc..2e876bd51 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -2,14 +2,20 @@ use anyhow::Context; use tracing::info; use crate::{ - common::platform::NativeWindow, + common::{platform::NativeWindow, Rect}, containers::{ - commands::move_container_within_tree, traits::CommonGetters, - WindowContainer, + commands::{ + attach_container, detach_container, move_container_within_tree, + }, + traits::{CommonGetters, PositionGetters}, + Container, WindowContainer, }, - user_config::{FullscreenStateConfig, UserConfig}, + user_config::{FloatingStateConfig, FullscreenStateConfig, UserConfig}, windows::{ - commands::update_window_state, traits::WindowGetters, WindowState, + commands::update_window_state, + traits::WindowGetters, + window_operation::{Operation, WindowOperation}, + TilingWindow, WindowState, }, wm_state::WmState, }; @@ -23,7 +29,17 @@ pub fn handle_window_location_changed( // Update the window's state to be fullscreen or toggled from fullscreen. if let Some(window) = found_window { - let frame_position = window.native().refresh_frame_position()?; + let frame_position: Rect = window.native().refresh_frame_position()?; + let old_frame_position: Rect = window.to_rect()?; + + update_window_operation( + state, + config, + &window, + &frame_position, + &old_frame_position, + )?; + let is_minimized = window.native().refresh_is_minimized()?; let old_is_maximized = window.native().is_maximized()?; @@ -131,3 +147,77 @@ pub fn handle_window_location_changed( Ok(()) } + +fn update_window_operation( + state: &mut WmState, + config: &UserConfig, + window: &WindowContainer, + frame_position: &Rect, + old_frame_position: &Rect, +) -> anyhow::Result<()> { + if let Some(tiling_window) = window.as_tiling_window() { + let window_operation = window.window_operation(); + if matches!( + window_operation, + WindowOperation { + operation: Operation::Waiting, + } + ) { + if frame_position.height() == old_frame_position.height() + && frame_position.width() == old_frame_position.width() + { + window.set_window_operation(WindowOperation { + operation: Operation::Moving, + ..window_operation + }); + set_into_floating(tiling_window.clone(), state, config)?; + } else { + window.set_window_operation(WindowOperation { + operation: Operation::Resizing, + ..window_operation + }); + } + } + } + Ok(()) +} + +fn set_into_floating( + moved_window: TilingWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + let moved_window_parent = moved_window + .parent() + .context("Tiling window has no parent")?; + + if let Some(Container::Split(split)) = moved_window.parent() { + if split.child_count() == 2 { + let split_parent = split.parent().unwrap(); + let split_index = split.index(); + let children = split.children(); + + // Looping in reversed order to reattach them in the right order + for child in children.into_iter().rev() { + detach_container(child.clone())?; + attach_container(&child, &split_parent, Some(split_index))?; + } + } + } + + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Floating(FloatingStateConfig { + centered: true, + shown_on_top: true, + is_tiling_drag: true, + }), + state, + config, + )?; + state + .pending_sync + .containers_to_redraw + .push(moved_window_parent); + Ok(()) +} diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index d67a6a47a..d02519ec0 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -1,23 +1,24 @@ use anyhow::Context; -use tracing::info; +use tracing::{debug, info}; + use crate::{ common::{platform::Platform, Point, TilingDirection}, containers::{ - commands::{attach_container, move_container_within_tree}, + commands::{ + attach_container, detach_container, move_container_within_tree, + }, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, SplitContainer, + Container, RootContainer, SplitContainer, }, - user_config::UserConfig, + user_config::{FloatingStateConfig, UserConfig}, windows::{ - commands::update_window_state, traits::WindowGetters, NonTilingWindow, - TilingWindow, WindowState, + commands::update_window_state, + traits::WindowGetters, + window_operation::{Operation, WindowOperation}, + NonTilingWindow, TilingWindow, WindowState, }, wm_state::WmState, }; -use crate::containers::commands::detach_container; -use crate::containers::RootContainer; -use crate::user_config::FloatingStateConfig; -use crate::workspaces::Workspace; /// Handles window move events pub fn window_moved_end( @@ -25,14 +26,17 @@ pub fn window_moved_end( state: &mut WmState, config: &UserConfig, ) -> anyhow::Result<()> { - // We continue only if it's a temporary Floating window + // We continue only if it's a temporary Floating window and if the window + // got moved and not resized if matches!( moved_window.state(), WindowState::Floating(FloatingStateConfig { is_tiling_drag: false, .. }) - ) { + ) || moved_window.window_operation().operation != Operation::Moving + { + moved_window.set_window_operation(WindowOperation::default()); return Ok(()); } info!("Tiling window drag end event"); @@ -41,22 +45,27 @@ pub fn window_moved_end( let mouse_position = Platform::mouse_position()?; - let window_under_cursor = match get_tiling_window_at_mouse_pos(&moved_window, root_container, &mouse_position) { + let window_under_cursor = match get_tiling_window_at_mouse_pos( + &moved_window, + root_container, + &mouse_position, + ) { Some(value) => value, None => { - update_window_state(moved_window.as_window_container().unwrap(), WindowState::Tiling, state, config)?; + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Tiling, + state, + config, + )?; return Ok(()); - }, + } }; - info!( + debug!( "Moved window: {:?} \n Target window: {:?}", - moved_window - .native() - .process_name(), - window_under_cursor - .native() - .process_name(), + moved_window.native().process_name(), + window_under_cursor.native().process_name(), ); let tiling_direction = get_split_direction(&window_under_cursor)?; @@ -66,8 +75,6 @@ pub fn window_moved_end( &tiling_direction, )?; - info!("{:?} {:?}", tiling_direction, new_window_position); - let parent = window_under_cursor.parent().unwrap(); match &parent { @@ -78,7 +85,7 @@ pub fn window_moved_end( move_window_to_target( state, config, - moved_window, + moved_window.clone(), window_under_cursor.clone(), &parent, current_tiling_direction, @@ -87,13 +94,14 @@ pub fn window_moved_end( )?; } // If the parent is a split we need to check the current split - // direction add the window to it or create a [Vertical/Horizontal] split container + // direction add the window to it or create a [Vertical/Horizontal] + // split container Container::Split(split) => { let current_tiling_direction = split.tiling_direction(); move_window_to_target( state, config, - moved_window, + moved_window.clone(), window_under_cursor.clone(), &parent, current_tiling_direction, @@ -103,25 +111,35 @@ pub fn window_moved_end( } _ => {} } - state.pending_sync.containers_to_redraw.push(Container::Workspace(window_under_cursor.workspace().unwrap())); + moved_window.set_window_operation(WindowOperation::default()); + state + .pending_sync + .containers_to_redraw + .push(Container::Workspace( + window_under_cursor.workspace().unwrap(), + )); Ok(()) } /// Return the window under the mouse position excluding the dragged window -fn get_tiling_window_at_mouse_pos(exclude_window: &NonTilingWindow, root_container: RootContainer, mouse_position: &Point) -> Option { +fn get_tiling_window_at_mouse_pos( + exclude_window: &NonTilingWindow, + root_container: RootContainer, + mouse_position: &Point, +) -> Option { let children_at_mouse_position: Vec<_> = root_container - .descendants() - .filter_map(|container| match container { - Container::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - frame.unwrap().contains_point(&mouse_position) - }) - .filter(|window| window.id() != exclude_window.id()) - .collect(); + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&mouse_position) + }) + .filter(|window| window.id() != exclude_window.id()) + .collect(); if children_at_mouse_position.is_empty() { return None; @@ -148,19 +166,23 @@ fn move_window_to_target( )?; let moved_window = state - .windows() - .iter() - .find(|w| w.id() == moved_window.id()) - .context("couldn't find the new tiled window")? - .as_tiling_window() - .context("window is not a tiled window")? - .clone(); + .windows() + .iter() + .find(|w| w.id() == moved_window.id()) + .context("couldn't find the new tiled window")? + .as_tiling_window() + .context("window is not a tiled window")? + .clone(); - // TODO: We can optimize that for sure by not detaching and attaching the window - // Little trick to get the right index + // TODO: We can optimize that for sure by not detaching and attaching the + // window Little trick to get the right index detach_container(Container::TilingWindow(moved_window.clone()))?; let target_window_index = target_window.index(); - attach_container(&Container::TilingWindow(moved_window.clone()), target_window_parent, None)?; + attach_container( + &Container::TilingWindow(moved_window.clone()), + target_window_parent, + None, + )?; let target_index = match new_window_position { DropPosition::Start => target_window_index, @@ -170,9 +192,6 @@ fn move_window_to_target( match (new_tiling_direction, current_tiling_direction) { (TilingDirection::Horizontal, TilingDirection::Horizontal) | (TilingDirection::Vertical, TilingDirection::Vertical) => { - info!("Target window index {}", target_window_index); - - dbg!(&target_window_parent); move_container_within_tree( Container::TilingWindow(moved_window.clone()), target_window_parent.clone(), @@ -228,7 +247,11 @@ fn create_split_container( tiling_direction, config.value.gaps.inner_gap.clone(), )); - attach_container(&split_container, &parent, Some(split_container_index))?; + attach_container( + &split_container, + &parent, + Some(split_container_index), + )?; move_container_within_tree( Container::TilingWindow(target_window), diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs index 88fd6f331..611d7f847 100644 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_start.rs @@ -8,7 +8,14 @@ use crate::{ Container, }, user_config::{FloatingStateConfig, UserConfig}, - windows::{commands::update_window_state, TilingWindow, WindowState}, + windows::{ + commands::update_window_state, + traits::WindowGetters, + window_operation::{ + Operation, WindowOperation, + }, + TilingWindow, WindowState, + }, wm_state::WmState, }; @@ -19,41 +26,9 @@ pub fn window_moved_start( config: &UserConfig, ) -> anyhow::Result<()> { info!("Tiling window drag start"); - let moved_window_parent = moved_window - .parent() - .context("Tiling window has no parent")?; - - if let Some(Container::Split(split)) = moved_window.parent() { - if split.child_count() == 2 { - let split_parent = split.parent().unwrap(); - let split_index = split.index(); - let children = split.children(); - - // Looping in reversed order to reattach them in the right order - for child in children.into_iter().rev(){ - detach_container(child.clone())?; - attach_container( - &child, - &split_parent, - Some(split_index), - )?; - } - } - } - update_window_state( - moved_window.as_window_container().unwrap(), - WindowState::Floating(FloatingStateConfig { - centered: true, - shown_on_top: true, - is_tiling_drag: true, - }), - state, - config, - )?; - state - .pending_sync - .containers_to_redraw - .push(moved_window_parent); + moved_window.set_window_operation(WindowOperation { + operation: Operation::Waiting + }); Ok(()) } diff --git a/packages/wm/src/windows/commands/manage_window.rs b/packages/wm/src/windows/commands/manage_window.rs index 8a0f4b50b..694c7ee7c 100644 --- a/packages/wm/src/windows/commands/manage_window.rs +++ b/packages/wm/src/windows/commands/manage_window.rs @@ -17,6 +17,7 @@ use crate::{ wm_event::WmEvent, wm_state::WmState, }; +use crate::windows::window_operation::WindowOperation; pub fn manage_window( native_window: NativeWindow, @@ -133,6 +134,7 @@ fn create_window( floating_placement, inner_gap, Vec::new(), + WindowOperation::default(), ) .into(), _ => NonTilingWindow::new( @@ -144,6 +146,7 @@ fn create_window( None, floating_placement, Vec::new(), + WindowOperation::default(), ) .into(), }; diff --git a/packages/wm/src/windows/mod.rs b/packages/wm/src/windows/mod.rs index 218da5bc1..d3de25a8f 100644 --- a/packages/wm/src/windows/mod.rs +++ b/packages/wm/src/windows/mod.rs @@ -4,6 +4,7 @@ mod tiling_window; pub mod traits; mod window_dto; mod window_state; +pub mod window_operation; pub use non_tiling_window::*; pub use tiling_window::*; diff --git a/packages/wm/src/windows/non_tiling_window.rs b/packages/wm/src/windows/non_tiling_window.rs index 2607a95dc..177e1d6a5 100644 --- a/packages/wm/src/windows/non_tiling_window.rs +++ b/packages/wm/src/windows/non_tiling_window.rs @@ -19,6 +19,7 @@ use crate::{ }, impl_common_getters, impl_container_debug, impl_window_getters, user_config::WindowRuleConfig, + windows::window_operation::WindowOperation, }; #[derive(Clone)] @@ -38,6 +39,7 @@ struct NonTilingWindowInner { has_pending_dpi_adjustment: bool, floating_placement: Rect, done_window_rules: Vec, + window_operation: WindowOperation, } impl NonTilingWindow { @@ -50,6 +52,7 @@ impl NonTilingWindow { insertion_target: Option<(Container, usize)>, floating_placement: Rect, done_window_rules: Vec, + window_operation: WindowOperation, ) -> Self { let window = NonTilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), @@ -65,6 +68,7 @@ impl NonTilingWindow { has_pending_dpi_adjustment: false, floating_placement, done_window_rules, + window_operation, }; Self(Rc::new(RefCell::new(window))) @@ -90,6 +94,7 @@ impl NonTilingWindow { self.floating_placement(), inner_gap, self.done_window_rules(), + self.window_operation() ) } diff --git a/packages/wm/src/windows/tiling_window.rs b/packages/wm/src/windows/tiling_window.rs index a9c8193f0..abfc560c8 100644 --- a/packages/wm/src/windows/tiling_window.rs +++ b/packages/wm/src/windows/tiling_window.rs @@ -28,6 +28,7 @@ use crate::{ impl_window_getters, user_config::WindowRuleConfig, }; +use crate::windows::window_operation::WindowOperation; #[derive(Clone)] pub struct TilingWindow(Rc>); @@ -47,6 +48,7 @@ struct TilingWindowInner { floating_placement: Rect, inner_gap: LengthValue, done_window_rules: Vec, + window_operation: WindowOperation, } impl TilingWindow { @@ -58,6 +60,7 @@ impl TilingWindow { floating_placement: Rect, inner_gap: LengthValue, done_window_rules: Vec, + window_operation: WindowOperation, ) -> Self { let window = TilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), @@ -74,6 +77,7 @@ impl TilingWindow { floating_placement, inner_gap, done_window_rules, + window_operation, }; Self(Rc::new(RefCell::new(window))) @@ -93,6 +97,7 @@ impl TilingWindow { insertion_target, self.floating_placement(), self.done_window_rules(), + self.window_operation(), ) } diff --git a/packages/wm/src/windows/traits/window_getters.rs b/packages/wm/src/windows/traits/window_getters.rs index c3fe190bf..28a513bdf 100644 --- a/packages/wm/src/windows/traits/window_getters.rs +++ b/packages/wm/src/windows/traits/window_getters.rs @@ -10,6 +10,7 @@ use crate::{ user_config::{UserConfig, WindowRuleConfig}, windows::WindowState, }; +use crate::windows::window_operation::WindowOperation; #[enum_dispatch] pub trait WindowGetters { @@ -108,6 +109,10 @@ pub trait WindowGetters { &self, done_window_rules: Vec, ); + + fn window_operation(&self) -> WindowOperation; + + fn set_window_operation(&self, window_operation: WindowOperation); } /// Implements the `WindowGetters` trait for a given struct. @@ -185,6 +190,14 @@ macro_rules! impl_window_getters { ) { self.0.borrow_mut().done_window_rules = done_window_rules; } + + fn window_operation(&self) -> WindowOperation{ + self.0.borrow().window_operation.clone() + } + + fn set_window_operation(&self, window_operation: WindowOperation) { + self.0.borrow_mut().window_operation = window_operation; + } } }; } diff --git a/packages/wm/src/windows/window_operation.rs b/packages/wm/src/windows/window_operation.rs new file mode 100644 index 000000000..66b405cc8 --- /dev/null +++ b/packages/wm/src/windows/window_operation.rs @@ -0,0 +1,14 @@ +#[derive(Debug, Clone, Default)] +pub struct WindowOperation{ + pub operation: Operation, + +} + +#[derive(Debug, Copy, Clone, Default, PartialEq)] +pub enum Operation{ + #[default] + None, + Waiting, + Moving, + Resizing, +} From 30cadf000d4efbe2293c7d2efc21b901f8bfcba4 Mon Sep 17 00:00:00 2001 From: Luca Date: Wed, 31 Jul 2024 23:43:38 +0200 Subject: [PATCH 20/35] refactor: get containers mouse position --- .../common/events/handle_window_moved_end.rs | 35 ++++++++----------- .../commands/get_containers_at_pos.rs | 32 +++++++++++++++++ packages/wm/src/containers/commands/mod.rs | 2 ++ 3 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 packages/wm/src/containers/commands/get_containers_at_pos.rs diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index d02519ec0..7c95cdd33 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -5,7 +5,8 @@ use crate::{ common::{platform::Platform, Point, TilingDirection}, containers::{ commands::{ - attach_container, detach_container, move_container_within_tree, + attach_container, detach_container, get_containers_at_position, + move_container_within_tree, }, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, Container, RootContainer, SplitContainer, @@ -19,6 +20,7 @@ use crate::{ }, wm_state::WmState, }; +use crate::containers::WindowContainer; /// Handles window move events pub fn window_moved_end( @@ -41,14 +43,12 @@ pub fn window_moved_end( } info!("Tiling window drag end event"); - let root_container = state.root_container.clone(); - let mouse_position = Platform::mouse_position()?; let window_under_cursor = match get_tiling_window_at_mouse_pos( &moved_window, - root_container, &mouse_position, + state, ) { Some(value) => value, None => { @@ -125,25 +125,18 @@ pub fn window_moved_end( /// Return the window under the mouse position excluding the dragged window fn get_tiling_window_at_mouse_pos( exclude_window: &NonTilingWindow, - root_container: RootContainer, mouse_position: &Point, + state: &WmState, ) -> Option { - let children_at_mouse_position: Vec<_> = root_container - .descendants() - .filter_map(|container| match container { - Container::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - frame.unwrap().contains_point(&mouse_position) - }) - .filter(|window| window.id() != exclude_window.id()) - .collect(); - - if children_at_mouse_position.is_empty() { - return None; - } + let children_at_mouse_position: Vec = + get_containers_at_position(state, mouse_position) + .into_iter() + .filter_map(|container| match container { + WindowContainer::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|window: &TilingWindow| window.id() != exclude_window.id()) + .collect(); children_at_mouse_position.into_iter().next() } diff --git a/packages/wm/src/containers/commands/get_containers_at_pos.rs b/packages/wm/src/containers/commands/get_containers_at_pos.rs new file mode 100644 index 000000000..c2afd19be --- /dev/null +++ b/packages/wm/src/containers/commands/get_containers_at_pos.rs @@ -0,0 +1,32 @@ +use crate::{ + common::Point, + containers::{ + traits::{CommonGetters, PositionGetters}, + Container, WindowContainer, + }, + wm_state::WmState, +}; + +/// Return all window under the mouse position +pub fn get_containers_at_position( + state: &WmState, + position: &Point, +) -> Vec { + state + .root_container + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => { + Some(WindowContainer::TilingWindow(tiling)) + } + Container::NonTilingWindow(non_tiling) => { + Some(WindowContainer::NonTilingWindow(non_tiling)) + } + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&position) + }) + .collect() +} diff --git a/packages/wm/src/containers/commands/mod.rs b/packages/wm/src/containers/commands/mod.rs index b42854eb2..4f0627379 100644 --- a/packages/wm/src/containers/commands/mod.rs +++ b/packages/wm/src/containers/commands/mod.rs @@ -9,6 +9,7 @@ mod resize_tiling_container; mod set_focused_descendant; mod toggle_tiling_direction; mod wrap_in_split_container; +mod get_containers_at_pos; pub use attach_container::*; pub use detach_container::*; @@ -21,3 +22,4 @@ pub use resize_tiling_container::*; pub use set_focused_descendant::*; pub use toggle_tiling_direction::*; pub use wrap_in_split_container::*; +pub use get_containers_at_pos::*; From 5e06c97eb56d9eddaa141f3bb973b23c7bc8d8ac Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 00:05:14 +0200 Subject: [PATCH 21/35] feat: doc comments --- .../common/events/handle_window_moved_end.rs | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 7c95cdd33..d36768027 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -9,7 +9,7 @@ use crate::{ move_container_within_tree, }, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, RootContainer, SplitContainer, + Container, SplitContainer, WindowContainer, }, user_config::{FloatingStateConfig, UserConfig}, windows::{ @@ -20,7 +20,6 @@ use crate::{ }, wm_state::WmState, }; -use crate::containers::WindowContainer; /// Handles window move events pub fn window_moved_end( @@ -69,7 +68,7 @@ pub fn window_moved_end( ); let tiling_direction = get_split_direction(&window_under_cursor)?; - let new_window_position = get_new_window_position( + let new_window_position = get_drop_position( &mouse_position, &window_under_cursor, &tiling_direction, @@ -149,7 +148,7 @@ fn move_window_to_target( target_window_parent: &Container, current_tiling_direction: TilingDirection, new_tiling_direction: TilingDirection, - new_window_position: DropPosition, + drop_position: DropPosition, ) -> anyhow::Result<()> { update_window_state( moved_window.as_window_container().unwrap(), @@ -167,8 +166,8 @@ fn move_window_to_target( .context("window is not a tiled window")? .clone(); - // TODO: We can optimize that for sure by not detaching and attaching the - // window Little trick to get the right index + // TODO: We can optimize that by not detaching and attaching the window + // Little trick to get the right index detach_container(Container::TilingWindow(moved_window.clone()))?; let target_window_index = target_window.index(); attach_container( @@ -177,7 +176,7 @@ fn move_window_to_target( None, )?; - let target_index = match new_window_position { + let target_index = match drop_position { DropPosition::Start => target_window_index, DropPosition::End => target_window_index + 1, }; @@ -199,7 +198,7 @@ fn move_window_to_target( config, moved_window, target_window, - new_window_position, + drop_position, &target_window_parent, target_index, )?; @@ -211,7 +210,7 @@ fn move_window_to_target( config, moved_window, target_window, - new_window_position, + drop_position, &target_window_parent, target_index, )?; @@ -221,6 +220,8 @@ fn move_window_to_target( Ok(()) } +/// Creates a split container and moves the target window and the moved +/// window inside at the dropped position fn create_split_container( tiling_direction: TilingDirection, state: &mut WmState, @@ -261,16 +262,24 @@ fn create_split_container( Ok(()) } +/// Represents where the window was dropped over another one. +/// It depends on the tiling direction. +/// +/// [DropPosition::Start] can either be the top or left side. +/// [DropPosition::Stop] can either be bottom or right side. #[derive(Debug)] enum DropPosition { Start, End, } -/// Returns the closest position of the mouse over the window +/// Determines the drop position for a window based on the mouse position +/// and tiling direction. /// -/// Example: Mouse x pos: 3, Window width: 5, Result: [DropPosition::End] -fn get_new_window_position( +/// This function calculates whether a window should be dropped at the +/// start or end of a tiling layout, depending on the mouse position +/// relative to the middle of the target window. +fn get_drop_position( mouse_position: &Point, window: &TilingWindow, tiling_direction: &TilingDirection, @@ -297,7 +306,10 @@ fn get_new_window_position( } } -/// Returns the TilingDirection based on the window size +/// Determines the optimal split direction for a given window. +/// +/// This function decides whether a window should be split vertically or +/// horizontally based on its current dimensions. fn get_split_direction( window: &TilingWindow, ) -> anyhow::Result { From d5e7a7b3869748022ab403dc2e45cd581ffb6a31 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 00:13:25 +0200 Subject: [PATCH 22/35] refactor --- .../handle_window_moved_or_resized_end.rs | 30 +++------ .../handle_window_moved_or_resized_start.rs | 61 +++---------------- .../events/handle_window_moved_start.rs | 34 ----------- .../events/handle_window_resized_end.rs | 21 +++++++ packages/wm/src/common/events/mod.rs | 2 +- packages/wm/src/wm.rs | 2 +- 6 files changed, 40 insertions(+), 110 deletions(-) delete mode 100644 packages/wm/src/common/events/handle_window_moved_start.rs create mode 100644 packages/wm/src/common/events/handle_window_resized_end.rs diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index f55926d9d..31115e1e8 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -1,26 +1,26 @@ use anyhow::Context; -use tracing::info; use crate::{ common::{ - events::handle_window_moved_end::window_moved_end, - platform::NativeWindow, LengthValue, + events::{ + handle_window_moved_end::window_moved_end, + handle_window_resized_end::window_resized_end, + }, + platform::NativeWindow, }, containers::{ traits::{CommonGetters, PositionGetters}, WindowContainer, }, user_config::UserConfig, - windows::{ - commands::resize_window, traits::WindowGetters, TilingWindow, - }, + windows::traits::WindowGetters, wm_state::WmState, }; /// Handles the event for when a window is finished being moved or resized /// by the user (e.g. via the window's drag handles). /// -/// This resizes the window if it's a tiling window. +/// This resizes the window if it's a tiling window and attach a dragged floating window. pub fn handle_window_moved_or_resized_end( native_window: NativeWindow, state: &mut WmState, @@ -61,19 +61,3 @@ pub fn handle_window_moved_or_resized_end( Ok(()) } - -/// Handles window resize events -fn window_resized_end( - window: TilingWindow, - state: &mut WmState, - width_delta: i32, - height_delta: i32, -) -> anyhow::Result<()> { - info!("Tiling window resized"); - resize_window( - window.clone().into(), - Some(LengthValue::from_px(width_delta)), - Some(LengthValue::from_px(height_delta)), - state, - ) -} diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index dd0b6ecd4..bf3ba699f 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -1,67 +1,26 @@ -use anyhow::Context; -use tracing::info; - use crate::{ - common::{ - events::handle_window_moved_start::window_moved_start, - platform::NativeWindow, - }, - containers::{ - traits::{CommonGetters, PositionGetters}, - WindowContainer, + common::platform::NativeWindow, + containers::WindowContainer, + windows::{ + traits::WindowGetters, + window_operation::{Operation, WindowOperation}, }, - user_config::UserConfig, - windows::traits::WindowGetters, wm_state::WmState, }; -/// Handles the event for when a window is finished being moved or resized +/// Handles the event for when a window is started being moved or resized /// by the user (e.g. via the window's drag handles). -/// -/// This resizes the window if it's a tiling window. pub fn handle_window_moved_or_resized_start( native_window: NativeWindow, state: &mut WmState, - config: &UserConfig, ) -> anyhow::Result<()> { let found_window = state.window_from_native(&native_window); - if let Some(WindowContainer::TilingWindow(window)) = found_window { - // TODO: Log window details. - - let parent = window.parent().context("No parent.")?; - - // Snap window to its original position if it's the only window in the - // workspace. - if parent.is_workspace() && window.tiling_siblings().count() == 0 { - state.pending_sync.containers_to_redraw.push(window.into()); - return Ok(()); - } - - let new_rect = window.native().refresh_frame_position()?; - let old_rect = window.to_rect()?; - - - // TODO: This method to check if the window was resized or moved doesn't work. We need to find an alternative - let width_delta = new_rect.width() - old_rect.width(); - let height_delta = new_rect.height() - old_rect.height(); - - let has_window_moved = match (width_delta, height_delta) { - (0, 0) => true, - _ => false, - }; - - return match has_window_moved { - true => window_moved_start(window, state, config), - false => window_resized_start(), - }; + if let Some(WindowContainer::TilingWindow(moved_window)) = found_window { + moved_window.set_window_operation(WindowOperation { + operation: Operation::Waiting, + }); } Ok(()) } - -/// Handles window resize events -fn window_resized_start() -> anyhow::Result<()> { - info!("Tiling window resize start"); - Ok(()) -} diff --git a/packages/wm/src/common/events/handle_window_moved_start.rs b/packages/wm/src/common/events/handle_window_moved_start.rs deleted file mode 100644 index 611d7f847..000000000 --- a/packages/wm/src/common/events/handle_window_moved_start.rs +++ /dev/null @@ -1,34 +0,0 @@ -use anyhow::Context; -use tracing::info; - -use crate::{ - containers::{ - commands::{attach_container, detach_container}, - traits::CommonGetters, - Container, - }, - user_config::{FloatingStateConfig, UserConfig}, - windows::{ - commands::update_window_state, - traits::WindowGetters, - window_operation::{ - Operation, WindowOperation, - }, - TilingWindow, WindowState, - }, - wm_state::WmState, -}; - -/// Handles window move events -pub fn window_moved_start( - moved_window: TilingWindow, - state: &mut WmState, - config: &UserConfig, -) -> anyhow::Result<()> { - info!("Tiling window drag start"); - - moved_window.set_window_operation(WindowOperation { - operation: Operation::Waiting - }); - Ok(()) -} diff --git a/packages/wm/src/common/events/handle_window_resized_end.rs b/packages/wm/src/common/events/handle_window_resized_end.rs new file mode 100644 index 000000000..d0a494dce --- /dev/null +++ b/packages/wm/src/common/events/handle_window_resized_end.rs @@ -0,0 +1,21 @@ +use tracing::info; +use crate::common::LengthValue; +use crate::windows::commands::resize_window; +use crate::windows::TilingWindow; +use crate::wm_state::WmState; + +/// Handles window resize events +pub fn window_resized_end( + window: TilingWindow, + state: &mut WmState, + width_delta: i32, + height_delta: i32, +) -> anyhow::Result<()> { + info!("Tiling window resized"); + resize_window( + window.clone().into(), + Some(LengthValue::from_px(width_delta)), + Some(LengthValue::from_px(height_delta)), + state, + ) +} diff --git a/packages/wm/src/common/events/mod.rs b/packages/wm/src/common/events/mod.rs index 2fb315544..4691c006a 100644 --- a/packages/wm/src/common/events/mod.rs +++ b/packages/wm/src/common/events/mod.rs @@ -10,8 +10,8 @@ mod handle_window_moved_end; mod handle_window_moved_or_resized_end; mod handle_window_shown; mod handle_window_title_changed; -mod handle_window_moved_start; mod handle_window_moved_or_resized_start; +mod handle_window_resized_end; pub use handle_display_settings_changed::*; pub use handle_mouse_move::*; diff --git a/packages/wm/src/wm.rs b/packages/wm/src/wm.rs index 39d9b6912..a5c7978a9 100644 --- a/packages/wm/src/wm.rs +++ b/packages/wm/src/wm.rs @@ -86,7 +86,7 @@ impl WindowManager { handle_window_moved_or_resized_end(window, state, config) } PlatformEvent::WindowMovedOrResizedStart(window) => { - handle_window_moved_or_resized_start(window, state, config) + handle_window_moved_or_resized_start(window, state) } PlatformEvent::WindowShown(window) => { handle_window_shown(window, state, config) From 5c8b85fe1c0152977101f141fe5f6c993988823c Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 00:20:16 +0200 Subject: [PATCH 23/35] comments --- .../src/common/events/handle_window_location_changed.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 2e876bd51..62a7487a2 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -148,6 +148,10 @@ pub fn handle_window_location_changed( Ok(()) } +/// Updates the window operation based on changes in frame position. +/// +/// This function determines whether a window is being moved or resized and updates its +/// operation state accordingly. If the window is being moved, it's set to floating mode. fn update_window_operation( state: &mut WmState, config: &UserConfig, @@ -182,6 +186,10 @@ fn update_window_operation( Ok(()) } +/// Converts a tiling window to a floating window and updates the window hierarchy. +/// +/// This function handles the process of transitioning a tiling window to a floating state, +/// including necessary adjustments to the window hierarchy and updating the window's state. fn set_into_floating( moved_window: TilingWindow, state: &mut WmState, From e195c2813a9435c5823ae98f1f433f7b67eb7e53 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 00:23:48 +0200 Subject: [PATCH 24/35] refactor: simplified code --- .../events/handle_window_location_changed.rs | 36 +++++++------------ .../common/events/handle_window_moved_end.rs | 4 +-- .../handle_window_moved_or_resized_end.rs | 5 +-- .../handle_window_moved_or_resized_start.rs | 6 ++-- packages/wm/src/windows/window_operation.rs | 8 +---- 5 files changed, 19 insertions(+), 40 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 62a7487a2..af0c085cb 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -12,10 +12,8 @@ use crate::{ }, user_config::{FloatingStateConfig, FullscreenStateConfig, UserConfig}, windows::{ - commands::update_window_state, - traits::WindowGetters, - window_operation::{Operation, WindowOperation}, - TilingWindow, WindowState, + commands::update_window_state, traits::WindowGetters, + window_operation::WindowOperation, TilingWindow, WindowState, }, wm_state::WmState, }; @@ -150,8 +148,9 @@ pub fn handle_window_location_changed( /// Updates the window operation based on changes in frame position. /// -/// This function determines whether a window is being moved or resized and updates its -/// operation state accordingly. If the window is being moved, it's set to floating mode. +/// This function determines whether a window is being moved or resized and +/// updates its operation state accordingly. If the window is being moved, +/// it's set to floating mode. fn update_window_operation( state: &mut WmState, config: &UserConfig, @@ -161,35 +160,26 @@ fn update_window_operation( ) -> anyhow::Result<()> { if let Some(tiling_window) = window.as_tiling_window() { let window_operation = window.window_operation(); - if matches!( - window_operation, - WindowOperation { - operation: Operation::Waiting, - } - ) { + if window_operation == WindowOperation::Waiting { if frame_position.height() == old_frame_position.height() && frame_position.width() == old_frame_position.width() { - window.set_window_operation(WindowOperation { - operation: Operation::Moving, - ..window_operation - }); + window.set_window_operation(WindowOperation::Moving); set_into_floating(tiling_window.clone(), state, config)?; } else { - window.set_window_operation(WindowOperation { - operation: Operation::Resizing, - ..window_operation - }); + window.set_window_operation(WindowOperation::Resizing); } } } Ok(()) } -/// Converts a tiling window to a floating window and updates the window hierarchy. +/// Converts a tiling window to a floating window and updates the window +/// hierarchy. /// -/// This function handles the process of transitioning a tiling window to a floating state, -/// including necessary adjustments to the window hierarchy and updating the window's state. +/// This function handles the process of transitioning a tiling window to a +/// floating state, including necessary adjustments to the window hierarchy +/// and updating the window's state. fn set_into_floating( moved_window: TilingWindow, state: &mut WmState, diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index d36768027..138ec493b 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -15,7 +15,7 @@ use crate::{ windows::{ commands::update_window_state, traits::WindowGetters, - window_operation::{Operation, WindowOperation}, + window_operation::{WindowOperation}, NonTilingWindow, TilingWindow, WindowState, }, wm_state::WmState, @@ -35,7 +35,7 @@ pub fn window_moved_end( is_tiling_drag: false, .. }) - ) || moved_window.window_operation().operation != Operation::Moving + ) || moved_window.window_operation() != WindowOperation::Moving { moved_window.set_window_operation(WindowOperation::default()); return Ok(()); diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index 31115e1e8..869ec6485 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -46,10 +46,7 @@ pub fn handle_window_moved_or_resized_end( let height_delta = new_rect.height() - old_rect.height(); if let WindowContainer::NonTilingWindow(window) = window { - let has_window_moved = match (width_delta, height_delta) { - (0, 0) => true, - _ => false, - }; + let has_window_moved = matches!((width_delta, height_delta), (0,0)); if has_window_moved { window_moved_end(window, state, config)?; diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index bf3ba699f..69f12803c 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -3,7 +3,7 @@ use crate::{ containers::WindowContainer, windows::{ traits::WindowGetters, - window_operation::{Operation, WindowOperation}, + window_operation::{WindowOperation}, }, wm_state::WmState, }; @@ -17,9 +17,7 @@ pub fn handle_window_moved_or_resized_start( let found_window = state.window_from_native(&native_window); if let Some(WindowContainer::TilingWindow(moved_window)) = found_window { - moved_window.set_window_operation(WindowOperation { - operation: Operation::Waiting, - }); + moved_window.set_window_operation(WindowOperation::Waiting); } Ok(()) diff --git a/packages/wm/src/windows/window_operation.rs b/packages/wm/src/windows/window_operation.rs index 66b405cc8..cc469b5b0 100644 --- a/packages/wm/src/windows/window_operation.rs +++ b/packages/wm/src/windows/window_operation.rs @@ -1,11 +1,5 @@ -#[derive(Debug, Clone, Default)] -pub struct WindowOperation{ - pub operation: Operation, - -} - #[derive(Debug, Copy, Clone, Default, PartialEq)] -pub enum Operation{ +pub enum WindowOperation{ #[default] None, Waiting, From 5aa1bc856bc76b57f04e060d03d02d9a289b6503 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 11:46:48 +0200 Subject: [PATCH 25/35] fix: pr review --- packages/wm/src/app_command.rs | 2 - .../events/handle_window_location_changed.rs | 22 +++++++---- .../common/events/handle_window_moved_end.rs | 24 ++++++------ .../handle_window_moved_or_resized_start.rs | 6 ++- packages/wm/src/user_config.rs | 4 -- packages/wm/src/windows/active_drag.rs | 12 ++++++ .../wm/src/windows/commands/manage_window.rs | 37 ++++++++++--------- packages/wm/src/windows/mod.rs | 3 +- packages/wm/src/windows/non_tiling_window.rs | 27 +++++++------- packages/wm/src/windows/tiling_window.rs | 24 ++++++------ .../wm/src/windows/traits/window_getters.rs | 19 +++++----- packages/wm/src/windows/window_operation.rs | 8 ---- 12 files changed, 98 insertions(+), 90 deletions(-) create mode 100644 packages/wm/src/windows/active_drag.rs delete mode 100644 packages/wm/src/windows/window_operation.rs diff --git a/packages/wm/src/app_command.rs b/packages/wm/src/app_command.rs index 19aa44dc6..95a59a72d 100644 --- a/packages/wm/src/app_command.rs +++ b/packages/wm/src/app_command.rs @@ -404,7 +404,6 @@ impl InvokeCommand { centered: centered.unwrap_or(floating_defaults.centered), shown_on_top: shown_on_top .unwrap_or(floating_defaults.shown_on_top), - is_tiling_drag: false, }), state, config, @@ -494,7 +493,6 @@ impl InvokeCommand { centered: centered.unwrap_or(floating_defaults.centered), shown_on_top: shown_on_top .unwrap_or(floating_defaults.shown_on_top), - is_tiling_drag: false, }); update_window_state( diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index af0c085cb..4bd7ab802 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -12,8 +12,10 @@ use crate::{ }, user_config::{FloatingStateConfig, FullscreenStateConfig, UserConfig}, windows::{ - commands::update_window_state, traits::WindowGetters, - window_operation::WindowOperation, TilingWindow, WindowState, + commands::update_window_state, + traits::WindowGetters, + active_drag::{ActiveDrag, ActiveDragOperation}, + TilingWindow, WindowState, }, wm_state::WmState, }; @@ -159,15 +161,18 @@ fn update_window_operation( old_frame_position: &Rect, ) -> anyhow::Result<()> { if let Some(tiling_window) = window.as_tiling_window() { - let window_operation = window.window_operation(); - if window_operation == WindowOperation::Waiting { + let mut active_drag: ActiveDrag = tiling_window.active_drag(); + if matches!(active_drag.operation, Some(ActiveDragOperation::Waiting)) + { if frame_position.height() == old_frame_position.height() && frame_position.width() == old_frame_position.width() { - window.set_window_operation(WindowOperation::Moving); + active_drag.operation = Some(ActiveDragOperation::Moving); + tiling_window.set_active_drag(active_drag); set_into_floating(tiling_window.clone(), state, config)?; } else { - window.set_window_operation(WindowOperation::Resizing); + active_drag.operation = Some(ActiveDragOperation::Resizing); + tiling_window.set_active_drag(active_drag); } } } @@ -203,12 +208,15 @@ fn set_into_floating( } } + let mut active_drag = moved_window.active_drag(); + active_drag.is_from_tiling = true; + moved_window.set_active_drag(active_drag); + update_window_state( moved_window.as_window_container().unwrap(), WindowState::Floating(FloatingStateConfig { centered: true, shown_on_top: true, - is_tiling_drag: true, }), state, config, diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 138ec493b..664c2b780 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -13,13 +13,12 @@ use crate::{ }, user_config::{FloatingStateConfig, UserConfig}, windows::{ - commands::update_window_state, - traits::WindowGetters, - window_operation::{WindowOperation}, - NonTilingWindow, TilingWindow, WindowState, + active_drag::ActiveDragOperation, commands::update_window_state, + traits::WindowGetters, NonTilingWindow, TilingWindow, WindowState, }, wm_state::WmState, }; +use crate::windows::ActiveDrag; /// Handles window move events pub fn window_moved_end( @@ -29,15 +28,12 @@ pub fn window_moved_end( ) -> anyhow::Result<()> { // We continue only if it's a temporary Floating window and if the window // got moved and not resized - if matches!( - moved_window.state(), - WindowState::Floating(FloatingStateConfig { - is_tiling_drag: false, - .. - }) - ) || moved_window.window_operation() != WindowOperation::Moving + let mut active_drag = moved_window.active_drag(); + if active_drag.is_from_tiling == false + || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) { - moved_window.set_window_operation(WindowOperation::default()); + active_drag.operation = None; + moved_window.set_active_drag(active_drag); return Ok(()); } info!("Tiling window drag end event"); @@ -110,7 +106,9 @@ pub fn window_moved_end( } _ => {} } - moved_window.set_window_operation(WindowOperation::default()); + + moved_window.set_active_drag(ActiveDrag::default()); + state .pending_sync .containers_to_redraw diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index 69f12803c..fc450566f 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -3,7 +3,7 @@ use crate::{ containers::WindowContainer, windows::{ traits::WindowGetters, - window_operation::{WindowOperation}, + active_drag::{ActiveDragOperation}, }, wm_state::WmState, }; @@ -17,7 +17,9 @@ pub fn handle_window_moved_or_resized_start( let found_window = state.window_from_native(&native_window); if let Some(WindowContainer::TilingWindow(moved_window)) = found_window { - moved_window.set_window_operation(WindowOperation::Waiting); + let mut active_drag = moved_window.active_drag(); + active_drag.operation = Some(ActiveDragOperation::Waiting); + moved_window.set_active_drag(active_drag); } Ok(()) diff --git a/packages/wm/src/user_config.rs b/packages/wm/src/user_config.rs index fcd679faa..ff824bc2b 100644 --- a/packages/wm/src/user_config.rs +++ b/packages/wm/src/user_config.rs @@ -449,10 +449,6 @@ pub struct FloatingStateConfig { /// Whether to show floating windows as always on top. #[serde(default = "default_bool::")] pub shown_on_top: bool, - - /// Whether the floating window was created with a drag. - #[serde(default = "default_bool::")] - pub is_tiling_drag: bool, } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] diff --git a/packages/wm/src/windows/active_drag.rs b/packages/wm/src/windows/active_drag.rs new file mode 100644 index 000000000..b0b966ae9 --- /dev/null +++ b/packages/wm/src/windows/active_drag.rs @@ -0,0 +1,12 @@ +#[derive(Debug, Clone, Default)] +pub struct ActiveDrag{ + pub operation: Option, + pub is_from_tiling: bool, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ActiveDragOperation { + Waiting, + Moving, + Resizing, +} diff --git a/packages/wm/src/windows/commands/manage_window.rs b/packages/wm/src/windows/commands/manage_window.rs index 694c7ee7c..c5a79365e 100644 --- a/packages/wm/src/windows/commands/manage_window.rs +++ b/packages/wm/src/windows/commands/manage_window.rs @@ -17,7 +17,8 @@ use crate::{ wm_event::WmEvent, wm_state::WmState, }; -use crate::windows::window_operation::WindowOperation; +use crate::windows::ActiveDrag; +use crate::windows::active_drag::ActiveDragOperation; pub fn manage_window( native_window: NativeWindow, @@ -127,26 +128,26 @@ fn create_window( let window_container: WindowContainer = match window_state { WindowState::Tiling => TilingWindow::new( - None, - native_window, - None, - border_delta, - floating_placement, - inner_gap, - Vec::new(), - WindowOperation::default(), + None, + native_window, + None, + border_delta, + floating_placement, + inner_gap, + Vec::new(), + ActiveDrag::default(), ) .into(), _ => NonTilingWindow::new( - None, - native_window, - window_state, - None, - border_delta, - None, - floating_placement, - Vec::new(), - WindowOperation::default(), + None, + native_window, + window_state, + None, + border_delta, + None, + floating_placement, + Vec::new(), + ActiveDrag::default(), ) .into(), }; diff --git a/packages/wm/src/windows/mod.rs b/packages/wm/src/windows/mod.rs index d3de25a8f..2508a6b11 100644 --- a/packages/wm/src/windows/mod.rs +++ b/packages/wm/src/windows/mod.rs @@ -4,9 +4,10 @@ mod tiling_window; pub mod traits; mod window_dto; mod window_state; -pub mod window_operation; +pub mod active_drag; pub use non_tiling_window::*; pub use tiling_window::*; pub use window_dto::*; pub use window_state::*; +pub use active_drag::*; diff --git a/packages/wm/src/windows/non_tiling_window.rs b/packages/wm/src/windows/non_tiling_window.rs index 177e1d6a5..5a818e702 100644 --- a/packages/wm/src/windows/non_tiling_window.rs +++ b/packages/wm/src/windows/non_tiling_window.rs @@ -19,8 +19,9 @@ use crate::{ }, impl_common_getters, impl_container_debug, impl_window_getters, user_config::WindowRuleConfig, - windows::window_operation::WindowOperation, + windows::active_drag::ActiveDragOperation, }; +use crate::windows::active_drag::ActiveDrag; #[derive(Clone)] pub struct NonTilingWindow(Rc>); @@ -39,20 +40,20 @@ struct NonTilingWindowInner { has_pending_dpi_adjustment: bool, floating_placement: Rect, done_window_rules: Vec, - window_operation: WindowOperation, + active_drag: ActiveDrag, } impl NonTilingWindow { pub fn new( - id: Option, - native: NativeWindow, - state: WindowState, - prev_state: Option, - border_delta: RectDelta, - insertion_target: Option<(Container, usize)>, - floating_placement: Rect, - done_window_rules: Vec, - window_operation: WindowOperation, + id: Option, + native: NativeWindow, + state: WindowState, + prev_state: Option, + border_delta: RectDelta, + insertion_target: Option<(Container, usize)>, + floating_placement: Rect, + done_window_rules: Vec, + active_drag: ActiveDrag, ) -> Self { let window = NonTilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), @@ -68,7 +69,7 @@ impl NonTilingWindow { has_pending_dpi_adjustment: false, floating_placement, done_window_rules, - window_operation, + active_drag, }; Self(Rc::new(RefCell::new(window))) @@ -94,7 +95,7 @@ impl NonTilingWindow { self.floating_placement(), inner_gap, self.done_window_rules(), - self.window_operation() + self.active_drag() ) } diff --git a/packages/wm/src/windows/tiling_window.rs b/packages/wm/src/windows/tiling_window.rs index abfc560c8..ff359fefa 100644 --- a/packages/wm/src/windows/tiling_window.rs +++ b/packages/wm/src/windows/tiling_window.rs @@ -28,7 +28,7 @@ use crate::{ impl_window_getters, user_config::WindowRuleConfig, }; -use crate::windows::window_operation::WindowOperation; +use crate::windows::active_drag::{ActiveDrag}; #[derive(Clone)] pub struct TilingWindow(Rc>); @@ -48,19 +48,19 @@ struct TilingWindowInner { floating_placement: Rect, inner_gap: LengthValue, done_window_rules: Vec, - window_operation: WindowOperation, + active_drag: ActiveDrag, } impl TilingWindow { pub fn new( - id: Option, - native: NativeWindow, - prev_state: Option, - border_delta: RectDelta, - floating_placement: Rect, - inner_gap: LengthValue, - done_window_rules: Vec, - window_operation: WindowOperation, + id: Option, + native: NativeWindow, + prev_state: Option, + border_delta: RectDelta, + floating_placement: Rect, + inner_gap: LengthValue, + done_window_rules: Vec, + active_drag: ActiveDrag, ) -> Self { let window = TilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), @@ -77,7 +77,7 @@ impl TilingWindow { floating_placement, inner_gap, done_window_rules, - window_operation, + active_drag, }; Self(Rc::new(RefCell::new(window))) @@ -97,7 +97,7 @@ impl TilingWindow { insertion_target, self.floating_placement(), self.done_window_rules(), - self.window_operation(), + self.active_drag(), ) } diff --git a/packages/wm/src/windows/traits/window_getters.rs b/packages/wm/src/windows/traits/window_getters.rs index 28a513bdf..47734e747 100644 --- a/packages/wm/src/windows/traits/window_getters.rs +++ b/packages/wm/src/windows/traits/window_getters.rs @@ -8,9 +8,8 @@ use crate::{ }, containers::WindowContainer, user_config::{UserConfig, WindowRuleConfig}, - windows::WindowState, + windows::{active_drag::ActiveDrag, WindowState}, }; -use crate::windows::window_operation::WindowOperation; #[enum_dispatch] pub trait WindowGetters { @@ -110,9 +109,9 @@ pub trait WindowGetters { done_window_rules: Vec, ); - fn window_operation(&self) -> WindowOperation; - - fn set_window_operation(&self, window_operation: WindowOperation); + fn active_drag(&self) -> ActiveDrag; + + fn set_active_drag(&self, active_drag: ActiveDrag); } /// Implements the `WindowGetters` trait for a given struct. @@ -191,12 +190,12 @@ macro_rules! impl_window_getters { self.0.borrow_mut().done_window_rules = done_window_rules; } - fn window_operation(&self) -> WindowOperation{ - self.0.borrow().window_operation.clone() + fn active_drag(&self) -> ActiveDrag { + self.0.borrow().active_drag.clone() } - - fn set_window_operation(&self, window_operation: WindowOperation) { - self.0.borrow_mut().window_operation = window_operation; + + fn set_active_drag(&self, active_drag: ActiveDrag) { + self.0.borrow_mut().active_drag = active_drag; } } }; diff --git a/packages/wm/src/windows/window_operation.rs b/packages/wm/src/windows/window_operation.rs deleted file mode 100644 index cc469b5b0..000000000 --- a/packages/wm/src/windows/window_operation.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[derive(Debug, Copy, Clone, Default, PartialEq)] -pub enum WindowOperation{ - #[default] - None, - Waiting, - Moving, - Resizing, -} From 704650a9605edef5e1355eb1f369856cd7cf2fac Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 12:10:14 +0200 Subject: [PATCH 26/35] fix: pr review --- .../common/events/handle_window_moved_end.rs | 4 +-- .../commands/get_containers_at_pos.rs | 32 ------------------- packages/wm/src/containers/commands/mod.rs | 2 -- packages/wm/src/wm_state.rs | 31 ++++++++++++++++-- 4 files changed, 30 insertions(+), 39 deletions(-) delete mode 100644 packages/wm/src/containers/commands/get_containers_at_pos.rs diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 664c2b780..574735a65 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -5,7 +5,7 @@ use crate::{ common::{platform::Platform, Point, TilingDirection}, containers::{ commands::{ - attach_container, detach_container, get_containers_at_position, + attach_container, detach_container, move_container_within_tree, }, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, @@ -126,7 +126,7 @@ fn get_tiling_window_at_mouse_pos( state: &WmState, ) -> Option { let children_at_mouse_position: Vec = - get_containers_at_position(state, mouse_position) + state.window_containers_at_position(mouse_position) .into_iter() .filter_map(|container| match container { WindowContainer::TilingWindow(tiling) => Some(tiling), diff --git a/packages/wm/src/containers/commands/get_containers_at_pos.rs b/packages/wm/src/containers/commands/get_containers_at_pos.rs deleted file mode 100644 index c2afd19be..000000000 --- a/packages/wm/src/containers/commands/get_containers_at_pos.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::{ - common::Point, - containers::{ - traits::{CommonGetters, PositionGetters}, - Container, WindowContainer, - }, - wm_state::WmState, -}; - -/// Return all window under the mouse position -pub fn get_containers_at_position( - state: &WmState, - position: &Point, -) -> Vec { - state - .root_container - .descendants() - .filter_map(|container| match container { - Container::TilingWindow(tiling) => { - Some(WindowContainer::TilingWindow(tiling)) - } - Container::NonTilingWindow(non_tiling) => { - Some(WindowContainer::NonTilingWindow(non_tiling)) - } - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - frame.unwrap().contains_point(&position) - }) - .collect() -} diff --git a/packages/wm/src/containers/commands/mod.rs b/packages/wm/src/containers/commands/mod.rs index 4f0627379..b42854eb2 100644 --- a/packages/wm/src/containers/commands/mod.rs +++ b/packages/wm/src/containers/commands/mod.rs @@ -9,7 +9,6 @@ mod resize_tiling_container; mod set_focused_descendant; mod toggle_tiling_direction; mod wrap_in_split_container; -mod get_containers_at_pos; pub use attach_container::*; pub use detach_container::*; @@ -22,4 +21,3 @@ pub use resize_tiling_container::*; pub use set_focused_descendant::*; pub use toggle_tiling_direction::*; pub use wrap_in_split_container::*; -pub use get_containers_at_pos::*; diff --git a/packages/wm/src/wm_state.rs b/packages/wm/src/wm_state.rs index 60ebb973d..c0962a711 100644 --- a/packages/wm/src/wm_state.rs +++ b/packages/wm/src/wm_state.rs @@ -10,11 +10,12 @@ use crate::{ common::{ commands::platform_sync, platform::{NativeMonitor, NativeWindow, Platform}, - Direction, + Direction, Point, }, containers::{ - commands::set_focused_descendant, traits::CommonGetters, Container, - RootContainer, WindowContainer, + commands::set_focused_descendant, + traits::{CommonGetters, PositionGetters}, + Container, RootContainer, WindowContainer, }, monitors::{commands::add_monitor, Monitor}, user_config::{BindingModeConfig, UserConfig}, @@ -455,6 +456,30 @@ impl WmState { .or(descendant_focus_order.first().cloned()) .or(Some(workspace.into())) } + + /// Returns all window under the mouse position + pub fn window_containers_at_position( + &self, + position: &Point, + ) -> Vec { + self + .root_container + .descendants() + .filter_map(|container| match container { + Container::TilingWindow(tiling) => { + Some(WindowContainer::TilingWindow(tiling)) + } + Container::NonTilingWindow(non_tiling) => { + Some(WindowContainer::NonTilingWindow(non_tiling)) + } + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&position) + }) + .collect() + } } impl Drop for WmState { From c8f48429d163e2796048a5afcad2ef788aa319e1 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 12:26:02 +0200 Subject: [PATCH 27/35] fix: pr review --- .../common/events/handle_window_moved_end.rs | 58 +++++++++---------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index 574735a65..b0ad924ad 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -5,20 +5,20 @@ use crate::{ common::{platform::Platform, Point, TilingDirection}, containers::{ commands::{ - attach_container, detach_container, - move_container_within_tree, + attach_container, detach_container, move_container_within_tree, + wrap_in_split_container, }, traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, SplitContainer, WindowContainer, + Container, SplitContainer, TilingContainer, WindowContainer, }, user_config::{FloatingStateConfig, UserConfig}, windows::{ active_drag::ActiveDragOperation, commands::update_window_state, - traits::WindowGetters, NonTilingWindow, TilingWindow, WindowState, + traits::WindowGetters, ActiveDrag, NonTilingWindow, TilingWindow, + WindowState, }, wm_state::WmState, }; -use crate::windows::ActiveDrag; /// Handles window move events pub fn window_moved_end( @@ -125,15 +125,15 @@ fn get_tiling_window_at_mouse_pos( mouse_position: &Point, state: &WmState, ) -> Option { - let children_at_mouse_position: Vec = - state.window_containers_at_position(mouse_position) - .into_iter() - .filter_map(|container| match container { - WindowContainer::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|window: &TilingWindow| window.id() != exclude_window.id()) - .collect(); + let children_at_mouse_position: Vec = state + .window_containers_at_position(mouse_position) + .into_iter() + .filter_map(|container| match container { + WindowContainer::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|window: &TilingWindow| window.id() != exclude_window.id()) + .collect(); children_at_mouse_position.into_iter().next() } @@ -235,27 +235,23 @@ fn create_split_container( DropPosition::End => 1, }; - let split_container = Container::Split(SplitContainer::new( + let split_container = SplitContainer::new( tiling_direction, config.value.gaps.inner_gap.clone(), - )); - attach_container( - &split_container, - &parent, - Some(split_container_index), - )?; + ); - move_container_within_tree( - Container::TilingWindow(target_window), - split_container.clone(), - 0, - state, - )?; - move_container_within_tree( - Container::TilingWindow(moved_window), - split_container, + let mut split_container_children = + vec![TilingContainer::TilingWindow(target_window)]; + + split_container_children.insert( target_index_inside_split_container, - state, + TilingContainer::TilingWindow(moved_window), + ); + + wrap_in_split_container( + split_container, + parent.clone(), + split_container_children, )?; Ok(()) } From 375363783ad619646fb756f7d3afd306e1d88016 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 12:38:15 +0200 Subject: [PATCH 28/35] fix: pr review --- .../common/events/handle_window_moved_end.rs | 52 ++++++------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index b0ad924ad..d5ffcec25 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -70,43 +70,21 @@ pub fn window_moved_end( &tiling_direction, )?; - let parent = window_under_cursor.parent().unwrap(); - - match &parent { - // If the parent is a workspace we only need to add the window to it or - // to create a Vertical split container - Container::Workspace(_) => { - let current_tiling_direction = TilingDirection::Horizontal; - move_window_to_target( - state, - config, - moved_window.clone(), - window_under_cursor.clone(), - &parent, - current_tiling_direction, - tiling_direction, - new_window_position, - )?; - } - // If the parent is a split we need to check the current split - // direction add the window to it or create a [Vertical/Horizontal] - // split container - Container::Split(split) => { - let current_tiling_direction = split.tiling_direction(); - move_window_to_target( - state, - config, - moved_window.clone(), - window_under_cursor.clone(), - &parent, - current_tiling_direction, - tiling_direction, - new_window_position, - )?; - } - _ => {} - } + let parent = window_under_cursor + .direction_container() + .context("The window has no direction container")?; + let parent_tiling_direction: TilingDirection = parent.tiling_direction(); + move_window_to_target( + state, + config, + moved_window.clone(), + window_under_cursor.clone(), + &parent.into(), + parent_tiling_direction, + tiling_direction, + new_window_position, + )?; moved_window.set_active_drag(ActiveDrag::default()); state @@ -242,7 +220,7 @@ fn create_split_container( let mut split_container_children = vec![TilingContainer::TilingWindow(target_window)]; - + split_container_children.insert( target_index_inside_split_container, TilingContainer::TilingWindow(moved_window), From 6067dcde4bddcbebf1c18ebbd7c4d50041093d2c Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 12:46:49 +0200 Subject: [PATCH 29/35] fix: pr review --- .../common/events/handle_window_moved_end.rs | 20 +++++++------------ .../wm/src/windows/commands/manage_window.rs | 1 - packages/wm/src/windows/non_tiling_window.rs | 1 - 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs index d5ffcec25..67804c69f 100644 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_end.rs @@ -11,7 +11,7 @@ use crate::{ traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, Container, SplitContainer, TilingContainer, WindowContainer, }, - user_config::{FloatingStateConfig, UserConfig}, + user_config::UserConfig, windows::{ active_drag::ActiveDragOperation, commands::update_window_state, traits::WindowGetters, ActiveDrag, NonTilingWindow, TilingWindow, @@ -87,12 +87,12 @@ pub fn window_moved_end( )?; moved_window.set_active_drag(ActiveDrag::default()); - state - .pending_sync - .containers_to_redraw - .push(Container::Workspace( - window_under_cursor.workspace().unwrap(), - )); + state.pending_sync.containers_to_redraw.push( + window_under_cursor + .workspace() + .context("No workspace")? + .into(), + ); Ok(()) } @@ -170,25 +170,21 @@ fn move_window_to_target( (TilingDirection::Horizontal, TilingDirection::Vertical) => { create_split_container( TilingDirection::Horizontal, - state, config, moved_window, target_window, drop_position, &target_window_parent, - target_index, )?; } (TilingDirection::Vertical, TilingDirection::Horizontal) => { create_split_container( TilingDirection::Vertical, - state, config, moved_window, target_window, drop_position, &target_window_parent, - target_index, )?; } } @@ -200,13 +196,11 @@ fn move_window_to_target( /// window inside at the dropped position fn create_split_container( tiling_direction: TilingDirection, - state: &mut WmState, config: &UserConfig, moved_window: TilingWindow, target_window: TilingWindow, dropped_position: DropPosition, parent: &Container, - split_container_index: usize, ) -> anyhow::Result<()> { let target_index_inside_split_container = match dropped_position { DropPosition::Start => 0, diff --git a/packages/wm/src/windows/commands/manage_window.rs b/packages/wm/src/windows/commands/manage_window.rs index c5a79365e..4ef8c1905 100644 --- a/packages/wm/src/windows/commands/manage_window.rs +++ b/packages/wm/src/windows/commands/manage_window.rs @@ -18,7 +18,6 @@ use crate::{ wm_state::WmState, }; use crate::windows::ActiveDrag; -use crate::windows::active_drag::ActiveDragOperation; pub fn manage_window( native_window: NativeWindow, diff --git a/packages/wm/src/windows/non_tiling_window.rs b/packages/wm/src/windows/non_tiling_window.rs index 5a818e702..3efff49c2 100644 --- a/packages/wm/src/windows/non_tiling_window.rs +++ b/packages/wm/src/windows/non_tiling_window.rs @@ -19,7 +19,6 @@ use crate::{ }, impl_common_getters, impl_container_debug, impl_window_getters, user_config::WindowRuleConfig, - windows::active_drag::ActiveDragOperation, }; use crate::windows::active_drag::ActiveDrag; From 98757c44e053f115cb6648e524a8615a29c7f60e Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 12:53:35 +0200 Subject: [PATCH 30/35] fix: pr review --- .../common/events/handle_window_moved_end.rs | 289 ---------------- .../handle_window_moved_or_resized_end.rs | 312 +++++++++++++++++- .../events/handle_window_resized_end.rs | 21 -- packages/wm/src/common/events/mod.rs | 2 - 4 files changed, 302 insertions(+), 322 deletions(-) delete mode 100644 packages/wm/src/common/events/handle_window_moved_end.rs delete mode 100644 packages/wm/src/common/events/handle_window_resized_end.rs diff --git a/packages/wm/src/common/events/handle_window_moved_end.rs b/packages/wm/src/common/events/handle_window_moved_end.rs deleted file mode 100644 index 67804c69f..000000000 --- a/packages/wm/src/common/events/handle_window_moved_end.rs +++ /dev/null @@ -1,289 +0,0 @@ -use anyhow::Context; -use tracing::{debug, info}; - -use crate::{ - common::{platform::Platform, Point, TilingDirection}, - containers::{ - commands::{ - attach_container, detach_container, move_container_within_tree, - wrap_in_split_container, - }, - traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, - Container, SplitContainer, TilingContainer, WindowContainer, - }, - user_config::UserConfig, - windows::{ - active_drag::ActiveDragOperation, commands::update_window_state, - traits::WindowGetters, ActiveDrag, NonTilingWindow, TilingWindow, - WindowState, - }, - wm_state::WmState, -}; - -/// Handles window move events -pub fn window_moved_end( - moved_window: NonTilingWindow, - state: &mut WmState, - config: &UserConfig, -) -> anyhow::Result<()> { - // We continue only if it's a temporary Floating window and if the window - // got moved and not resized - let mut active_drag = moved_window.active_drag(); - if active_drag.is_from_tiling == false - || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) - { - active_drag.operation = None; - moved_window.set_active_drag(active_drag); - return Ok(()); - } - info!("Tiling window drag end event"); - - let mouse_position = Platform::mouse_position()?; - - let window_under_cursor = match get_tiling_window_at_mouse_pos( - &moved_window, - &mouse_position, - state, - ) { - Some(value) => value, - None => { - update_window_state( - moved_window.as_window_container().unwrap(), - WindowState::Tiling, - state, - config, - )?; - return Ok(()); - } - }; - - debug!( - "Moved window: {:?} \n Target window: {:?}", - moved_window.native().process_name(), - window_under_cursor.native().process_name(), - ); - - let tiling_direction = get_split_direction(&window_under_cursor)?; - let new_window_position = get_drop_position( - &mouse_position, - &window_under_cursor, - &tiling_direction, - )?; - - let parent = window_under_cursor - .direction_container() - .context("The window has no direction container")?; - let parent_tiling_direction: TilingDirection = parent.tiling_direction(); - - move_window_to_target( - state, - config, - moved_window.clone(), - window_under_cursor.clone(), - &parent.into(), - parent_tiling_direction, - tiling_direction, - new_window_position, - )?; - moved_window.set_active_drag(ActiveDrag::default()); - - state.pending_sync.containers_to_redraw.push( - window_under_cursor - .workspace() - .context("No workspace")? - .into(), - ); - - Ok(()) -} - -/// Return the window under the mouse position excluding the dragged window -fn get_tiling_window_at_mouse_pos( - exclude_window: &NonTilingWindow, - mouse_position: &Point, - state: &WmState, -) -> Option { - let children_at_mouse_position: Vec = state - .window_containers_at_position(mouse_position) - .into_iter() - .filter_map(|container| match container { - WindowContainer::TilingWindow(tiling) => Some(tiling), - _ => None, - }) - .filter(|window: &TilingWindow| window.id() != exclude_window.id()) - .collect(); - - children_at_mouse_position.into_iter().next() -} - -fn move_window_to_target( - state: &mut WmState, - config: &UserConfig, - moved_window: NonTilingWindow, - target_window: TilingWindow, - target_window_parent: &Container, - current_tiling_direction: TilingDirection, - new_tiling_direction: TilingDirection, - drop_position: DropPosition, -) -> anyhow::Result<()> { - update_window_state( - moved_window.as_window_container().unwrap(), - WindowState::Tiling, - state, - config, - )?; - - let moved_window = state - .windows() - .iter() - .find(|w| w.id() == moved_window.id()) - .context("couldn't find the new tiled window")? - .as_tiling_window() - .context("window is not a tiled window")? - .clone(); - - // TODO: We can optimize that by not detaching and attaching the window - // Little trick to get the right index - detach_container(Container::TilingWindow(moved_window.clone()))?; - let target_window_index = target_window.index(); - attach_container( - &Container::TilingWindow(moved_window.clone()), - target_window_parent, - None, - )?; - - let target_index = match drop_position { - DropPosition::Start => target_window_index, - DropPosition::End => target_window_index + 1, - }; - - match (new_tiling_direction, current_tiling_direction) { - (TilingDirection::Horizontal, TilingDirection::Horizontal) - | (TilingDirection::Vertical, TilingDirection::Vertical) => { - move_container_within_tree( - Container::TilingWindow(moved_window.clone()), - target_window_parent.clone(), - target_index, - state, - )?; - } - (TilingDirection::Horizontal, TilingDirection::Vertical) => { - create_split_container( - TilingDirection::Horizontal, - config, - moved_window, - target_window, - drop_position, - &target_window_parent, - )?; - } - (TilingDirection::Vertical, TilingDirection::Horizontal) => { - create_split_container( - TilingDirection::Vertical, - config, - moved_window, - target_window, - drop_position, - &target_window_parent, - )?; - } - } - - Ok(()) -} - -/// Creates a split container and moves the target window and the moved -/// window inside at the dropped position -fn create_split_container( - tiling_direction: TilingDirection, - config: &UserConfig, - moved_window: TilingWindow, - target_window: TilingWindow, - dropped_position: DropPosition, - parent: &Container, -) -> anyhow::Result<()> { - let target_index_inside_split_container = match dropped_position { - DropPosition::Start => 0, - DropPosition::End => 1, - }; - - let split_container = SplitContainer::new( - tiling_direction, - config.value.gaps.inner_gap.clone(), - ); - - let mut split_container_children = - vec![TilingContainer::TilingWindow(target_window)]; - - split_container_children.insert( - target_index_inside_split_container, - TilingContainer::TilingWindow(moved_window), - ); - - wrap_in_split_container( - split_container, - parent.clone(), - split_container_children, - )?; - Ok(()) -} - -/// Represents where the window was dropped over another one. -/// It depends on the tiling direction. -/// -/// [DropPosition::Start] can either be the top or left side. -/// [DropPosition::Stop] can either be bottom or right side. -#[derive(Debug)] -enum DropPosition { - Start, - End, -} - -/// Determines the drop position for a window based on the mouse position -/// and tiling direction. -/// -/// This function calculates whether a window should be dropped at the -/// start or end of a tiling layout, depending on the mouse position -/// relative to the middle of the target window. -fn get_drop_position( - mouse_position: &Point, - window: &TilingWindow, - tiling_direction: &TilingDirection, -) -> anyhow::Result { - let rect = window.to_rect()?; - - match tiling_direction { - TilingDirection::Vertical => { - let middle = rect.top + (rect.height() / 2); - if mouse_position.y < middle { - Ok(DropPosition::Start) - } else { - Ok(DropPosition::End) - } - } - TilingDirection::Horizontal => { - let middle = rect.left + (rect.width() / 2); - if mouse_position.x < middle { - Ok(DropPosition::Start) - } else { - Ok(DropPosition::End) - } - } - } -} - -/// Determines the optimal split direction for a given window. -/// -/// This function decides whether a window should be split vertically or -/// horizontally based on its current dimensions. -fn get_split_direction( - window: &TilingWindow, -) -> anyhow::Result { - let rect = window.to_rect()?; - - if rect.height() > rect.width() { - Ok(TilingDirection::Vertical) - } else { - Ok(TilingDirection::Horizontal) - } -} diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index 869ec6485..83479a6b8 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -1,26 +1,34 @@ use anyhow::Context; +use tracing::{debug, info}; use crate::{ common::{ - events::{ - handle_window_moved_end::window_moved_end, - handle_window_resized_end::window_resized_end, - }, - platform::NativeWindow, + platform::{NativeWindow, Platform}, + LengthValue, Point, TilingDirection, }, containers::{ - traits::{CommonGetters, PositionGetters}, - WindowContainer, + commands::{ + attach_container, detach_container, move_container_within_tree, + wrap_in_split_container, + }, + traits::{CommonGetters, PositionGetters, TilingDirectionGetters}, + Container, SplitContainer, TilingContainer, WindowContainer, }, user_config::UserConfig, - windows::traits::WindowGetters, + windows::{ + active_drag::ActiveDragOperation, + commands::{resize_window, update_window_state}, + traits::WindowGetters, + ActiveDrag, NonTilingWindow, TilingWindow, WindowState, + }, wm_state::WmState, }; /// Handles the event for when a window is finished being moved or resized /// by the user (e.g. via the window's drag handles). /// -/// This resizes the window if it's a tiling window and attach a dragged floating window. +/// This resizes the window if it's a tiling window and attach a dragged +/// floating window. pub fn handle_window_moved_or_resized_end( native_window: NativeWindow, state: &mut WmState, @@ -46,7 +54,7 @@ pub fn handle_window_moved_or_resized_end( let height_delta = new_rect.height() - old_rect.height(); if let WindowContainer::NonTilingWindow(window) = window { - let has_window_moved = matches!((width_delta, height_delta), (0,0)); + let has_window_moved = matches!((width_delta, height_delta), (0, 0)); if has_window_moved { window_moved_end(window, state, config)?; @@ -58,3 +66,287 @@ pub fn handle_window_moved_or_resized_end( Ok(()) } + +/// Handles window resize events +fn window_resized_end( + window: TilingWindow, + state: &mut WmState, + width_delta: i32, + height_delta: i32, +) -> anyhow::Result<()> { + info!("Tiling window resized"); + resize_window( + window.clone().into(), + Some(LengthValue::from_px(width_delta)), + Some(LengthValue::from_px(height_delta)), + state, + ) +} + +/// Handles window move events +fn window_moved_end( + moved_window: NonTilingWindow, + state: &mut WmState, + config: &UserConfig, +) -> anyhow::Result<()> { + // We continue only if it's a temporary Floating window and if the window + // got moved and not resized + let mut active_drag = moved_window.active_drag(); + if active_drag.is_from_tiling == false + || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) + { + active_drag.operation = None; + moved_window.set_active_drag(active_drag); + return Ok(()); + } + info!("Tiling window drag end event"); + + let mouse_position = Platform::mouse_position()?; + + let window_under_cursor = match get_tiling_window_at_mouse_pos( + &moved_window, + &mouse_position, + state, + ) { + Some(value) => value, + None => { + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Tiling, + state, + config, + )?; + return Ok(()); + } + }; + + debug!( + "Moved window: {:?} \n Target window: {:?}", + moved_window.native().process_name(), + window_under_cursor.native().process_name(), + ); + + let tiling_direction = get_split_direction(&window_under_cursor)?; + let new_window_position = get_drop_position( + &mouse_position, + &window_under_cursor, + &tiling_direction, + )?; + + let parent = window_under_cursor + .direction_container() + .context("The window has no direction container")?; + let parent_tiling_direction: TilingDirection = parent.tiling_direction(); + + move_window_to_target( + state, + config, + moved_window.clone(), + window_under_cursor.clone(), + &parent.into(), + parent_tiling_direction, + tiling_direction, + new_window_position, + )?; + moved_window.set_active_drag(ActiveDrag::default()); + + state.pending_sync.containers_to_redraw.push( + window_under_cursor + .workspace() + .context("No workspace")? + .into(), + ); + + Ok(()) +} + +/// Return the window under the mouse position excluding the dragged window +fn get_tiling_window_at_mouse_pos( + exclude_window: &NonTilingWindow, + mouse_position: &Point, + state: &WmState, +) -> Option { + let children_at_mouse_position: Vec = state + .window_containers_at_position(mouse_position) + .into_iter() + .filter_map(|container| match container { + WindowContainer::TilingWindow(tiling) => Some(tiling), + _ => None, + }) + .filter(|window: &TilingWindow| window.id() != exclude_window.id()) + .collect(); + + children_at_mouse_position.into_iter().next() +} + +fn move_window_to_target( + state: &mut WmState, + config: &UserConfig, + moved_window: NonTilingWindow, + target_window: TilingWindow, + target_window_parent: &Container, + current_tiling_direction: TilingDirection, + new_tiling_direction: TilingDirection, + drop_position: DropPosition, +) -> anyhow::Result<()> { + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Tiling, + state, + config, + )?; + + let moved_window = state + .windows() + .iter() + .find(|w| w.id() == moved_window.id()) + .context("couldn't find the new tiled window")? + .as_tiling_window() + .context("window is not a tiled window")? + .clone(); + + // TODO: We can optimize that by not detaching and attaching the window + // Little trick to get the right index + detach_container(Container::TilingWindow(moved_window.clone()))?; + let target_window_index = target_window.index(); + attach_container( + &Container::TilingWindow(moved_window.clone()), + target_window_parent, + None, + )?; + + let target_index = match drop_position { + DropPosition::Start => target_window_index, + DropPosition::End => target_window_index + 1, + }; + + match (new_tiling_direction, current_tiling_direction) { + (TilingDirection::Horizontal, TilingDirection::Horizontal) + | (TilingDirection::Vertical, TilingDirection::Vertical) => { + move_container_within_tree( + Container::TilingWindow(moved_window.clone()), + target_window_parent.clone(), + target_index, + state, + )?; + } + (TilingDirection::Horizontal, TilingDirection::Vertical) => { + create_split_container( + TilingDirection::Horizontal, + config, + moved_window, + target_window, + drop_position, + &target_window_parent, + )?; + } + (TilingDirection::Vertical, TilingDirection::Horizontal) => { + create_split_container( + TilingDirection::Vertical, + config, + moved_window, + target_window, + drop_position, + &target_window_parent, + )?; + } + } + + Ok(()) +} + +/// Creates a split container and moves the target window and the moved +/// window inside at the dropped position +fn create_split_container( + tiling_direction: TilingDirection, + config: &UserConfig, + moved_window: TilingWindow, + target_window: TilingWindow, + dropped_position: DropPosition, + parent: &Container, +) -> anyhow::Result<()> { + let target_index_inside_split_container = match dropped_position { + DropPosition::Start => 0, + DropPosition::End => 1, + }; + + let split_container = SplitContainer::new( + tiling_direction, + config.value.gaps.inner_gap.clone(), + ); + + let mut split_container_children = + vec![TilingContainer::TilingWindow(target_window)]; + + split_container_children.insert( + target_index_inside_split_container, + TilingContainer::TilingWindow(moved_window), + ); + + wrap_in_split_container( + split_container, + parent.clone(), + split_container_children, + )?; + Ok(()) +} + +/// Represents where the window was dropped over another one. +/// It depends on the tiling direction. +/// +/// [DropPosition::Start] can either be the top or left side. +/// [DropPosition::Stop] can either be bottom or right side. +#[derive(Debug)] +enum DropPosition { + Start, + End, +} + +/// Determines the drop position for a window based on the mouse position +/// and tiling direction. +/// +/// This function calculates whether a window should be dropped at the +/// start or end of a tiling layout, depending on the mouse position +/// relative to the middle of the target window. +fn get_drop_position( + mouse_position: &Point, + window: &TilingWindow, + tiling_direction: &TilingDirection, +) -> anyhow::Result { + let rect = window.to_rect()?; + + match tiling_direction { + TilingDirection::Vertical => { + let middle = rect.top + (rect.height() / 2); + if mouse_position.y < middle { + Ok(DropPosition::Start) + } else { + Ok(DropPosition::End) + } + } + TilingDirection::Horizontal => { + let middle = rect.left + (rect.width() / 2); + if mouse_position.x < middle { + Ok(DropPosition::Start) + } else { + Ok(DropPosition::End) + } + } + } +} + +/// Determines the optimal split direction for a given window. +/// +/// This function decides whether a window should be split vertically or +/// horizontally based on its current dimensions. +fn get_split_direction( + window: &TilingWindow, +) -> anyhow::Result { + let rect = window.to_rect()?; + + if rect.height() > rect.width() { + Ok(TilingDirection::Vertical) + } else { + Ok(TilingDirection::Horizontal) + } +} diff --git a/packages/wm/src/common/events/handle_window_resized_end.rs b/packages/wm/src/common/events/handle_window_resized_end.rs deleted file mode 100644 index d0a494dce..000000000 --- a/packages/wm/src/common/events/handle_window_resized_end.rs +++ /dev/null @@ -1,21 +0,0 @@ -use tracing::info; -use crate::common::LengthValue; -use crate::windows::commands::resize_window; -use crate::windows::TilingWindow; -use crate::wm_state::WmState; - -/// Handles window resize events -pub fn window_resized_end( - window: TilingWindow, - state: &mut WmState, - width_delta: i32, - height_delta: i32, -) -> anyhow::Result<()> { - info!("Tiling window resized"); - resize_window( - window.clone().into(), - Some(LengthValue::from_px(width_delta)), - Some(LengthValue::from_px(height_delta)), - state, - ) -} diff --git a/packages/wm/src/common/events/mod.rs b/packages/wm/src/common/events/mod.rs index 4691c006a..991eb7f74 100644 --- a/packages/wm/src/common/events/mod.rs +++ b/packages/wm/src/common/events/mod.rs @@ -6,12 +6,10 @@ mod handle_window_hidden; mod handle_window_location_changed; mod handle_window_minimize_ended; mod handle_window_minimized; -mod handle_window_moved_end; mod handle_window_moved_or_resized_end; mod handle_window_shown; mod handle_window_title_changed; mod handle_window_moved_or_resized_start; -mod handle_window_resized_end; pub use handle_display_settings_changed::*; pub use handle_mouse_move::*; From 49bdb8cb520a8bdb58c7a3944055e8fd51fa9614 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 15:28:37 +0200 Subject: [PATCH 31/35] fix: bug resize considered as a drag --- packages/wm/src/common/events/handle_window_location_changed.rs | 1 + packages/wm/src/common/rect.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 4bd7ab802..0880138c8 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -163,6 +163,7 @@ fn update_window_operation( if let Some(tiling_window) = window.as_tiling_window() { let mut active_drag: ActiveDrag = tiling_window.active_drag(); if matches!(active_drag.operation, Some(ActiveDragOperation::Waiting)) + && frame_position != old_frame_position { if frame_position.height() == old_frame_position.height() && frame_position.width() == old_frame_position.width() diff --git a/packages/wm/src/common/rect.rs b/packages/wm/src/common/rect.rs index e8c46f178..0301b014f 100644 --- a/packages/wm/src/common/rect.rs +++ b/packages/wm/src/common/rect.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use super::{Direction, Point, RectDelta}; -#[derive(Debug, Deserialize, Clone, Serialize)] +#[derive(Debug, Deserialize, Clone, Serialize, Eq, PartialEq)] pub struct Rect { /// X-coordinate of the left edge of the rectangle. pub left: i32, From 16f7ffb53f4f85aabf23b5c1124fa6087c90762f Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 19:49:22 +0200 Subject: [PATCH 32/35] fix: moving window into an empty workspace --- .../handle_window_moved_or_resized_end.rs | 44 +++++++++++++++---- packages/wm/src/wm_state.rs | 19 ++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index 83479a6b8..e38223f3a 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -4,7 +4,7 @@ use tracing::{debug, info}; use crate::{ common::{ platform::{NativeWindow, Platform}, - LengthValue, Point, TilingDirection, + DisplayState, LengthValue, Point, TilingDirection, }, containers::{ commands::{ @@ -42,10 +42,10 @@ pub fn handle_window_moved_or_resized_end( // Snap window to its original position if it's the only window in the // workspace. - if parent.is_workspace() && window.tiling_siblings().count() == 0 { - state.pending_sync.containers_to_redraw.push(window.into()); - return Ok(()); - } + // if parent.is_workspace() && window.tiling_siblings().count() == 0 { + // state.pending_sync.containers_to_redraw.push(window.into()); + // return Ok(()); + // } let new_rect = window.native().refresh_frame_position()?; let old_rect = window.to_rect()?; @@ -110,6 +110,34 @@ fn window_moved_end( ) { Some(value) => value, None => { + let target_monitor = state + .monitor_at_position(&mouse_position) + .context("couldn't get the monitor")?; + + let target_workspace = target_monitor + .displayed_workspace() + .context("couldn't get the workspace")?; + + let visible_tiling_window_count = target_workspace + .descendants() + .fold(0, |acc, container| match container { + Container::TilingWindow(tiling_window) => { + match tiling_window.display_state() { + DisplayState::Shown | DisplayState::Showing => acc + 1, + _ => acc, + } + } + _ => acc, + }); + + if visible_tiling_window_count == 0 { + move_container_within_tree( + moved_window.clone().into(), + target_workspace.into(), + 0, + state, + )?; + } update_window_state( moved_window.as_window_container().unwrap(), WindowState::Tiling, @@ -166,7 +194,7 @@ fn get_tiling_window_at_mouse_pos( mouse_position: &Point, state: &WmState, ) -> Option { - let children_at_mouse_position: Vec = state + state .window_containers_at_position(mouse_position) .into_iter() .filter_map(|container| match container { @@ -174,9 +202,7 @@ fn get_tiling_window_at_mouse_pos( _ => None, }) .filter(|window: &TilingWindow| window.id() != exclude_window.id()) - .collect(); - - children_at_mouse_position.into_iter().next() + .next() } fn move_window_to_target( diff --git a/packages/wm/src/wm_state.rs b/packages/wm/src/wm_state.rs index c0962a711..6421d3489 100644 --- a/packages/wm/src/wm_state.rs +++ b/packages/wm/src/wm_state.rs @@ -480,6 +480,25 @@ impl WmState { }) .collect() } + + /// Returns all window under the mouse position + pub fn monitor_at_position( + &self, + position: &Point, + ) -> Option { + self + .root_container + .descendants() + .filter_map(|container| match container { + Container::Monitor(monitor) => Some(monitor), + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&position) + }) + .next() + } } impl Drop for WmState { From 3a47a58c7bfe51b8439b260b1b6dbdf160cebbc5 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 19:55:25 +0200 Subject: [PATCH 33/35] refactor --- .../handle_window_moved_or_resized_end.rs | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index e38223f3a..bc0561d28 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -110,41 +110,7 @@ fn window_moved_end( ) { Some(value) => value, None => { - let target_monitor = state - .monitor_at_position(&mouse_position) - .context("couldn't get the monitor")?; - - let target_workspace = target_monitor - .displayed_workspace() - .context("couldn't get the workspace")?; - - let visible_tiling_window_count = target_workspace - .descendants() - .fold(0, |acc, container| match container { - Container::TilingWindow(tiling_window) => { - match tiling_window.display_state() { - DisplayState::Shown | DisplayState::Showing => acc + 1, - _ => acc, - } - } - _ => acc, - }); - - if visible_tiling_window_count == 0 { - move_container_within_tree( - moved_window.clone().into(), - target_workspace.into(), - 0, - state, - )?; - } - update_window_state( - moved_window.as_window_container().unwrap(), - WindowState::Tiling, - state, - config, - )?; - return Ok(()); + return on_no_target_window(&moved_window, state, config, &mouse_position); } }; @@ -188,6 +154,50 @@ fn window_moved_end( Ok(()) } +fn on_no_target_window( + moved_window: &NonTilingWindow, + state: &mut WmState, + config: &UserConfig, + mouse_position: &Point, +) -> anyhow::Result<()> { + let target_monitor = state + .monitor_at_position(&mouse_position) + .context("couldn't get the monitor")?; + + let target_workspace = target_monitor + .displayed_workspace() + .context("couldn't get the workspace")?; + + let visible_tiling_window_count = target_workspace.descendants().fold( + 0, + |acc, container| match container { + Container::TilingWindow(tiling_window) => { + match tiling_window.display_state() { + DisplayState::Shown | DisplayState::Showing => acc + 1, + _ => acc, + } + } + _ => acc, + }, + ); + + if visible_tiling_window_count == 0 { + move_container_within_tree( + moved_window.clone().into(), + target_workspace.into(), + 0, + state, + )?; + } + update_window_state( + moved_window.as_window_container().unwrap(), + WindowState::Tiling, + state, + config, + )?; + return Ok(()); +} + /// Return the window under the mouse position excluding the dragged window fn get_tiling_window_at_mouse_pos( exclude_window: &NonTilingWindow, From 6bf4528bbdbd15371bb3ed749d36711f799ffcf3 Mon Sep 17 00:00:00 2001 From: Luca Date: Thu, 1 Aug 2024 20:18:23 +0200 Subject: [PATCH 34/35] refactor: use option for active_drag --- .../events/handle_window_location_changed.rs | 31 ++++++++++--------- .../handle_window_moved_or_resized_end.rs | 16 +++++----- .../handle_window_moved_or_resized_start.rs | 6 ++-- packages/wm/src/windows/active_drag.rs | 1 - .../wm/src/windows/commands/manage_window.rs | 4 +-- packages/wm/src/windows/non_tiling_window.rs | 4 +-- packages/wm/src/windows/tiling_window.rs | 4 +-- .../wm/src/windows/traits/window_getters.rs | 8 ++--- 8 files changed, 36 insertions(+), 38 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index 0880138c8..ec7b7a38c 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -161,19 +161,19 @@ fn update_window_operation( old_frame_position: &Rect, ) -> anyhow::Result<()> { if let Some(tiling_window) = window.as_tiling_window() { - let mut active_drag: ActiveDrag = tiling_window.active_drag(); - if matches!(active_drag.operation, Some(ActiveDragOperation::Waiting)) - && frame_position != old_frame_position - { - if frame_position.height() == old_frame_position.height() - && frame_position.width() == old_frame_position.width() + if let Some(mut active_drag) = tiling_window.active_drag() { + if active_drag.operation.is_none() && frame_position != old_frame_position { - active_drag.operation = Some(ActiveDragOperation::Moving); - tiling_window.set_active_drag(active_drag); - set_into_floating(tiling_window.clone(), state, config)?; - } else { - active_drag.operation = Some(ActiveDragOperation::Resizing); - tiling_window.set_active_drag(active_drag); + if frame_position.height() == old_frame_position.height() + && frame_position.width() == old_frame_position.width() + { + active_drag.operation = Some(ActiveDragOperation::Moving); + tiling_window.set_active_drag(Some(active_drag)); + set_into_floating(tiling_window.clone(), state, config)?; + } else { + active_drag.operation = Some(ActiveDragOperation::Resizing); + tiling_window.set_active_drag(Some(active_drag)); + } } } } @@ -209,9 +209,10 @@ fn set_into_floating( } } - let mut active_drag = moved_window.active_drag(); - active_drag.is_from_tiling = true; - moved_window.set_active_drag(active_drag); + if let Some(mut active_drag) = moved_window.active_drag() { + active_drag.is_from_tiling = true; + moved_window.set_active_drag(Some(active_drag)); + } update_window_state( moved_window.as_window_container().unwrap(), diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index bc0561d28..bd96571d5 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -91,13 +91,13 @@ fn window_moved_end( ) -> anyhow::Result<()> { // We continue only if it's a temporary Floating window and if the window // got moved and not resized - let mut active_drag = moved_window.active_drag(); - if active_drag.is_from_tiling == false - || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) - { - active_drag.operation = None; - moved_window.set_active_drag(active_drag); - return Ok(()); + if let Some(active_drag) = moved_window.active_drag() { + if active_drag.is_from_tiling == false + || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) + { + moved_window.set_active_drag(None); + return Ok(()); + } } info!("Tiling window drag end event"); @@ -142,7 +142,7 @@ fn window_moved_end( tiling_direction, new_window_position, )?; - moved_window.set_active_drag(ActiveDrag::default()); + moved_window.set_active_drag(None); state.pending_sync.containers_to_redraw.push( window_under_cursor diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index fc450566f..f2a62c175 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -3,10 +3,10 @@ use crate::{ containers::WindowContainer, windows::{ traits::WindowGetters, - active_drag::{ActiveDragOperation}, }, wm_state::WmState, }; +use crate::windows::ActiveDrag; /// Handles the event for when a window is started being moved or resized /// by the user (e.g. via the window's drag handles). @@ -17,9 +17,7 @@ pub fn handle_window_moved_or_resized_start( let found_window = state.window_from_native(&native_window); if let Some(WindowContainer::TilingWindow(moved_window)) = found_window { - let mut active_drag = moved_window.active_drag(); - active_drag.operation = Some(ActiveDragOperation::Waiting); - moved_window.set_active_drag(active_drag); + moved_window.set_active_drag(Some(ActiveDrag::default())); } Ok(()) diff --git a/packages/wm/src/windows/active_drag.rs b/packages/wm/src/windows/active_drag.rs index b0b966ae9..3a980827d 100644 --- a/packages/wm/src/windows/active_drag.rs +++ b/packages/wm/src/windows/active_drag.rs @@ -6,7 +6,6 @@ pub struct ActiveDrag{ #[derive(Debug, Copy, Clone, PartialEq)] pub enum ActiveDragOperation { - Waiting, Moving, Resizing, } diff --git a/packages/wm/src/windows/commands/manage_window.rs b/packages/wm/src/windows/commands/manage_window.rs index 4ef8c1905..8d148bec2 100644 --- a/packages/wm/src/windows/commands/manage_window.rs +++ b/packages/wm/src/windows/commands/manage_window.rs @@ -134,7 +134,7 @@ fn create_window( floating_placement, inner_gap, Vec::new(), - ActiveDrag::default(), + None, ) .into(), _ => NonTilingWindow::new( @@ -146,7 +146,7 @@ fn create_window( None, floating_placement, Vec::new(), - ActiveDrag::default(), + None, ) .into(), }; diff --git a/packages/wm/src/windows/non_tiling_window.rs b/packages/wm/src/windows/non_tiling_window.rs index 3efff49c2..d0890f26e 100644 --- a/packages/wm/src/windows/non_tiling_window.rs +++ b/packages/wm/src/windows/non_tiling_window.rs @@ -39,7 +39,7 @@ struct NonTilingWindowInner { has_pending_dpi_adjustment: bool, floating_placement: Rect, done_window_rules: Vec, - active_drag: ActiveDrag, + active_drag: Option, } impl NonTilingWindow { @@ -52,7 +52,7 @@ impl NonTilingWindow { insertion_target: Option<(Container, usize)>, floating_placement: Rect, done_window_rules: Vec, - active_drag: ActiveDrag, + active_drag: Option, ) -> Self { let window = NonTilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), diff --git a/packages/wm/src/windows/tiling_window.rs b/packages/wm/src/windows/tiling_window.rs index ff359fefa..e39b00859 100644 --- a/packages/wm/src/windows/tiling_window.rs +++ b/packages/wm/src/windows/tiling_window.rs @@ -48,7 +48,7 @@ struct TilingWindowInner { floating_placement: Rect, inner_gap: LengthValue, done_window_rules: Vec, - active_drag: ActiveDrag, + active_drag: Option, } impl TilingWindow { @@ -60,7 +60,7 @@ impl TilingWindow { floating_placement: Rect, inner_gap: LengthValue, done_window_rules: Vec, - active_drag: ActiveDrag, + active_drag: Option, ) -> Self { let window = TilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), diff --git a/packages/wm/src/windows/traits/window_getters.rs b/packages/wm/src/windows/traits/window_getters.rs index 47734e747..c86c4761d 100644 --- a/packages/wm/src/windows/traits/window_getters.rs +++ b/packages/wm/src/windows/traits/window_getters.rs @@ -109,9 +109,9 @@ pub trait WindowGetters { done_window_rules: Vec, ); - fn active_drag(&self) -> ActiveDrag; + fn active_drag(&self) -> Option; - fn set_active_drag(&self, active_drag: ActiveDrag); + fn set_active_drag(&self, active_drag: Option); } /// Implements the `WindowGetters` trait for a given struct. @@ -190,11 +190,11 @@ macro_rules! impl_window_getters { self.0.borrow_mut().done_window_rules = done_window_rules; } - fn active_drag(&self) -> ActiveDrag { + fn active_drag(&self) -> Option { self.0.borrow().active_drag.clone() } - fn set_active_drag(&self, active_drag: ActiveDrag) { + fn set_active_drag(&self, active_drag: Option) { self.0.borrow_mut().active_drag = active_drag; } } From 1082f2933a9fdc4a74c268a018a2b1a0aa8c0805 Mon Sep 17 00:00:00 2001 From: Lars Berger Date: Fri, 2 Aug 2024 02:53:42 +0800 Subject: [PATCH 35/35] style: linting fixes --- .../events/handle_window_location_changed.rs | 11 +++--- .../handle_window_moved_or_resized_end.rs | 24 ++++++------- .../handle_window_moved_or_resized_start.rs | 5 +-- packages/wm/src/common/events/mod.rs | 2 +- .../src/common/platform/window_event_hook.rs | 4 +-- .../commands/move_container_within_tree.rs | 18 +++++----- packages/wm/src/windows/active_drag.rs | 10 +++--- .../wm/src/windows/commands/manage_window.rs | 35 +++++++++---------- packages/wm/src/windows/mod.rs | 4 +-- packages/wm/src/windows/non_tiling_window.rs | 25 ++++++------- packages/wm/src/windows/tiling_window.rs | 18 +++++----- packages/wm/src/wm_state.rs | 29 +++++++-------- 12 files changed, 88 insertions(+), 97 deletions(-) diff --git a/packages/wm/src/common/events/handle_window_location_changed.rs b/packages/wm/src/common/events/handle_window_location_changed.rs index ec7b7a38c..5e7209038 100644 --- a/packages/wm/src/common/events/handle_window_location_changed.rs +++ b/packages/wm/src/common/events/handle_window_location_changed.rs @@ -12,10 +12,8 @@ use crate::{ }, user_config::{FloatingStateConfig, FullscreenStateConfig, UserConfig}, windows::{ - commands::update_window_state, - traits::WindowGetters, - active_drag::{ActiveDrag, ActiveDragOperation}, - TilingWindow, WindowState, + commands::update_window_state, traits::WindowGetters, + ActiveDragOperation, TilingWindow, WindowState, }, wm_state::WmState, }; @@ -162,10 +160,11 @@ fn update_window_operation( ) -> anyhow::Result<()> { if let Some(tiling_window) = window.as_tiling_window() { if let Some(mut active_drag) = tiling_window.active_drag() { - if active_drag.operation.is_none() && frame_position != old_frame_position + if active_drag.operation.is_none() + && frame_position != old_frame_position { if frame_position.height() == old_frame_position.height() - && frame_position.width() == old_frame_position.width() + && frame_position.width() == old_frame_position.width() { active_drag.operation = Some(ActiveDragOperation::Moving); tiling_window.set_active_drag(Some(active_drag)); diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs index bd96571d5..bae71e2d2 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_end.rs @@ -16,10 +16,9 @@ use crate::{ }, user_config::UserConfig, windows::{ - active_drag::ActiveDragOperation, commands::{resize_window, update_window_state}, traits::WindowGetters, - ActiveDrag, NonTilingWindow, TilingWindow, WindowState, + ActiveDragOperation, NonTilingWindow, TilingWindow, WindowState, }, wm_state::WmState, }; @@ -38,15 +37,6 @@ pub fn handle_window_moved_or_resized_end( if let Some(window) = found_window { // TODO: Log window details. - let parent = window.parent().context("No parent.")?; - - // Snap window to its original position if it's the only window in the - // workspace. - // if parent.is_workspace() && window.tiling_siblings().count() == 0 { - // state.pending_sync.containers_to_redraw.push(window.into()); - // return Ok(()); - // } - let new_rect = window.native().refresh_frame_position()?; let old_rect = window.to_rect()?; @@ -93,7 +83,10 @@ fn window_moved_end( // got moved and not resized if let Some(active_drag) = moved_window.active_drag() { if active_drag.is_from_tiling == false - || !matches!(active_drag.operation, Some(ActiveDragOperation::Moving)) + || !matches!( + active_drag.operation, + Some(ActiveDragOperation::Moving) + ) { moved_window.set_active_drag(None); return Ok(()); @@ -110,7 +103,12 @@ fn window_moved_end( ) { Some(value) => value, None => { - return on_no_target_window(&moved_window, state, config, &mouse_position); + return on_no_target_window( + &moved_window, + state, + config, + &mouse_position, + ); } }; diff --git a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs index f2a62c175..b8a25ee87 100644 --- a/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs +++ b/packages/wm/src/common/events/handle_window_moved_or_resized_start.rs @@ -1,12 +1,9 @@ use crate::{ common::platform::NativeWindow, containers::WindowContainer, - windows::{ - traits::WindowGetters, - }, + windows::{traits::WindowGetters, ActiveDrag}, wm_state::WmState, }; -use crate::windows::ActiveDrag; /// Handles the event for when a window is started being moved or resized /// by the user (e.g. via the window's drag handles). diff --git a/packages/wm/src/common/events/mod.rs b/packages/wm/src/common/events/mod.rs index 991eb7f74..0019a0f67 100644 --- a/packages/wm/src/common/events/mod.rs +++ b/packages/wm/src/common/events/mod.rs @@ -7,9 +7,9 @@ mod handle_window_location_changed; mod handle_window_minimize_ended; mod handle_window_minimized; mod handle_window_moved_or_resized_end; +mod handle_window_moved_or_resized_start; mod handle_window_shown; mod handle_window_title_changed; -mod handle_window_moved_or_resized_start; pub use handle_display_settings_changed::*; pub use handle_mouse_move::*; diff --git a/packages/wm/src/common/platform/window_event_hook.rs b/packages/wm/src/common/platform/window_event_hook.rs index c6d170700..06d8f7d69 100644 --- a/packages/wm/src/common/platform/window_event_hook.rs +++ b/packages/wm/src/common/platform/window_event_hook.rs @@ -12,8 +12,8 @@ use windows::Win32::{ EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_SHOW, EVENT_OBJECT_UNCLOAKED, EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, - EVENT_SYSTEM_MOVESIZEEND,EVENT_SYSTEM_MOVESIZESTART, OBJID_WINDOW, WINEVENT_OUTOFCONTEXT, - WINEVENT_SKIPOWNPROCESS, + EVENT_SYSTEM_MOVESIZEEND, EVENT_SYSTEM_MOVESIZESTART, OBJID_WINDOW, + WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS, }, }, }; diff --git a/packages/wm/src/containers/commands/move_container_within_tree.rs b/packages/wm/src/containers/commands/move_container_within_tree.rs index 3c487f44d..128378b93 100644 --- a/packages/wm/src/containers/commands/move_container_within_tree.rs +++ b/packages/wm/src/containers/commands/move_container_within_tree.rs @@ -43,15 +43,15 @@ pub fn move_container_within_tree( // If the container is already a child of the target parent, then shift // it to the target index. if container_to_move.parent().context("No parent.")? == target_parent { - target_parent - .borrow_children_mut() - .shift_to_index(target_index, container_to_move.clone()); - - if container_to_move.has_focus(None) { - state.emit_event(WmEvent::FocusedContainerMoved { - focused_container: container_to_move.to_dto()?, - }); - } + target_parent + .borrow_children_mut() + .shift_to_index(target_index, container_to_move.clone()); + + if container_to_move.has_focus(None) { + state.emit_event(WmEvent::FocusedContainerMoved { + focused_container: container_to_move.to_dto()?, + }); + } return Ok(()); } diff --git a/packages/wm/src/windows/active_drag.rs b/packages/wm/src/windows/active_drag.rs index 3a980827d..d54035c19 100644 --- a/packages/wm/src/windows/active_drag.rs +++ b/packages/wm/src/windows/active_drag.rs @@ -1,11 +1,11 @@ #[derive(Debug, Clone, Default)] -pub struct ActiveDrag{ - pub operation: Option, - pub is_from_tiling: bool, +pub struct ActiveDrag { + pub operation: Option, + pub is_from_tiling: bool, } #[derive(Debug, Copy, Clone, PartialEq)] pub enum ActiveDragOperation { - Moving, - Resizing, + Moving, + Resizing, } diff --git a/packages/wm/src/windows/commands/manage_window.rs b/packages/wm/src/windows/commands/manage_window.rs index 8d148bec2..413f2500b 100644 --- a/packages/wm/src/windows/commands/manage_window.rs +++ b/packages/wm/src/windows/commands/manage_window.rs @@ -17,7 +17,6 @@ use crate::{ wm_event::WmEvent, wm_state::WmState, }; -use crate::windows::ActiveDrag; pub fn manage_window( native_window: NativeWindow, @@ -127,26 +126,26 @@ fn create_window( let window_container: WindowContainer = match window_state { WindowState::Tiling => TilingWindow::new( - None, - native_window, - None, - border_delta, - floating_placement, - inner_gap, - Vec::new(), - None, + None, + native_window, + None, + border_delta, + floating_placement, + inner_gap, + Vec::new(), + None, ) .into(), _ => NonTilingWindow::new( - None, - native_window, - window_state, - None, - border_delta, - None, - floating_placement, - Vec::new(), - None, + None, + native_window, + window_state, + None, + border_delta, + None, + floating_placement, + Vec::new(), + None, ) .into(), }; diff --git a/packages/wm/src/windows/mod.rs b/packages/wm/src/windows/mod.rs index 2508a6b11..9d4b32447 100644 --- a/packages/wm/src/windows/mod.rs +++ b/packages/wm/src/windows/mod.rs @@ -1,13 +1,13 @@ +mod active_drag; pub mod commands; mod non_tiling_window; mod tiling_window; pub mod traits; mod window_dto; mod window_state; -pub mod active_drag; +pub use active_drag::*; pub use non_tiling_window::*; pub use tiling_window::*; pub use window_dto::*; pub use window_state::*; -pub use active_drag::*; diff --git a/packages/wm/src/windows/non_tiling_window.rs b/packages/wm/src/windows/non_tiling_window.rs index d0890f26e..173c32619 100644 --- a/packages/wm/src/windows/non_tiling_window.rs +++ b/packages/wm/src/windows/non_tiling_window.rs @@ -7,7 +7,9 @@ use std::{ use anyhow::Context; use uuid::Uuid; -use super::{traits::WindowGetters, TilingWindow, WindowDto, WindowState}; +use super::{ + traits::WindowGetters, ActiveDrag, TilingWindow, WindowDto, WindowState, +}; use crate::{ common::{ platform::NativeWindow, DisplayState, LengthValue, Rect, RectDelta, @@ -20,7 +22,6 @@ use crate::{ impl_common_getters, impl_container_debug, impl_window_getters, user_config::WindowRuleConfig, }; -use crate::windows::active_drag::ActiveDrag; #[derive(Clone)] pub struct NonTilingWindow(Rc>); @@ -44,15 +45,15 @@ struct NonTilingWindowInner { impl NonTilingWindow { pub fn new( - id: Option, - native: NativeWindow, - state: WindowState, - prev_state: Option, - border_delta: RectDelta, - insertion_target: Option<(Container, usize)>, - floating_placement: Rect, - done_window_rules: Vec, - active_drag: Option, + id: Option, + native: NativeWindow, + state: WindowState, + prev_state: Option, + border_delta: RectDelta, + insertion_target: Option<(Container, usize)>, + floating_placement: Rect, + done_window_rules: Vec, + active_drag: Option, ) -> Self { let window = NonTilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), @@ -94,7 +95,7 @@ impl NonTilingWindow { self.floating_placement(), inner_gap, self.done_window_rules(), - self.active_drag() + self.active_drag(), ) } diff --git a/packages/wm/src/windows/tiling_window.rs b/packages/wm/src/windows/tiling_window.rs index e39b00859..c0fdd65da 100644 --- a/packages/wm/src/windows/tiling_window.rs +++ b/packages/wm/src/windows/tiling_window.rs @@ -27,8 +27,8 @@ use crate::{ impl_position_getters_as_resizable, impl_tiling_size_getters, impl_window_getters, user_config::WindowRuleConfig, + windows::active_drag::ActiveDrag, }; -use crate::windows::active_drag::{ActiveDrag}; #[derive(Clone)] pub struct TilingWindow(Rc>); @@ -53,14 +53,14 @@ struct TilingWindowInner { impl TilingWindow { pub fn new( - id: Option, - native: NativeWindow, - prev_state: Option, - border_delta: RectDelta, - floating_placement: Rect, - inner_gap: LengthValue, - done_window_rules: Vec, - active_drag: Option, + id: Option, + native: NativeWindow, + prev_state: Option, + border_delta: RectDelta, + floating_placement: Rect, + inner_gap: LengthValue, + done_window_rules: Vec, + active_drag: Option, ) -> Self { let window = TilingWindowInner { id: id.unwrap_or_else(|| Uuid::new_v4()), diff --git a/packages/wm/src/wm_state.rs b/packages/wm/src/wm_state.rs index 6421d3489..21d7baf64 100644 --- a/packages/wm/src/wm_state.rs +++ b/packages/wm/src/wm_state.rs @@ -480,24 +480,21 @@ impl WmState { }) .collect() } - + /// Returns all window under the mouse position - pub fn monitor_at_position( - &self, - position: &Point, - ) -> Option { + pub fn monitor_at_position(&self, position: &Point) -> Option { self - .root_container - .descendants() - .filter_map(|container| match container { - Container::Monitor(monitor) => Some(monitor), - _ => None, - }) - .filter(|c| { - let frame = c.to_rect(); - frame.unwrap().contains_point(&position) - }) - .next() + .root_container + .descendants() + .filter_map(|container| match container { + Container::Monitor(monitor) => Some(monitor), + _ => None, + }) + .filter(|c| { + let frame = c.to_rect(); + frame.unwrap().contains_point(&position) + }) + .next() } }