Skip to content

Commit

Permalink
fix: floating windows being snapped to tiling without dragging
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-berger committed Aug 3, 2024
1 parent 21674fd commit e7d5c4c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 121 deletions.
135 changes: 56 additions & 79 deletions packages/wm/src/common/events/handle_window_location_changed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ use tracing::info;
use crate::{
common::{platform::NativeWindow, Rect},
containers::{
commands::{
attach_container, detach_container, move_container_within_tree,
},
commands::{flatten_split_container, move_container_within_tree},
traits::{CommonGetters, PositionGetters},
Container, WindowContainer,
WindowContainer,
},
user_config::{FloatingStateConfig, FullscreenStateConfig, UserConfig},
windows::{
commands::update_window_state, traits::WindowGetters,
commands::update_window_state, traits::WindowGetters, ActiveDrag,
ActiveDragOperation, TilingWindow, WindowState,
},
wm_state::WmState,
Expand All @@ -30,14 +28,6 @@ pub fn handle_window_location_changed(
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 All @@ -47,6 +37,17 @@ pub fn handle_window_location_changed(
.nearest_monitor(&window.native())
.context("Failed to get workspace of nearest monitor.")?;

// TODO: Include this as part of the `match` statement below.
if let Some(tiling_window) = window.as_tiling_window() {
update_drag_state(
tiling_window.clone(),
&frame_position,
&old_frame_position,
state,
config,
)?;
}

match window.state() {
WindowState::Fullscreen(fullscreen_state) => {
let monitor_rect = if config.has_outer_gaps() {
Expand Down Expand Up @@ -156,80 +157,56 @@ pub fn handle_window_location_changed(
/// 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,
window: &WindowContainer,
fn update_drag_state(
window: TilingWindow,
frame_position: &Rect,
old_frame_position: &Rect,
) -> 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 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));
}
}
}
}
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,
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))?;
}
if let Some(active_drag) = window.active_drag() {
let should_ignore = active_drag.operation.is_some()
|| frame_position == old_frame_position;

if should_ignore {
return Ok(());
}
}

if let Some(mut active_drag) = moved_window.active_drag() {
active_drag.is_from_tiling = true;
moved_window.set_active_drag(Some(active_drag));
let is_move = frame_position.height() == old_frame_position.height()
&& frame_position.width() == old_frame_position.width();

let operation = match is_move {
true => ActiveDragOperation::Moving,
false => ActiveDragOperation::Resizing,
};

window.set_active_drag(Some(ActiveDrag {
operation: Some(operation),
..active_drag
}));

// Transition window to be floating while it's being dragged.
if is_move {
let parent = window.parent().context("No parent")?;

update_window_state(
window.into(),
WindowState::Floating(FloatingStateConfig {
centered: false,
shown_on_top: true,
}),
state,
config,
)?;

// Flatten the parent split container if it only contains the window.
if let Some(split_parent) = parent.as_split() {
if split_parent.child_count() == 1 {
flatten_split_container(split_parent.clone())?;
}
}
}
}

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(())
}
65 changes: 26 additions & 39 deletions packages/wm/src/common/events/handle_window_moved_or_resized_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,57 +53,43 @@ 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();

if let WindowContainer::NonTilingWindow(window) = window {
let has_window_moved = matches!((width_delta, height_delta), (0, 0));

if has_window_moved {
window_moved_end(window, state, config)?;
match &window {
WindowContainer::NonTilingWindow(window) => {
if let Some(active_drag) = window.active_drag() {
if active_drag.is_from_tiling
&& active_drag.operation == Some(ActiveDragOperation::Moving)
{
// We continue only if it's a temporary floating window and if
// the window got moved and not resized.
window_moved_end(window.clone(), state, config)?;
}
}
}
WindowContainer::TilingWindow(window) => {
info!("Tiling window resized");

resize_window(
window.clone().into(),
Some(LengthValue::from_px(width_delta)),
Some(LengthValue::from_px(height_delta)),
state,
)?;
}
} else if let WindowContainer::TilingWindow(window) = window {
window_resized_end(window, state, width_delta, height_delta)?;
}

window.set_active_drag(None);
}

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
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");

info!("Tiling window drag end event.");
let mouse_position = Platform::mouse_position()?;

let window_under_cursor = match get_tiling_window_at_mouse_pos(
Expand Down Expand Up @@ -150,7 +136,6 @@ fn window_moved_end(
tiling_direction,
new_window_position,
)?;
moved_window.set_active_drag(None);

state.pending_sync.containers_to_redraw.push(
window_under_cursor
Expand Down Expand Up @@ -197,12 +182,14 @@ fn on_no_target_window(
state,
)?;
}

update_window_state(
moved_window.as_window_container().unwrap(),
WindowState::Tiling,
state,
config,
)?;

return Ok(());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
common::platform::NativeWindow,
containers::WindowContainer,
windows::{traits::WindowGetters, ActiveDrag},
wm_state::WmState,
};
Expand All @@ -13,8 +12,11 @@ pub fn handle_window_moved_or_resized_start(
) -> anyhow::Result<()> {
let found_window = state.window_from_native(&native_window);

if let Some(WindowContainer::TilingWindow(moved_window)) = found_window {
moved_window.set_active_drag(Some(ActiveDrag::default()));
if let Some(found_window) = found_window {
found_window.set_active_drag(Some(ActiveDrag {
operation: None,
is_from_tiling: found_window.is_tiling_window(),
}));
}

Ok(())
Expand Down

0 comments on commit e7d5c4c

Please sign in to comment.