Skip to content

Commit

Permalink
feat: resizing with the mouse works as before
Browse files Browse the repository at this point in the history
  • Loading branch information
LucaCoduriV committed Jul 31, 2024
1 parent e263886 commit 3e988e8
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 96 deletions.
102 changes: 96 additions & 6 deletions packages/wm/src/common/events/handle_window_location_changed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -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()?;
Expand Down Expand Up @@ -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(())
}
131 changes: 77 additions & 54 deletions packages/wm/src/common/events/handle_window_moved_end.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
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(
moved_window: NonTilingWindow,
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");
Expand All @@ -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)?;
Expand All @@ -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 {
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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<TilingWindow> {
fn get_tiling_window_at_mouse_pos(
exclude_window: &NonTilingWindow,
root_container: RootContainer,
mouse_position: &Point,
) -> Option<TilingWindow> {
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;
Expand All @@ -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,
Expand All @@ -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(),
Expand Down Expand Up @@ -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),
Expand Down
Loading

0 comments on commit 3e988e8

Please sign in to comment.