From 4b70cb40e0ff9c80081c48e37f1b8b8e0bfa1fde Mon Sep 17 00:00:00 2001 From: Samuel Onoja Date: Tue, 29 Sep 2026 15:51:51 +0100 Subject: [PATCH] Move and resize floating windows with the Super button --- compositor/src/input.rs | 108 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/compositor/src/input.rs b/compositor/src/input.rs index c69ccde..0ae4973 100644 --- a/compositor/src/input.rs +++ b/compositor/src/input.rs @@ -11,12 +11,16 @@ use smithay::{ input::{ keyboard::{FilterResult, keysyms}, pointer::{ - AxisFrame, ButtonEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, - GestureSwipeUpdateEvent, MotionEvent, PointerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent, Focus, GestureSwipeBeginEvent, GestureSwipeEndEvent, + GestureSwipeUpdateEvent, GrabStartData, MotionEvent, PointerHandle, + RelativeMotionEvent, }, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, }, - reexports::wayland_server::protocol::wl_surface::WlSurface, + reexports::{ + wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge as XdgResizeEdge, + wayland_server::protocol::wl_surface::WlSurface, + }, utils::{Logical, Point, SERIAL_COUNTER, Serial}, wayland::{ keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat, @@ -24,7 +28,14 @@ use smithay::{ }, }; -use crate::{Ferese, config::BindingAction}; +use crate::{ + Ferese, + config::BindingAction, + grabs::{MoveSurfaceGrab, ResizeEdge, ResizeSurfaceGrab}, +}; + +const BTN_LEFT: u32 = 0x110; +const BTN_RIGHT: u32 = 0x111; impl Ferese { pub fn process_input_event(&mut self, event: InputEvent) { @@ -336,6 +347,22 @@ impl Ferese { return; } + if event.state() == ButtonState::Pressed + && self.start_floating_pointer_grab(&pointer, event.button_code(), serial) + { + pointer.button( + self, + &ButtonEvent { + button: event.button_code(), + state: event.state(), + serial, + time: event.time() as u32, + }, + ); + pointer.frame(self); + return; + } + if event.state() == ButtonState::Pressed && !pointer.is_grabbed() { self.focus_window_at(pointer.current_location(), serial, true); } @@ -457,6 +484,79 @@ impl Ferese { } } + fn start_floating_pointer_grab( + &mut self, + pointer: &PointerHandle, + button: u32, + serial: Serial, + ) -> bool { + if self.session_lock.active + || pointer.is_grabbed() + || !matches!(button, BTN_LEFT | BTN_RIGHT) + || !self + .seat + .get_keyboard() + .is_some_and(|keyboard| keyboard.modifier_state().logo) + { + return false; + } + + let location = pointer.current_location(); + if self.layer_under(location).is_some() { + return false; + } + let Some(window) = self.window_under_visual(location) else { + return false; + }; + if !self.is_floating_window(&window) { + return false; + } + let Some(rect) = self.visual_rect_for_window(&window) else { + return false; + }; + + self.focus_window_at(location, serial, true); + let start_data = GrabStartData { + focus: None, + button, + location, + }; + + if button == BTN_LEFT { + pointer.set_grab( + self, + MoveSurfaceGrab { + start_data, + window, + initial_location: rect.loc, + initial_size: rect.size, + finished: false, + }, + serial, + Focus::Clear, + ); + } else { + let horizontal_right = + location.x >= f64::from(rect.loc.x) + f64::from(rect.size.w) / 2.0; + let vertical_bottom = + location.y >= f64::from(rect.loc.y) + f64::from(rect.size.h) / 2.0; + let edge = match (horizontal_right, vertical_bottom) { + (false, false) => XdgResizeEdge::TopLeft, + (true, false) => XdgResizeEdge::TopRight, + (false, true) => XdgResizeEdge::BottomLeft, + (true, true) => XdgResizeEdge::BottomRight, + }; + pointer.set_grab( + self, + ResizeSurfaceGrab::new(start_data, window, ResizeEdge::from(edge), rect), + serial, + Focus::Clear, + ); + } + + true + } + fn absolute_event_position(&self, event: &E) -> Option> where I: InputBackend,