Don't pass pointer button events to client when moving or resizing

This commit is contained in:
João Capucho 2024-08-21 21:29:23 +01:00 committed by Victoria Brekenfeld
parent 3c24934f48
commit 66695482d0
2 changed files with 90 additions and 49 deletions

View file

@ -78,6 +78,7 @@ use std::{
any::Any, any::Any,
borrow::Cow, borrow::Cow,
cell::RefCell, cell::RefCell,
collections::HashSet,
os::unix::process::CommandExt, os::unix::process::CommandExt,
thread, thread,
time::{Duration, Instant}, time::{Duration, Instant},
@ -87,6 +88,8 @@ pub mod gestures;
#[derive(Default)] #[derive(Default)]
pub struct SupressedKeys(RefCell<Vec<(Keycode, Option<RegistrationToken>)>>); pub struct SupressedKeys(RefCell<Vec<(Keycode, Option<RegistrationToken>)>>);
#[derive(Default)]
pub struct SupressedButtons(RefCell<HashSet<u32>>);
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ModifiersShortcutQueue(RefCell<Option<shortcuts::Binding>>); pub struct ModifiersShortcutQueue(RefCell<Option<shortcuts::Binding>>);
@ -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 { impl ModifiersShortcutQueue {
pub fn set(&self, binding: shortcuts::Binding) { pub fn set(&self, binding: shortcuts::Binding) {
let mut set = self.0.borrow_mut(); let mut set = self.0.borrow_mut();
@ -773,6 +786,7 @@ impl State {
let serial = SERIAL_COUNTER.next_serial(); let serial = SERIAL_COUNTER.next_serial();
let button = event.button_code(); let button = event.button_code();
let mut pass_event = !seat.supressed_buttons().remove(button);
if event.state() == ButtonState::Pressed { if event.state() == ButtonState::Pressed {
// change the keyboard focus unless the pointer is grabbed // change the keyboard focus unless the pointer is grabbed
// We test for any matching surface type here but always use the root // 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) target.toplevel().map(Cow::into_owned)
{ {
let seat_clone = seat.clone(); let seat_clone = seat.clone();
let button = PointerButtonEvent::button(&event); let mouse_button =
self.common.event_loop_handle.insert_idle( PointerButtonEvent::button(&event);
move |state| {
fn dispatch_grab<G: PointerGrab<State> + 'static>(
grab: Option<(G, smithay::input::pointer::Focus)>,
seat: Seat<State>,
serial: Serial,
state: &mut State)
{
if let Some((target, focus)) = grab {
seat
.modifiers_shortcut_queue()
.clear();
seat let mut supress_button = || {
.get_pointer() // If the logo is held then the pointer event is
.unwrap() // aimed at the compositor and shouldn't be passed
.set_grab( // to the application.
state, target, serial, pass_event = false;
focus, seat.supressed_buttons().add(button);
); };
}
}
let mut shell = fn dispatch_grab<
state.common.shell.write().unwrap(); G: PointerGrab<State> + 'static,
if let Some(button) = button { >(
match button { grab: Option<(
smithay::backend::input::MouseButton::Left => { G,
smithay::input::pointer::Focus,
)>,
seat: Seat<State>,
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( let res = shell.move_request(
&surface, &surface,
&seat_clone, &seat_clone,
@ -888,12 +912,19 @@ impl State {
&state.common.config, &state.common.config,
&state.common.event_loop_handle, &state.common.event_loop_handle,
&state.common.xdg_activation_state, &state.common.xdg_activation_state,
false false,
); );
drop(shell); drop(shell);
dispatch_grab(res, seat_clone, serial, state); 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(target_elem) = shell.element_for_surface(&surface) else { return };
let Some(geom) = shell let Some(geom) = shell
.space_for(target_elem) .space_for(target_elem)
@ -912,17 +943,16 @@ impl State {
&seat_clone, &seat_clone,
serial, serial,
edge, edge,
false false,
); );
drop(shell); drop(shell);
dispatch_grab(res, seat_clone, serial, state); dispatch_grab(res, seat_clone, serial, state);
}, }
_ => {}, );
} },
_ => {},
} }
}, }
);
} }
} }
under = Some(target); under = Some(target);
@ -971,20 +1001,25 @@ impl State {
.set_overview_mode(None, self.common.event_loop_handle.clone()); .set_overview_mode(None, self.common.event_loop_handle.clone());
} }
} }
std::mem::drop(shell); std::mem::drop(shell);
}; };
let ptr = seat.get_pointer().unwrap(); let ptr = seat.get_pointer().unwrap();
ptr.button( if pass_event {
self, ptr.button(
&ButtonEvent { self,
button, &ButtonEvent {
state: event.state(), button,
serial, state: event.state(),
time: event.time_msec(), serial,
}, time: event.time_msec(),
); },
ptr.frame(self); );
ptr.frame(self);
} else if event.state() == ButtonState::Released {
ptr.unset_grab(self, serial, event.time_msec())
}
} }
} }
InputEvent::PointerAxis { event, .. } => { InputEvent::PointerAxis { event, .. } => {

View file

@ -5,7 +5,7 @@ use std::{any::Any, cell::RefCell, collections::HashMap, sync::Mutex, time::Dura
use crate::{ use crate::{
backend::render::cursor::{CursorShape, CursorState}, backend::render::cursor::{CursorShape, CursorState},
config::{xkb_config_to_wl, Config}, config::{xkb_config_to_wl, Config},
input::{ModifiersShortcutQueue, SupressedKeys}, input::{ModifiersShortcutQueue, SupressedButtons, SupressedKeys},
state::State, state::State,
}; };
use smithay::{ use smithay::{
@ -169,6 +169,7 @@ pub fn create_seat(
userdata.insert_if_missing_threadsafe(SeatId::default); userdata.insert_if_missing_threadsafe(SeatId::default);
userdata.insert_if_missing(Devices::default); userdata.insert_if_missing(Devices::default);
userdata.insert_if_missing(SupressedKeys::default); userdata.insert_if_missing(SupressedKeys::default);
userdata.insert_if_missing(SupressedButtons::default);
userdata.insert_if_missing(ModifiersShortcutQueue::default); userdata.insert_if_missing(ModifiersShortcutQueue::default);
userdata.insert_if_missing_threadsafe(SeatMoveGrabState::default); userdata.insert_if_missing_threadsafe(SeatMoveGrabState::default);
userdata.insert_if_missing_threadsafe(SeatMenuGrabState::default); userdata.insert_if_missing_threadsafe(SeatMenuGrabState::default);
@ -215,6 +216,7 @@ pub trait SeatExt {
fn set_active_output(&self, output: &Output); fn set_active_output(&self, output: &Output);
fn devices(&self) -> &Devices; fn devices(&self) -> &Devices;
fn supressed_keys(&self) -> &SupressedKeys; fn supressed_keys(&self) -> &SupressedKeys;
fn supressed_buttons(&self) -> &SupressedButtons;
fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue; fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue;
fn cursor_geometry( fn cursor_geometry(
@ -254,6 +256,10 @@ impl SeatExt for Seat<State> {
self.user_data().get::<SupressedKeys>().unwrap() self.user_data().get::<SupressedKeys>().unwrap()
} }
fn supressed_buttons(&self) -> &SupressedButtons {
self.user_data().get::<SupressedButtons>().unwrap()
}
fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue { fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue {
self.user_data().get::<ModifiersShortcutQueue>().unwrap() self.user_data().get::<ModifiersShortcutQueue>().unwrap()
} }