From 66695482d071f10cb1e863be5b7b07db3a8df024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 21 Aug 2024 21:29:23 +0100 Subject: [PATCH] Don't pass pointer button events to client when moving or resizing --- src/input/mod.rs | 131 ++++++++++++++++++++++++++++----------------- src/shell/seats.rs | 8 ++- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/input/mod.rs b/src/input/mod.rs index 5d47bf0e..a98dd647 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -78,6 +78,7 @@ use std::{ any::Any, borrow::Cow, cell::RefCell, + collections::HashSet, os::unix::process::CommandExt, thread, time::{Duration, Instant}, @@ -87,6 +88,8 @@ pub mod gestures; #[derive(Default)] pub struct SupressedKeys(RefCell)>>); +#[derive(Default)] +pub struct SupressedButtons(RefCell>); #[derive(Default, Debug)] pub struct ModifiersShortcutQueue(RefCell>); @@ -116,6 +119,16 @@ impl SupressedKeys { } } +impl SupressedButtons { + fn add(&self, button: u32) { + self.0.borrow_mut().insert(button); + } + + fn remove(&self, button: u32) -> bool { + self.0.borrow_mut().remove(&button) + } +} + impl ModifiersShortcutQueue { pub fn set(&self, binding: shortcuts::Binding) { let mut set = self.0.borrow_mut(); @@ -773,6 +786,7 @@ impl State { let serial = SERIAL_COUNTER.next_serial(); let button = event.button_code(); + let mut pass_event = !seat.supressed_buttons().remove(button); if event.state() == ButtonState::Pressed { // change the keyboard focus unless the pointer is grabbed // We test for any matching surface type here but always use the root @@ -850,35 +864,45 @@ impl State { target.toplevel().map(Cow::into_owned) { let seat_clone = seat.clone(); - let button = PointerButtonEvent::button(&event); - self.common.event_loop_handle.insert_idle( - move |state| { - fn dispatch_grab + 'static>( - grab: Option<(G, smithay::input::pointer::Focus)>, - seat: Seat, - serial: Serial, - state: &mut State) - { - if let Some((target, focus)) = grab { - seat - .modifiers_shortcut_queue() - .clear(); + let mouse_button = + PointerButtonEvent::button(&event); - seat - .get_pointer() - .unwrap() - .set_grab( - state, target, serial, - focus, - ); - } - } + let mut supress_button = || { + // If the logo is held then the pointer event is + // aimed at the compositor and shouldn't be passed + // to the application. + pass_event = false; + seat.supressed_buttons().add(button); + }; - let mut shell = - state.common.shell.write().unwrap(); - if let Some(button) = button { - match button { - smithay::backend::input::MouseButton::Left => { + fn dispatch_grab< + G: PointerGrab + 'static, + >( + grab: Option<( + G, + smithay::input::pointer::Focus, + )>, + seat: Seat, + serial: Serial, + state: &mut State, + ) { + if let Some((target, focus)) = grab { + seat.modifiers_shortcut_queue().clear(); + + seat.get_pointer() + .unwrap() + .set_grab(state, target, serial, focus); + } + } + + if let Some(mouse_button) = mouse_button { + match mouse_button { + smithay::backend::input::MouseButton::Left => { + supress_button(); + self.common.event_loop_handle.insert_idle( + move |state| { + let mut shell = + state.common.shell.write().unwrap(); let res = shell.move_request( &surface, &seat_clone, @@ -888,12 +912,19 @@ impl State { &state.common.config, &state.common.event_loop_handle, &state.common.xdg_activation_state, - false + false, ); drop(shell); dispatch_grab(res, seat_clone, serial, state); - }, - smithay::backend::input::MouseButton::Right => { + } + ); + }, + smithay::backend::input::MouseButton::Right => { + supress_button(); + self.common.event_loop_handle.insert_idle( + move |state| { + let mut shell = + state.common.shell.write().unwrap(); let Some(target_elem) = shell.element_for_surface(&surface) else { return }; let Some(geom) = shell .space_for(target_elem) @@ -912,17 +943,16 @@ impl State { &seat_clone, serial, edge, - false + false, ); drop(shell); dispatch_grab(res, seat_clone, serial, state); - }, - _ => {}, - } - - } - }, - ); + } + ); + }, + _ => {}, + } + } } } under = Some(target); @@ -971,20 +1001,25 @@ impl State { .set_overview_mode(None, self.common.event_loop_handle.clone()); } } + std::mem::drop(shell); }; let ptr = seat.get_pointer().unwrap(); - ptr.button( - self, - &ButtonEvent { - button, - state: event.state(), - serial, - time: event.time_msec(), - }, - ); - ptr.frame(self); + if pass_event { + ptr.button( + self, + &ButtonEvent { + button, + state: event.state(), + serial, + time: event.time_msec(), + }, + ); + ptr.frame(self); + } else if event.state() == ButtonState::Released { + ptr.unset_grab(self, serial, event.time_msec()) + } } } InputEvent::PointerAxis { event, .. } => { diff --git a/src/shell/seats.rs b/src/shell/seats.rs index d42941df..ab01fb9f 100644 --- a/src/shell/seats.rs +++ b/src/shell/seats.rs @@ -5,7 +5,7 @@ use std::{any::Any, cell::RefCell, collections::HashMap, sync::Mutex, time::Dura use crate::{ backend::render::cursor::{CursorShape, CursorState}, config::{xkb_config_to_wl, Config}, - input::{ModifiersShortcutQueue, SupressedKeys}, + input::{ModifiersShortcutQueue, SupressedButtons, SupressedKeys}, state::State, }; use smithay::{ @@ -169,6 +169,7 @@ pub fn create_seat( userdata.insert_if_missing_threadsafe(SeatId::default); userdata.insert_if_missing(Devices::default); userdata.insert_if_missing(SupressedKeys::default); + userdata.insert_if_missing(SupressedButtons::default); userdata.insert_if_missing(ModifiersShortcutQueue::default); userdata.insert_if_missing_threadsafe(SeatMoveGrabState::default); userdata.insert_if_missing_threadsafe(SeatMenuGrabState::default); @@ -215,6 +216,7 @@ pub trait SeatExt { fn set_active_output(&self, output: &Output); fn devices(&self) -> &Devices; fn supressed_keys(&self) -> &SupressedKeys; + fn supressed_buttons(&self) -> &SupressedButtons; fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue; fn cursor_geometry( @@ -254,6 +256,10 @@ impl SeatExt for Seat { self.user_data().get::().unwrap() } + fn supressed_buttons(&self) -> &SupressedButtons { + self.user_data().get::().unwrap() + } + fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue { self.user_data().get::().unwrap() }