From 9df450843c84056eaa5a320eb7e0ab36d6917d9a Mon Sep 17 00:00:00 2001 From: Seaotatop Date: Wed, 21 Jun 2023 21:49:20 -0500 Subject: [PATCH] Make tiled windows move like tiled windows --- src/grab/move_grab.rs | 54 +++++++++++++++++++++++++++++++++++++------ src/state.rs | 8 ------- src/window.rs | 35 ++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/grab/move_grab.rs b/src/grab/move_grab.rs index aa5f6da..33d4d61 100644 --- a/src/grab/move_grab.rs +++ b/src/grab/move_grab.rs @@ -10,10 +10,14 @@ use smithay::{ }, SeatHandler, }, - utils::{IsAlive, Logical, Point}, + utils::{IsAlive, Logical, Point, Rectangle}, }; -use crate::{backend::Backend, state::State}; +use crate::{ + backend::Backend, + state::State, + window::window_state::{Float, WindowState}, +}; pub struct MoveSurfaceGrab { pub start_data: GrabStartData, @@ -36,11 +40,47 @@ impl PointerGrab> for MoveSurfaceGrab> { return; } - let delta = event.location - self.start_data.location; - let new_loc = self.initial_window_loc.to_f64() + delta; - data.space - .map_element(self.window.clone(), new_loc.to_i32_round(), true); - data.focus_state.set_focus(self.window.clone()); + let tiled = WindowState::with_state(&self.window, |state| { + matches!(state.floating, Float::Tiled(_)) + }); + + if tiled { + let window_under = data + .space + .elements() + .find(|&win| { + if let Some(loc) = data.space.element_location(win) { + let size = win.geometry().size; + let rect = Rectangle { size, loc }; + rect.contains(event.location.to_i32_round()) + } else { + false + } + }) + .cloned(); + + if let Some(window_under) = window_under { + if window_under == self.window { + return; + } + + let window_under_floating = WindowState::with_state(&window_under, |state| { + matches!(state.floating, Float::Floating) + }); + + if window_under_floating { + return; + } + + tracing::info!("{:?}, {:?}", self.window.geometry(), self.window.bbox()); + data.swap_window_positions(&self.window, &window_under); + } + } else { + let delta = event.location - self.start_data.location; + let new_loc = self.initial_window_loc.to_f64() + delta; + data.space + .map_element(self.window.clone(), new_loc.to_i32_round(), true); + } } fn relative_motion( diff --git a/src/state.rs b/src/state.rs index c93e314..0f65561 100644 --- a/src/state.rs +++ b/src/state.rs @@ -379,14 +379,6 @@ impl State { popup_manager: PopupManager::default(), }) } - - /// Returns the [Window] associated with a given [WlSurface]. - pub fn window_for_surface(&self, surface: &WlSurface) -> Option { - self.space - .elements() - .find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false)) - .cloned() - } } pub struct CalloopData { diff --git a/src/window.rs b/src/window.rs index 967d193..474425f 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,8 +1,9 @@ use std::cell::RefCell; use smithay::{ - desktop::Window, reexports::wayland_server::protocol::wl_surface::WlSurface, - wayland::compositor, + desktop::Window, + reexports::wayland_server::protocol::wl_surface::WlSurface, + wayland::{compositor, seat::WaylandFocus}, }; use crate::{backend::Backend, layout::Layout, state::State}; @@ -26,6 +27,36 @@ pub trait SurfaceState: Default + 'static { } } +impl State { + /// Returns the [Window] associated with a given [WlSurface]. + pub fn window_for_surface(&self, surface: &WlSurface) -> Option { + self.space + .elements() + .find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false)) + .cloned() + } + + pub fn swap_window_positions(&mut self, win1: &Window, win2: &Window) { + let win1_loc = self.space.element_location(win1).unwrap(); // TODO: handle unwraps + let win2_loc = self.space.element_location(win2).unwrap(); + let win1_geo = self.space.element_geometry(win1).unwrap(); + let win2_geo = self.space.element_geometry(win2).unwrap(); + + win1.toplevel().with_pending_state(|state| { + state.size = Some(win2_geo.size); + }); + win2.toplevel().with_pending_state(|state| { + state.size = Some(win1_geo.size); + }); + + self.space.map_element(win1.clone(), win2_loc, false); + self.space.map_element(win2.clone(), win1_loc, false); + + win1.toplevel().send_pending_configure(); + win2.toplevel().send_pending_configure(); + } +} + pub fn toggle_floating(state: &mut State, window: &Window) { WindowState::with_state(window, |window_state| { match window_state.floating {