Make tiled windows move like tiled windows

This commit is contained in:
Seaotatop 2023-06-21 21:49:20 -05:00
parent e701334538
commit 9df450843c
3 changed files with 80 additions and 17 deletions

View file

@ -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<S: SeatHandler> {
pub start_data: GrabStartData<S>,
@ -36,11 +40,47 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
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(

View file

@ -379,14 +379,6 @@ impl<B: Backend> State<B> {
popup_manager: PopupManager::default(),
})
}
/// Returns the [Window] associated with a given [WlSurface].
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
self.space
.elements()
.find(|window| window.wl_surface().map(|s| s == *surface).unwrap_or(false))
.cloned()
}
}
pub struct CalloopData<B: Backend> {

View file

@ -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<B: Backend> State<B> {
/// Returns the [Window] associated with a given [WlSurface].
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
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<B: Backend>(state: &mut State<B>, window: &Window) {
WindowState::with_state(window, |window_state| {
match window_state.floating {