feat: support interactive window move and resize
This commit is contained in:
1 parent
3c1cfe351c
commit
0cc0488257
7 files changed
+660
-13
No files matched your search
@@ -44,7 +44,7 @@ impl CompositorHandler for Ferese {
|
||||
window.on_commit();
|
||||
}
|
||||
}
|
||||
xdg_shell::handle_commit(&mut self.popups, &self.space, surface);
|
||||
xdg_shell::handle_commit(&mut self.popups, &mut self.space, surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,16 @@ use smithay::{
|
||||
desktop::{
|
||||
PopupKind, PopupManager, Space, Window, find_popup_root_surface, get_popup_toplevel_coords,
|
||||
},
|
||||
input::{
|
||||
Seat,
|
||||
pointer::{Focus, GrabStartData},
|
||||
},
|
||||
reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode,
|
||||
reexports::wayland_server::protocol::{wl_seat, wl_surface::WlSurface},
|
||||
utils::Serial,
|
||||
reexports::wayland_server::{
|
||||
Resource,
|
||||
protocol::{wl_seat, wl_surface::WlSurface},
|
||||
},
|
||||
utils::{Rectangle, Serial},
|
||||
wayland::{
|
||||
compositor::with_states,
|
||||
shell::xdg::decoration::XdgDecorationHandler,
|
||||
@@ -15,7 +22,10 @@ use smithay::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::Ferese;
|
||||
use crate::{
|
||||
Ferese,
|
||||
grabs::{MoveSurfaceGrab, ResizeEdge, ResizeSurfaceGrab, handle_resize_commit},
|
||||
};
|
||||
|
||||
impl XdgShellHandler for Ferese {
|
||||
fn xdg_shell_state(&mut self) -> &mut XdgShellState {
|
||||
@@ -48,20 +58,103 @@ impl XdgShellHandler for Ferese {
|
||||
surface.send_repositioned(token);
|
||||
}
|
||||
|
||||
fn move_request(&mut self, _: ToplevelSurface, _: wl_seat::WlSeat, _: Serial) {}
|
||||
fn move_request(&mut self, surface: ToplevelSurface, seat: wl_seat::WlSeat, serial: Serial) {
|
||||
let Some(seat) = Seat::from_resource(&seat) else {
|
||||
return;
|
||||
};
|
||||
let Some(start_data) = check_grab(&seat, surface.wl_surface(), serial) else {
|
||||
return;
|
||||
};
|
||||
let Some(pointer) = seat.get_pointer() else {
|
||||
return;
|
||||
};
|
||||
let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == surface.wl_surface())
|
||||
})
|
||||
.cloned()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(initial_location) = self.space.element_location(&window) else {
|
||||
return;
|
||||
};
|
||||
pointer.set_grab(
|
||||
self,
|
||||
MoveSurfaceGrab {
|
||||
start_data,
|
||||
window,
|
||||
initial_location,
|
||||
},
|
||||
serial,
|
||||
Focus::Clear,
|
||||
);
|
||||
}
|
||||
|
||||
fn resize_request(
|
||||
&mut self,
|
||||
_: ToplevelSurface,
|
||||
_: wl_seat::WlSeat,
|
||||
_: Serial,
|
||||
_: smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
||||
surface: ToplevelSurface,
|
||||
seat: wl_seat::WlSeat,
|
||||
serial: Serial,
|
||||
edges: smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
||||
) {
|
||||
let Some(seat) = Seat::from_resource(&seat) else {
|
||||
return;
|
||||
};
|
||||
let Some(start_data) = check_grab(&seat, surface.wl_surface(), serial) else {
|
||||
return;
|
||||
};
|
||||
let Some(pointer) = seat.get_pointer() else {
|
||||
return;
|
||||
};
|
||||
let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == surface.wl_surface())
|
||||
})
|
||||
.cloned()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Some(location) = self.space.element_location(&window) else {
|
||||
return;
|
||||
};
|
||||
let rect = Rectangle::new(location, window.geometry().size);
|
||||
pointer.set_grab(
|
||||
self,
|
||||
ResizeSurfaceGrab::new(start_data, window, ResizeEdge::from(edges), rect),
|
||||
serial,
|
||||
Focus::Clear,
|
||||
);
|
||||
}
|
||||
|
||||
fn grab(&mut self, _: PopupSurface, _: wl_seat::WlSeat, _: Serial) {}
|
||||
}
|
||||
|
||||
fn check_grab(
|
||||
seat: &Seat<Ferese>,
|
||||
surface: &WlSurface,
|
||||
serial: Serial,
|
||||
) -> Option<GrabStartData<Ferese>> {
|
||||
let pointer = seat.get_pointer()?;
|
||||
if !pointer.has_grab(serial) {
|
||||
return None;
|
||||
}
|
||||
let start_data = pointer.grab_start_data()?;
|
||||
let (focus, _) = start_data.focus.as_ref()?;
|
||||
focus
|
||||
.id()
|
||||
.same_client_as(&surface.id())
|
||||
.then_some(start_data)
|
||||
}
|
||||
|
||||
impl XdgDecorationHandler for Ferese {
|
||||
fn new_decoration(&mut self, toplevel: ToplevelSurface) {
|
||||
set_decoration_mode(&toplevel, Mode::ClientSide);
|
||||
@@ -87,7 +180,8 @@ fn set_decoration_mode(toplevel: &ToplevelSurface, mode: Mode) {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
|
||||
pub fn handle_commit(popups: &mut PopupManager, space: &Space<Window>, surface: &WlSurface) {
|
||||
pub fn handle_commit(popups: &mut PopupManager, space: &mut Space<Window>, surface: &WlSurface) {
|
||||
handle_resize_commit(space, surface);
|
||||
if let Some(window) = space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
|
||||
Reference in new issue
Block a user