From e7e9b768c84c4cabe948dd1c004628941d7be544 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 5 Sep 2023 10:55:23 -0700 Subject: [PATCH 1/3] Update Smithay, adjusting for API changes The main changes are those related to pointer gestures. Which are a bit verbose but not too difficult. --- Cargo.lock | 31 +-- Cargo.toml | 2 +- src/backend/kms/mod.rs | 23 ++- src/backend/winit.rs | 4 +- src/backend/x11.rs | 4 +- src/shell/element/mod.rs | 128 +++++++++++- src/shell/element/stack.rs | 113 ++++++++++- src/shell/element/surface.rs | 233 ++++++++++++++++------ src/shell/element/window.rs | 106 +++++++++- src/shell/focus/target.rs | 216 +++++++++++++++++++- src/shell/grabs/mod.rs | 102 +++++++++- src/shell/grabs/moving.rs | 79 +++++++- src/shell/layout/floating/grabs/resize.rs | 78 +++++++- src/shell/layout/tiling/grabs/resize.rs | 87 +++++++- src/utils/iced.rs | 64 +++++- 15 files changed, 1151 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e5359f7..e2ce436c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1063,17 +1063,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - [[package]] name = "errno" version = "0.3.2" @@ -2230,13 +2219,13 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libseat" -version = "0.1.7" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "845e5c255462c9bc7c71c17b996766b76e3c66f2ddd5846bfbc83f18382aa648" +checksum = "54a0adf8d8607a73a5b74cbe4132f57cb349e4bf860103cd089461bbcbc9907e" dependencies = [ - "errno 0.2.8", + "errno", "libseat-sys", - "slog", + "log", ] [[package]] @@ -3579,7 +3568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags 1.3.2", - "errno 0.3.2", + "errno", "io-lifetimes", "libc", "linux-raw-sys 0.3.8", @@ -3593,7 +3582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ "bitflags 2.3.3", - "errno 0.3.2", + "errno", "libc", "linux-raw-sys 0.4.3", "windows-sys 0.48.0", @@ -3754,12 +3743,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slog" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" - [[package]] name = "slotmap" version = "1.0.6" @@ -3778,7 +3761,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=02ccc8ca17#02ccc8ca17fbc655d2247124fe628d276cb5179a" +source = "git+https://github.com/smithay//smithay?rev=36a0ec69b1#36a0ec69b1a2331b1a2d0e046b026cb85d7d132c" dependencies = [ "appendlist", "ash", diff --git a/Cargo.toml b/Cargo.toml index 8d7bec91..9dd2803c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,4 +87,4 @@ debug = true lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = { git = "https://github.com/smithay//smithay", rev = "02ccc8ca17" } +smithay = { git = "https://github.com/smithay//smithay", rev = "36a0ec69b1" } diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 305baeb5..d1051649 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -507,7 +507,11 @@ impl State { surface .output .current_mode() - .map(|mode| mode.refresh as u32) + .map(|mode| { + Duration::from_secs_f64( + 1_000.0 / mode.refresh as f64, + ) + }) .unwrap_or_default(), seq as u64, flags, @@ -1002,19 +1006,20 @@ fn get_surface_dmabuf_feedback( .collect::>(); let surface = compositor.surface(); - let planes = surface.planes().unwrap(); + let planes = surface.planes(); // We limit the scan-out trache to formats we can also render from // so that there is always a fallback render path available in case // the supplied buffer can not be scanned out directly - let planes_formats = surface - .supported_formats(planes.primary.handle) - .unwrap() - .into_iter() + let planes_formats = planes + .primary + .formats + .iter() + .cloned() .chain( planes .overlay .iter() - .flat_map(|p| surface.supported_formats(p.handle).unwrap()), + .flat_map(|p| p.formats.iter().cloned()), ) .collect::>() .intersection(&combined_formats) @@ -1330,9 +1335,7 @@ impl KmsState { let driver = drm .get_driver() .with_context(|| "Failed to query drm driver")?; - let mut planes = drm_surface - .planes() - .with_context(|| "Failed to query drm planes")?; + let mut planes = drm_surface.planes().clone(); // QUIRK: Using an overlay plane on a nvidia card breaks the display controller (wtf...) if driver .name() diff --git a/src/backend/winit.rs b/src/backend/winit.rs index afba09d8..9d7f3435 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -30,7 +30,7 @@ use smithay::{ utils::Transform, wayland::dmabuf::DmabufFeedbackBuilder, }; -use std::cell::RefCell; +use std::{cell::RefCell, time::Duration}; use tracing::{error, info, warn}; #[cfg(feature = "debug")] @@ -94,7 +94,7 @@ impl WinitState { state.clock.now(), self.output .current_mode() - .map(|mode| mode.refresh as u32) + .map(|mode| Duration::from_secs_f64(1_000.0 / mode.refresh as f64)) .unwrap_or_default(), 0, wp_presentation_feedback::Kind::Vsync, diff --git a/src/backend/x11.rs b/src/backend/x11.rs index 0d133b46..65a825bd 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -39,7 +39,7 @@ use smithay::{ utils::{DeviceFd, Transform}, wayland::dmabuf::DmabufFeedbackBuilder, }; -use std::{cell::RefCell, os::unix::io::OwnedFd}; +use std::{cell::RefCell, os::unix::io::OwnedFd, time::Duration}; use tracing::{debug, error, info, warn}; #[cfg(feature = "debug")] @@ -260,7 +260,7 @@ impl Surface { state.clock.now(), self.output .current_mode() - .map(|mode| mode.refresh as u32) + .map(|mode| Duration::from_secs_f64(1_000.0 / mode.refresh as f64)) .unwrap_or_default(), 0, wp_presentation_feedback::Kind::Vsync, diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 075d1a3b..c4cd1777 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -25,7 +25,12 @@ use smithay::{ desktop::{space::SpaceElement, PopupManager, WindowSurfaceType}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent}, + pointer::{ + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerTarget, RelativeMotionEvent, + }, Seat, }, output::Output, @@ -909,6 +914,127 @@ impl PointerTarget for CosmicMapped { _ => {} } } + fn gesture_swipe_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeBeginEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_swipe_begin(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_swipe_begin(w, seat, data, event) + } + _ => {} + } + } + fn gesture_swipe_update( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeUpdateEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_swipe_update(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_swipe_update(w, seat, data, event) + } + _ => {} + } + } + fn gesture_swipe_end( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeEndEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_swipe_end(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_swipe_end(w, seat, data, event) + } + _ => {} + } + } + fn gesture_pinch_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchBeginEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_pinch_begin(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_pinch_begin(w, seat, data, event) + } + _ => {} + } + } + fn gesture_pinch_update( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchUpdateEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_pinch_update(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_pinch_update(w, seat, data, event) + } + _ => {} + } + } + fn gesture_pinch_end( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchEndEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_pinch_end(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_pinch_end(w, seat, data, event) + } + _ => {} + } + } + fn gesture_hold_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureHoldBeginEvent, + ) { + match &self.element { + CosmicMappedInternal::Stack(s) => { + PointerTarget::gesture_hold_begin(s, seat, data, event) + } + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_hold_begin(w, seat, data, event) + } + _ => {} + } + } + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + match &self.element { + CosmicMappedInternal::Stack(s) => PointerTarget::gesture_hold_end(s, seat, data, event), + CosmicMappedInternal::Window(w) => { + PointerTarget::gesture_hold_end(w, seat, data, event) + } + _ => {} + } + } } impl WaylandFocus for CosmicMapped { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index eed954d1..ec8c6758 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -32,8 +32,10 @@ use smithay::{ input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, - PointerTarget, RelativeMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, PointerTarget, RelativeMotionEvent, }, Seat, }, @@ -1179,6 +1181,113 @@ impl PointerTarget for CosmicStack { _ => {} } } + + fn gesture_swipe_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeBeginEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_swipe_begin(seat, data, event) + } + }) + } + + fn gesture_swipe_update( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeUpdateEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_swipe_update(seat, data, event) + } + }) + } + + fn gesture_swipe_end( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeEndEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_swipe_end(seat, data, event) + } + }) + } + + fn gesture_pinch_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchBeginEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_pinch_begin(seat, data, event) + } + }) + } + + fn gesture_pinch_update( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchUpdateEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_pinch_update(seat, data, event) + } + }) + } + + fn gesture_pinch_end( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchEndEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_pinch_end(seat, data, event) + } + }) + } + + fn gesture_hold_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureHoldBeginEvent, + ) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_hold_begin(seat, data, event) + } + }) + } + + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + self.0.with_program(|p| { + if p.current_focus() == Focus::Window { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.gesture_hold_end(seat, data, event) + } + }) + } } render_elements! { diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index e0cd6414..a7533cdf 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -17,7 +17,16 @@ use smithay::{ }, PopupManager, Window, }, - input::{keyboard::KeyboardTarget, pointer::PointerTarget}, + input::{ + keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, + pointer::{ + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerTarget, RelativeMotionEvent, + }, + Seat, + }, output::Output, reexports::{ wayland_protocols::{ @@ -34,12 +43,15 @@ use smithay::{ wayland::{ compositor::{with_states, SurfaceData}, seat::WaylandFocus, - shell::xdg::{ToplevelSurface, XdgToplevelSurfaceData}, + shell::xdg::{SurfaceCachedState, ToplevelSurface, XdgToplevelSurfaceData}, }, xwayland::{xwm::X11Relatable, X11Surface}, }; -use crate::{state::SurfaceDmabufFeedback, wayland::handlers::decoration::PreferredDecorationMode}; +use crate::{ + state::{State, SurfaceDmabufFeedback}, + wayland::handlers::decoration::PreferredDecorationMode, +}; space_elements! { #[derive(Debug, Clone, PartialEq)] @@ -363,13 +375,7 @@ impl CosmicSurface { match self { CosmicSurface::Wayland(window) => { Some(with_states(window.toplevel().wl_surface(), |states| { - let attrs = states - .data_map - .get::() - .unwrap() - .lock() - .unwrap(); - attrs.min_size + states.cached_state.current::().min_size })) .filter(|size| !(size.w == 0 && size.h == 0)) } @@ -389,13 +395,7 @@ impl CosmicSurface { match self { CosmicSurface::Wayland(window) => { Some(with_states(window.toplevel().wl_surface(), |states| { - let attrs = states - .data_map - .get::() - .unwrap() - .lock() - .unwrap(); - attrs.max_size + states.cached_state.current::().max_size })) .filter(|size| !(size.w == 0 && size.h == 0)) } @@ -638,12 +638,12 @@ impl CosmicSurface { } } -impl KeyboardTarget for CosmicSurface { +impl KeyboardTarget for CosmicSurface { fn enter( &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - keys: Vec>, + seat: &Seat, + data: &mut State, + keys: Vec>, serial: smithay::utils::Serial, ) { match self { @@ -657,12 +657,7 @@ impl KeyboardTarget for CosmicSurface { } } - fn leave( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - serial: smithay::utils::Serial, - ) { + fn leave(&self, seat: &Seat, data: &mut State, serial: smithay::utils::Serial) { match self { CosmicSurface::Wayland(window) => KeyboardTarget::leave(window, seat, data, serial), CosmicSurface::X11(surface) => KeyboardTarget::leave(surface, seat, data, serial), @@ -672,9 +667,9 @@ impl KeyboardTarget for CosmicSurface { fn key( &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - key: smithay::input::keyboard::KeysymHandle<'_>, + seat: &Seat, + data: &mut State, + key: KeysymHandle<'_>, state: smithay::backend::input::KeyState, serial: smithay::utils::Serial, time: u32, @@ -692,9 +687,9 @@ impl KeyboardTarget for CosmicSurface { fn modifiers( &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - modifiers: smithay::input::keyboard::ModifiersState, + seat: &Seat, + data: &mut State, + modifiers: ModifiersState, serial: smithay::utils::Serial, ) { match self { @@ -709,13 +704,8 @@ impl KeyboardTarget for CosmicSurface { } } -impl PointerTarget for CosmicSurface { - fn enter( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - event: &smithay::input::pointer::MotionEvent, - ) { +impl PointerTarget for CosmicSurface { + fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { CosmicSurface::Wayland(window) => PointerTarget::enter(window, seat, data, event), CosmicSurface::X11(surface) => PointerTarget::enter(surface, seat, data, event), @@ -723,12 +713,7 @@ impl PointerTarget for CosmicSurface { } } - fn motion( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - event: &smithay::input::pointer::MotionEvent, - ) { + fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { match self { CosmicSurface::Wayland(window) => PointerTarget::motion(window, seat, data, event), CosmicSurface::X11(surface) => PointerTarget::motion(surface, seat, data, event), @@ -736,12 +721,7 @@ impl PointerTarget for CosmicSurface { } } - fn relative_motion( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - event: &smithay::input::pointer::RelativeMotionEvent, - ) { + fn relative_motion(&self, seat: &Seat, data: &mut State, event: &RelativeMotionEvent) { match self { CosmicSurface::Wayland(window) => { PointerTarget::relative_motion(window, seat, data, event) @@ -753,12 +733,7 @@ impl PointerTarget for CosmicSurface { } } - fn button( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - event: &smithay::input::pointer::ButtonEvent, - ) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { match self { CosmicSurface::Wayland(window) => PointerTarget::button(window, seat, data, event), CosmicSurface::X11(surface) => PointerTarget::button(surface, seat, data, event), @@ -766,12 +741,7 @@ impl PointerTarget for CosmicSurface { } } - fn axis( - &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, - frame: smithay::input::pointer::AxisFrame, - ) { + fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { match self { CosmicSurface::Wayland(window) => PointerTarget::axis(window, seat, data, frame), CosmicSurface::X11(surface) => PointerTarget::axis(surface, seat, data, frame), @@ -781,8 +751,8 @@ impl PointerTarget for CosmicSurface { fn leave( &self, - seat: &smithay::input::Seat, - data: &mut crate::state::State, + seat: &Seat, + data: &mut State, serial: smithay::utils::Serial, time: u32, ) { @@ -794,6 +764,137 @@ impl PointerTarget for CosmicSurface { _ => unreachable!(), } } + + fn gesture_swipe_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeBeginEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_swipe_begin(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_swipe_begin(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_swipe_update( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeUpdateEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_swipe_update(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_swipe_update(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_swipe_end( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeEndEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_swipe_end(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_swipe_end(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_pinch_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchBeginEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_pinch_begin(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_pinch_begin(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_pinch_update( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchUpdateEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_pinch_update(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_pinch_update(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_pinch_end( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchEndEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_pinch_end(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_pinch_end(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_hold_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureHoldBeginEvent, + ) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_hold_begin(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_hold_begin(surface, seat, data, event) + } + _ => unreachable!(), + } + } + + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + match self { + CosmicSurface::Wayland(window) => { + PointerTarget::gesture_hold_end(window, seat, data, event) + } + CosmicSurface::X11(surface) => { + PointerTarget::gesture_hold_end(surface, seat, data, event) + } + _ => unreachable!(), + } + } } impl WaylandFocus for CosmicSurface { diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index ef6634b5..569ddec2 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -24,7 +24,12 @@ use smithay::{ desktop::space::SpaceElement, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent}, + pointer::{ + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerTarget, RelativeMotionEvent, + }, Seat, }, output::Output, @@ -590,6 +595,105 @@ impl PointerTarget for CosmicWindow { _ => {} } } + + fn gesture_swipe_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeBeginEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_swipe_begin(&p.window, seat, data, event) + } + }) + } + + fn gesture_swipe_update( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeUpdateEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_swipe_update(&p.window, seat, data, event) + } + }) + } + + fn gesture_swipe_end( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeEndEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_swipe_end(&p.window, seat, data, event) + } + }) + } + + fn gesture_pinch_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchBeginEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_pinch_begin(&p.window, seat, data, event) + } + }) + } + + fn gesture_pinch_update( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchUpdateEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_pinch_update(&p.window, seat, data, event) + } + }) + } + + fn gesture_pinch_end( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchEndEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_pinch_end(&p.window, seat, data, event) + } + }) + } + + fn gesture_hold_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureHoldBeginEvent, + ) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_hold_begin(&p.window, seat, data, event) + } + }) + } + + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + self.0.with_program(|p| { + if !p.has_ssd(false) || p.current_focus() == Focus::Window { + PointerTarget::gesture_hold_end(&p.window, seat, data, event) + } + }) + } } render_elements! { diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 26efabe7..2c11a8fa 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -11,7 +11,12 @@ use smithay::{ desktop::{LayerSurface, PopupKind}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent}, + pointer::{ + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerTarget, RelativeMotionEvent, + }, Seat, }, output::WeakOutput, @@ -198,6 +203,215 @@ impl PointerTarget for PointerFocusTarget { PointerFocusTarget::ResizeFork(f) => PointerTarget::leave(f, seat, data, serial, time), } } + fn gesture_swipe_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeBeginEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_swipe_begin(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_swipe_begin(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_swipe_begin(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_swipe_begin(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_swipe_begin(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_swipe_begin(f, seat, data, event) + } + } + } + fn gesture_swipe_update( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeUpdateEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_swipe_update(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_swipe_update(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_swipe_update(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_swipe_update(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_swipe_update(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_swipe_update(f, seat, data, event) + } + } + } + fn gesture_swipe_end( + &self, + seat: &Seat, + data: &mut State, + event: &GestureSwipeEndEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_swipe_end(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_swipe_end(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_swipe_end(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_swipe_end(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_swipe_end(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_swipe_end(f, seat, data, event) + } + } + } + fn gesture_pinch_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchBeginEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_pinch_begin(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_pinch_begin(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_pinch_begin(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_pinch_begin(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_pinch_begin(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_pinch_begin(f, seat, data, event) + } + } + } + fn gesture_pinch_update( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchUpdateEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_pinch_update(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_pinch_update(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_pinch_update(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_pinch_update(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_pinch_update(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_pinch_update(f, seat, data, event) + } + } + } + fn gesture_pinch_end( + &self, + seat: &Seat, + data: &mut State, + event: &GesturePinchEndEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_pinch_end(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_pinch_end(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_pinch_end(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_pinch_end(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_pinch_end(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_pinch_end(f, seat, data, event) + } + } + } + fn gesture_hold_begin( + &self, + seat: &Seat, + data: &mut State, + event: &GestureHoldBeginEvent, + ) { + match self { + PointerFocusTarget::Element(w) => { + PointerTarget::gesture_hold_begin(w, seat, data, event) + } + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_hold_begin(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_hold_begin(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_hold_begin(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_hold_begin(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_hold_begin(f, seat, data, event) + } + } + } + fn gesture_hold_end(&self, seat: &Seat, data: &mut State, event: &GestureHoldEndEvent) { + match self { + PointerFocusTarget::Element(w) => PointerTarget::gesture_hold_end(w, seat, data, event), + PointerFocusTarget::Fullscreen(w) => { + PointerTarget::gesture_hold_end(w, seat, data, event) + } + PointerFocusTarget::LayerSurface(l) => { + PointerTarget::gesture_hold_end(l, seat, data, event) + } + PointerFocusTarget::Popup(p) => { + PointerTarget::gesture_hold_end(p.wl_surface(), seat, data, event) + } + PointerFocusTarget::OverrideRedirect(s) => { + PointerTarget::gesture_hold_end(s, seat, data, event) + } + PointerFocusTarget::ResizeFork(f) => { + PointerTarget::gesture_hold_end(f, seat, data, event) + } + } + } } impl KeyboardTarget for KeyboardFocusTarget { diff --git a/src/shell/grabs/mod.rs b/src/shell/grabs/mod.rs index 35a8d094..f5f9fb7f 100644 --- a/src/shell/grabs/mod.rs +++ b/src/shell/grabs/mod.rs @@ -1,7 +1,9 @@ use smithay::{ input::pointer::{ - AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, - PointerInnerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, reexports::wayland_protocols::xdg::shell::server::xdg_toplevel, utils::{Logical, Point}, @@ -150,6 +152,102 @@ impl PointerGrab for ResizeGrab { } } + fn gesture_swipe_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeBeginEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_swipe_begin(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_swipe_begin(data, handle, event), + } + } + + fn gesture_swipe_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeUpdateEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_swipe_update(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_swipe_update(data, handle, event), + } + } + + fn gesture_swipe_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeEndEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_swipe_end(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_swipe_end(data, handle, event), + } + } + + fn gesture_pinch_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchBeginEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_pinch_begin(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_pinch_begin(data, handle, event), + } + } + + fn gesture_pinch_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchUpdateEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_pinch_update(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_pinch_update(data, handle, event), + } + } + + fn gesture_pinch_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchEndEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_pinch_end(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_pinch_end(data, handle, event), + } + } + + fn gesture_hold_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldBeginEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_hold_begin(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_hold_begin(data, handle, event), + } + } + + fn gesture_hold_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldEndEvent, + ) { + match self { + ResizeGrab::Floating(grab) => grab.gesture_hold_end(data, handle, event), + ResizeGrab::Tiling(grab) => grab.gesture_hold_end(data, handle, event), + } + } + fn start_data(&self) -> &PointerGrabStartData { match self { ResizeGrab::Floating(grab) => grab.start_data(), diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 6d277fc6..69857391 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -25,8 +25,11 @@ use smithay::{ desktop::space::SpaceElement, input::{ pointer::{ - AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, - PointerGrab, PointerInnerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + RelativeMotionEvent, }, Seat, }, @@ -308,6 +311,78 @@ impl PointerGrab for MoveGrab { handle.axis(state, details); } + fn gesture_swipe_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeBeginEvent, + ) { + handle.gesture_swipe_begin(data, event) + } + + fn gesture_swipe_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeUpdateEvent, + ) { + handle.gesture_swipe_update(data, event) + } + + fn gesture_swipe_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeEndEvent, + ) { + handle.gesture_swipe_end(data, event) + } + + fn gesture_pinch_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchBeginEvent, + ) { + handle.gesture_pinch_begin(data, event) + } + + fn gesture_pinch_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchUpdateEvent, + ) { + handle.gesture_pinch_update(data, event) + } + + fn gesture_pinch_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchEndEvent, + ) { + handle.gesture_pinch_end(data, event) + } + + fn gesture_hold_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldBeginEvent, + ) { + handle.gesture_hold_begin(data, event) + } + + fn gesture_hold_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldEndEvent, + ) { + handle.gesture_hold_end(data, event) + } + fn start_data(&self) -> &PointerGrabStartData { &self.start_data } diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index a1c75262..93e986aa 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -9,8 +9,10 @@ use crate::{ use smithay::{ desktop::space::SpaceElement, input::pointer::{ - AxisFrame, ButtonEvent, GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, - PointerInnerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, utils::{IsAlive, Logical, Point, Rectangle, Size}, }; @@ -162,6 +164,78 @@ impl PointerGrab for ResizeSurfaceGrab { handle.axis(data, details) } + fn gesture_swipe_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeBeginEvent, + ) { + handle.gesture_swipe_begin(data, event) + } + + fn gesture_swipe_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeUpdateEvent, + ) { + handle.gesture_swipe_update(data, event) + } + + fn gesture_swipe_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeEndEvent, + ) { + handle.gesture_swipe_end(data, event) + } + + fn gesture_pinch_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchBeginEvent, + ) { + handle.gesture_pinch_begin(data, event) + } + + fn gesture_pinch_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchUpdateEvent, + ) { + handle.gesture_pinch_update(data, event) + } + + fn gesture_pinch_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchEndEvent, + ) { + handle.gesture_pinch_end(data, event) + } + + fn gesture_hold_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldBeginEvent, + ) { + handle.gesture_hold_begin(data, event) + } + + fn gesture_hold_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldEndEvent, + ) { + handle.gesture_hold_end(data, event) + } + fn start_data(&self) -> &PointerGrabStartData { &self.start_data } diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index f5cbb694..1c45eebc 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -10,8 +10,11 @@ use smithay::{ backend::input::ButtonState, input::{ pointer::{ - AxisFrame, ButtonEvent, Focus, GrabStartData as PointerGrabStartData, MotionEvent, - PointerGrab, PointerInnerHandle, PointerTarget, RelativeMotionEvent, + AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + PointerTarget, RelativeMotionEvent, }, Seat, }, @@ -99,6 +102,14 @@ impl PointerTarget for ResizeForkTarget { ) { } fn axis(&self, _seat: &Seat, _data: &mut State, _frame: AxisFrame) {} + fn gesture_swipe_begin(&self, _: &Seat, _: &mut State, _: &GestureSwipeBeginEvent) {} + fn gesture_swipe_update(&self, _: &Seat, _: &mut State, _: &GestureSwipeUpdateEvent) {} + fn gesture_swipe_end(&self, _: &Seat, _: &mut State, _: &GestureSwipeEndEvent) {} + fn gesture_pinch_begin(&self, _: &Seat, _: &mut State, _: &GesturePinchBeginEvent) {} + fn gesture_pinch_update(&self, _: &Seat, _: &mut State, _: &GesturePinchUpdateEvent) {} + fn gesture_pinch_end(&self, _: &Seat, _: &mut State, _: &GesturePinchEndEvent) {} + fn gesture_hold_begin(&self, _: &Seat, _: &mut State, _: &GestureHoldBeginEvent) {} + fn gesture_hold_end(&self, _: &Seat, _: &mut State, _: &GestureHoldEndEvent) {} } pub struct ResizeForkGrab { @@ -223,6 +234,78 @@ impl PointerGrab for ResizeForkGrab { handle.axis(data, details) } + fn gesture_swipe_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeBeginEvent, + ) { + handle.gesture_swipe_begin(data, event) + } + + fn gesture_swipe_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeUpdateEvent, + ) { + handle.gesture_swipe_update(data, event) + } + + fn gesture_swipe_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureSwipeEndEvent, + ) { + handle.gesture_swipe_end(data, event) + } + + fn gesture_pinch_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchBeginEvent, + ) { + handle.gesture_pinch_begin(data, event) + } + + fn gesture_pinch_update( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchUpdateEvent, + ) { + handle.gesture_pinch_update(data, event) + } + + fn gesture_pinch_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GesturePinchEndEvent, + ) { + handle.gesture_pinch_end(data, event) + } + + fn gesture_hold_begin( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldBeginEvent, + ) { + handle.gesture_hold_begin(data, event) + } + + fn gesture_hold_end( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + event: &GestureHoldEndEvent, + ) { + handle.gesture_hold_end(data, event) + } + fn start_data(&self) -> &PointerGrabStartData { &self.start_data } diff --git a/src/utils/iced.rs b/src/utils/iced.rs index 91bdd5f6..9a91b90c 100644 --- a/src/utils/iced.rs +++ b/src/utils/iced.rs @@ -44,7 +44,12 @@ use smithay::{ desktop::space::{RenderZindex, SpaceElement}, input::{ keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, - pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget, RelativeMotionEvent}, + pointer::{ + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerTarget, RelativeMotionEvent, + }, Seat, }, output::Output, @@ -461,6 +466,63 @@ impl PointerTarget for IcedEle .queue_event(Event::Mouse(MouseEvent::CursorLeft)); let _ = internal.update(true); } + + fn gesture_swipe_begin( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GestureSwipeBeginEvent, + ) { + } + fn gesture_swipe_update( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GestureSwipeUpdateEvent, + ) { + } + fn gesture_swipe_end( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GestureSwipeEndEvent, + ) { + } + fn gesture_pinch_begin( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GesturePinchBeginEvent, + ) { + } + fn gesture_pinch_update( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GesturePinchUpdateEvent, + ) { + } + fn gesture_pinch_end( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GesturePinchEndEvent, + ) { + } + fn gesture_hold_begin( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GestureHoldBeginEvent, + ) { + } + fn gesture_hold_end( + &self, + _: &Seat, + _: &mut crate::state::State, + _: &GestureHoldEndEvent, + ) { + } } impl KeyboardTarget for IcedElement

{ From c68625ff78d5f27eadb2bda7aa7889edbc2aa68a Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 5 Sep 2023 13:41:21 -0700 Subject: [PATCH 2/3] Add pointer gestures support --- src/input/mod.rs | 683 +++++++++++++---------- src/state.rs | 12 + src/wayland/handlers/mod.rs | 1 + src/wayland/handlers/pointer_gestures.rs | 6 + 4 files changed, 400 insertions(+), 302 deletions(-) create mode 100644 src/wayland/handlers/pointer_gestures.rs diff --git a/src/input/mod.rs b/src/input/mod.rs index a0b85780..c4fa79cc 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -18,13 +18,19 @@ use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_session_v1::Inp #[allow(deprecated)] use smithay::{ backend::input::{ - Axis, AxisSource, Device, DeviceCapability, InputBackend, InputEvent, KeyState, - PointerAxisEvent, + Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent, + GesturePinchUpdateEvent as _, GestureSwipeUpdateEvent as _, InputBackend, InputEvent, + KeyState, PointerAxisEvent, }, desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType}, input::{ keyboard::{keysyms, FilterResult, KeysymHandle, XkbConfig}, - pointer::{AxisFrame, ButtonEvent, CursorImageStatus, MotionEvent, RelativeMotionEvent}, + pointer::{ + AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + RelativeMotionEvent, + }, Seat, SeatState, }, output::Output, @@ -220,14 +226,15 @@ impl State { use smithay::backend::input::KeyboardKeyEvent; let loop_handle = self.common.event_loop_handle.clone(); - let device = event.device(); - for seat in self.common.seats().cloned().collect::>().iter() { + if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { + let userdata = seat.user_data(); + let current_output = seat.active_output(); let workspace = self.common.shell.active_space_mut(¤t_output); let shortcuts_inhibited = workspace .focus_stack - .get(seat) + .get(&seat) .last() .and_then(|window| { window.wl_surface().and_then(|surface| { @@ -237,16 +244,13 @@ impl State { .map(|inhibitor| inhibitor.is_active()) .unwrap_or(false); - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - if devices.has_device(&device) { - let keycode = event.key_code(); - let state = event.state(); - trace!(?keycode, ?state, "key"); + let keycode = event.key_code(); + let state = event.state(); + trace!(?keycode, ?state, "key"); - let serial = SERIAL_COUNTER.next_serial(); - let time = Event::time_msec(&event); - if let Some((action, pattern)) = seat + let serial = SERIAL_COUNTER.next_serial(); + let time = Event::time_msec(&event); + if let Some((action, pattern)) = seat .get_keyboard() .unwrap() .input( @@ -366,7 +370,7 @@ impl State { // Pass keys to debug interface, if it has focus #[cfg(feature = "debug")] { - if data.common.seats().position(|x| x == seat).unwrap() == 0 + if data.common.seats().position(|x| x == &seat).unwrap() == 0 && data.common.egui.active { if data.common.egui.state.wants_keyboard() { @@ -427,223 +431,224 @@ impl State { ) .flatten() { - self.handle_action(action, seat, serial, time, pattern, None) + self.handle_action(action, &seat, serial, time, pattern, None) } - break; - } } } InputEvent::PointerMotion { event, .. } => { use smithay::backend::input::PointerMotionEvent; - let device = event.device(); - for seat in self.common.seats().cloned().collect::>().iter() { - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - if devices.has_device(&device) { - let current_output = seat.active_output(); - - let mut position = seat.get_pointer().unwrap().current_location(); - position += event.delta(); + if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { + let current_output = seat.active_output(); - let output = self - .common - .shell - .outputs() - .find(|output| output.geometry().to_f64().contains(position)) - .cloned() - .unwrap_or(current_output.clone()); - if output != current_output { - for session in sessions_for_output(&self.common, ¤t_output) { - session.cursor_leave(seat, InputType::Pointer); - } + let mut position = seat.get_pointer().unwrap().current_location(); + position += event.delta(); - for session in sessions_for_output(&self.common, &output) { - session.cursor_enter(seat, InputType::Pointer); - } + let output = self + .common + .shell + .outputs() + .find(|output| output.geometry().to_f64().contains(position)) + .cloned() + .unwrap_or(current_output.clone()); + if output != current_output { + for session in sessions_for_output(&self.common, ¤t_output) { + session.cursor_leave(&seat, InputType::Pointer); + } - seat.set_active_output(&output); + for session in sessions_for_output(&self.common, &output) { + session.cursor_enter(&seat, InputType::Pointer); } - let output_geometry = output.geometry(); - position.x = (output_geometry.loc.x as f64) - .max(position.x) - .min((output_geometry.loc.x + output_geometry.size.w) as f64); - position.y = (output_geometry.loc.y as f64) - .max(position.y) - .min((output_geometry.loc.y + output_geometry.size.h) as f64); + seat.set_active_output(&output); + } + let output_geometry = output.geometry(); - let serial = SERIAL_COUNTER.next_serial(); - let relative_pos = self.common.shell.map_global_to_space(position, &output); - let overview = self.common.shell.overview_mode(); - let workspace = self.common.shell.workspaces.active_mut(&output); - let under = State::surface_under( - position, - relative_pos, - &output, - output_geometry, - &self.common.shell.override_redirect_windows, - overview, - workspace, - ); + position.x = (output_geometry.loc.x as f64) + .max(position.x) + .min((output_geometry.loc.x + output_geometry.size.w) as f64); + position.y = (output_geometry.loc.y as f64) + .max(position.y) + .min((output_geometry.loc.y + output_geometry.size.h) as f64); - for session in sessions_for_output(&self.common, &output) { - if let Some((geometry, offset)) = seat.cursor_geometry( - position.to_buffer( - output.current_scale().fractional_scale(), - output.current_transform(), - &output.geometry().size.to_f64(), - ), - self.common.clock.now(), - ) { - session.cursor_info(seat, InputType::Pointer, geometry, offset); - } - } - let ptr = seat.get_pointer().unwrap(); - ptr.motion( - self, - under.clone(), - &MotionEvent { - location: position, - serial, - time: event.time_msec(), - }, - ); - ptr.relative_motion( - self, - under, - &RelativeMotionEvent { - delta: event.delta(), - delta_unaccel: event.delta_unaccel(), - utime: event.time(), - }, - ); - #[cfg(feature = "debug")] - if self.common.seats().position(|x| x == seat).unwrap() == 0 { - let location = if let Some(output) = self.common.shell.outputs.first() { - self.common - .shell - .map_global_to_space(position, output) - .to_i32_round() - } else { - position.to_i32_round() - }; - self.common.egui.state.handle_pointer_motion(location); + let serial = SERIAL_COUNTER.next_serial(); + let relative_pos = self.common.shell.map_global_to_space(position, &output); + let overview = self.common.shell.overview_mode(); + let workspace = self.common.shell.workspaces.active_mut(&output); + let under = State::surface_under( + position, + relative_pos, + &output, + output_geometry, + &self.common.shell.override_redirect_windows, + overview, + workspace, + ); + + for session in sessions_for_output(&self.common, &output) { + if let Some((geometry, offset)) = seat.cursor_geometry( + position.to_buffer( + output.current_scale().fractional_scale(), + output.current_transform(), + &output.geometry().size.to_f64(), + ), + self.common.clock.now(), + ) { + session.cursor_info(&seat, InputType::Pointer, geometry, offset); } - break; + } + let ptr = seat.get_pointer().unwrap(); + ptr.motion( + self, + under.clone(), + &MotionEvent { + location: position, + serial, + time: event.time_msec(), + }, + ); + ptr.relative_motion( + self, + under, + &RelativeMotionEvent { + delta: event.delta(), + delta_unaccel: event.delta_unaccel(), + utime: event.time(), + }, + ); + #[cfg(feature = "debug")] + if self.common.seats().position(|x| x == &seat).unwrap() == 0 { + let location = if let Some(output) = self.common.shell.outputs.first() { + self.common + .shell + .map_global_to_space(position, output) + .to_i32_round() + } else { + position.to_i32_round() + }; + self.common.egui.state.handle_pointer_motion(location); } } } InputEvent::PointerMotionAbsolute { event, .. } => { - let device = event.device(); - for seat in self.common.seats().cloned().collect::>().iter() { - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - if devices.has_device(&device) { - let output = seat.active_output(); - let geometry = output.geometry(); - let position = geometry.loc.to_f64() - + smithay::backend::input::AbsolutePositionEvent::position_transformed( - &event, - geometry.size, - ); - let relative_pos = self.common.shell.map_global_to_space(position, &output); - let overview = self.common.shell.overview_mode(); - let workspace = self.common.shell.workspaces.active_mut(&output); - let serial = SERIAL_COUNTER.next_serial(); - let under = State::surface_under( - position, - relative_pos, - &output, - geometry, - &self.common.shell.override_redirect_windows, - overview, - workspace, + if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { + let output = seat.active_output(); + let geometry = output.geometry(); + let position = geometry.loc.to_f64() + + smithay::backend::input::AbsolutePositionEvent::position_transformed( + &event, + geometry.size, ); + let relative_pos = self.common.shell.map_global_to_space(position, &output); + let overview = self.common.shell.overview_mode(); + let workspace = self.common.shell.workspaces.active_mut(&output); + let serial = SERIAL_COUNTER.next_serial(); + let under = State::surface_under( + position, + relative_pos, + &output, + geometry, + &self.common.shell.override_redirect_windows, + overview, + workspace, + ); - for session in sessions_for_output(&self.common, &output) { - if let Some((geometry, offset)) = seat.cursor_geometry( - position.to_buffer( - output.current_scale().fractional_scale(), - output.current_transform(), - &output.geometry().size.to_f64(), - ), - self.common.clock.now(), - ) { - session.cursor_info(seat, InputType::Pointer, geometry, offset); - } - } - seat.get_pointer().unwrap().motion( - self, - under, - &MotionEvent { - location: position, - serial, - time: event.time_msec(), - }, - ); - #[cfg(feature = "debug")] - if self.common.seats().position(|x| x == seat).unwrap() == 0 { - let location = if let Some(output) = self.common.shell.outputs.first() { - self.common - .shell - .map_global_to_space(position, output) - .to_i32_round() - } else { - position.to_i32_round() - }; - self.common.egui.state.handle_pointer_motion(location); + for session in sessions_for_output(&self.common, &output) { + if let Some((geometry, offset)) = seat.cursor_geometry( + position.to_buffer( + output.current_scale().fractional_scale(), + output.current_transform(), + &output.geometry().size.to_f64(), + ), + self.common.clock.now(), + ) { + session.cursor_info(&seat, InputType::Pointer, geometry, offset); } - - break; + } + seat.get_pointer().unwrap().motion( + self, + under, + &MotionEvent { + location: position, + serial, + time: event.time_msec(), + }, + ); + #[cfg(feature = "debug")] + if self.common.seats().position(|x| x == &seat).unwrap() == 0 { + let location = if let Some(output) = self.common.shell.outputs.first() { + self.common + .shell + .map_global_to_space(position, output) + .to_i32_round() + } else { + position.to_i32_round() + }; + self.common.egui.state.handle_pointer_motion(location); } } } InputEvent::PointerButton { event, .. } => { use smithay::backend::input::{ButtonState, PointerButtonEvent}; - let device = event.device(); - for seat in self.common.seats().cloned().collect::>().iter() { - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - if devices.has_device(&device) { - #[cfg(feature = "debug")] - if self.common.seats().position(|x| x == seat).unwrap() == 0 - && self.common.egui.active - { - if self.common.egui.state.wants_pointer() { - if let Some(button) = event.button() { - self.common.egui.state.handle_pointer_button( - button, - event.state() == ButtonState::Pressed, - ); - } - break; + if let Some(seat) = self.common.seat_with_device(&event.device()).cloned() { + #[cfg(feature = "debug")] + if self.common.seats().position(|x| x == &seat).unwrap() == 0 + && self.common.egui.active + { + if self.common.egui.state.wants_pointer() { + if let Some(button) = event.button() { + self.common.egui.state.handle_pointer_button( + button, + event.state() == ButtonState::Pressed, + ); } + return; } + } - let serial = SERIAL_COUNTER.next_serial(); - let button = event.button_code(); - if event.state() == ButtonState::Pressed { - // change the keyboard focus unless the pointer or keyboard is grabbed - // We test for any matching surface type here but always use the root - // (in case of a window the toplevel) surface for the focus. - // see: https://gitlab.freedesktop.org/wayland/wayland/-/issues/294 - if !seat.get_pointer().unwrap().is_grabbed() - && !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false) - { - let output = seat.active_output(); - let pos = seat.get_pointer().unwrap().current_location(); - let relative_pos = - self.common.shell.map_global_to_space(pos, &output); - let overview = self.common.shell.overview_mode(); - let workspace = self.common.shell.active_space_mut(&output); - let mut under = None; + let serial = SERIAL_COUNTER.next_serial(); + let button = event.button_code(); + if event.state() == ButtonState::Pressed { + // change the keyboard focus unless the pointer or keyboard is grabbed + // We test for any matching surface type here but always use the root + // (in case of a window the toplevel) surface for the focus. + // see: https://gitlab.freedesktop.org/wayland/wayland/-/issues/294 + if !seat.get_pointer().unwrap().is_grabbed() + && !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false) + { + let output = seat.active_output(); + let pos = seat.get_pointer().unwrap().current_location(); + let relative_pos = self.common.shell.map_global_to_space(pos, &output); + let overview = self.common.shell.overview_mode(); + let workspace = self.common.shell.active_space_mut(&output); + let mut under = None; - if let Some(window) = workspace.get_fullscreen(&output) { + if let Some(window) = workspace.get_fullscreen(&output) { + let layers = layer_map_for_output(&output); + if let Some(layer) = + layers.layer_under(WlrLayer::Overlay, relative_pos) + { + let layer_loc = layers.layer_geometry(layer).unwrap().loc; + if layer.can_receive_keyboard_focus() + && layer + .surface_under( + relative_pos - layer_loc.to_f64(), + WindowSurfaceType::ALL, + ) + .is_some() + { + under = Some(layer.clone().into()); + } + } else { + under = Some(window.clone().into()); + } + } else { + let done = { let layers = layer_map_for_output(&output); - if let Some(layer) = - layers.layer_under(WlrLayer::Overlay, relative_pos) + if let Some(layer) = layers + .layer_under(WlrLayer::Overlay, relative_pos) + .or_else(|| layers.layer_under(WlrLayer::Top, relative_pos)) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; if layer.can_receive_keyboard_focus() @@ -656,17 +661,22 @@ impl State { { under = Some(layer.clone().into()); } + true } else { - under = Some(window.clone().into()); + false } - } else { - let done = { + }; + if !done { + if let Some((target, _)) = + workspace.element_under(relative_pos, overview) + { + under = Some(target); + } else { let layers = layer_map_for_output(&output); - if let Some(layer) = layers - .layer_under(WlrLayer::Overlay, relative_pos) - .or_else(|| { - layers.layer_under(WlrLayer::Top, relative_pos) - }) + if let Some(layer) = + layers.layer_under(WlrLayer::Bottom, pos).or_else( + || layers.layer_under(WlrLayer::Background, pos), + ) { let layer_loc = layers.layer_geometry(layer).unwrap().loc; @@ -680,67 +690,35 @@ impl State { { under = Some(layer.clone().into()); } - true - } else { - false - } - }; - if !done { - if let Some((target, _)) = - workspace.element_under(relative_pos, overview) - { - under = Some(target); - } else { - let layers = layer_map_for_output(&output); - if let Some(layer) = layers - .layer_under(WlrLayer::Bottom, pos) - .or_else(|| { - layers.layer_under(WlrLayer::Background, pos) - }) - { - let layer_loc = - layers.layer_geometry(layer).unwrap().loc; - if layer.can_receive_keyboard_focus() - && layer - .surface_under( - relative_pos - layer_loc.to_f64(), - WindowSurfaceType::ALL, - ) - .is_some() - { - under = Some(layer.clone().into()); - } - }; - } + }; } } - Common::set_focus( - self, - under.and_then(|target| target.try_into().ok()).as_ref(), - seat, - Some(serial), - ); } - } else { - if let OverviewMode::Started(Trigger::Pointer(action_button), _) = - self.common.shell.overview_mode() - { - if action_button == button { - self.common.shell.set_overview_mode(None); - } + Common::set_focus( + self, + under.and_then(|target| target.try_into().ok()).as_ref(), + &seat, + Some(serial), + ); + } + } else { + if let OverviewMode::Started(Trigger::Pointer(action_button), _) = + self.common.shell.overview_mode() + { + if action_button == button { + self.common.shell.set_overview_mode(None); } - }; - seat.get_pointer().unwrap().button( - self, - &ButtonEvent { - button, - state: event.state(), - serial, - time: event.time_msec(), - }, - ); - break; - } + } + }; + seat.get_pointer().unwrap().button( + self, + &ButtonEvent { + button, + state: event.state(), + serial, + time: event.time_msec(), + }, + ); } } InputEvent::PointerAxis { event, .. } => { @@ -753,8 +731,7 @@ impl State { 1.0 }; - let device = event.device(); - for seat in self.common.seats().cloned().collect::>().iter() { + if let Some(seat) = self.common.seat_with_device(&event.device()) { #[cfg(feature = "debug")] if self.common.seats().position(|x| x == seat).unwrap() == 0 && self.common.egui.active @@ -770,50 +747,152 @@ impl State { .or_else(|| event.amount(Axis::Vertical).map(|x| x * 3.0)) .unwrap_or(0.0), ); - break; + return; } } - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - if devices.has_device(&device) { - let horizontal_amount = - event.amount(Axis::Horizontal).unwrap_or_else(|| { - event.amount_discrete(Axis::Horizontal).unwrap_or(0.0) * 3.0 - }); - let vertical_amount = event.amount(Axis::Vertical).unwrap_or_else(|| { - event.amount_discrete(Axis::Vertical).unwrap_or(0.0) * 3.0 - }); - let horizontal_amount_discrete = event.amount_discrete(Axis::Horizontal); - let vertical_amount_discrete = event.amount_discrete(Axis::Vertical); + let horizontal_amount = event.amount(Axis::Horizontal).unwrap_or_else(|| { + event.amount_discrete(Axis::Horizontal).unwrap_or(0.0) * 3.0 + }); + let vertical_amount = event.amount(Axis::Vertical).unwrap_or_else(|| { + event.amount_discrete(Axis::Vertical).unwrap_or(0.0) * 3.0 + }); + let horizontal_amount_discrete = event.amount_discrete(Axis::Horizontal); + let vertical_amount_discrete = event.amount_discrete(Axis::Vertical); - { - let mut frame = - AxisFrame::new(event.time_msec()).source(event.source()); - if horizontal_amount != 0.0 { - frame = frame - .value(Axis::Horizontal, scroll_factor * horizontal_amount); - if let Some(discrete) = horizontal_amount_discrete { - frame = frame.discrete(Axis::Horizontal, discrete as i32); - } - } else if event.source() == AxisSource::Finger { - frame = frame.stop(Axis::Horizontal); + { + let mut frame = AxisFrame::new(event.time_msec()).source(event.source()); + if horizontal_amount != 0.0 { + frame = + frame.value(Axis::Horizontal, scroll_factor * horizontal_amount); + if let Some(discrete) = horizontal_amount_discrete { + frame = frame.discrete(Axis::Horizontal, discrete as i32); } - if vertical_amount != 0.0 { - frame = - frame.value(Axis::Vertical, scroll_factor * vertical_amount); - if let Some(discrete) = vertical_amount_discrete { - frame = frame.discrete(Axis::Vertical, discrete as i32); - } - } else if event.source() == AxisSource::Finger { - frame = frame.stop(Axis::Vertical); + } else if event.source() == AxisSource::Finger { + frame = frame.stop(Axis::Horizontal); + } + if vertical_amount != 0.0 { + frame = frame.value(Axis::Vertical, scroll_factor * vertical_amount); + if let Some(discrete) = vertical_amount_discrete { + frame = frame.discrete(Axis::Vertical, discrete as i32); } - seat.get_pointer().unwrap().axis(self, frame); + } else if event.source() == AxisSource::Finger { + frame = frame.stop(Axis::Vertical); } - break; + seat.get_pointer().unwrap().axis(self, frame); } } } + InputEvent::GestureSwipeBegin { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_swipe_begin( + self, + &GestureSwipeBeginEvent { + serial, + time: event.time_msec(), + fingers: event.fingers(), + }, + ); + } + } + InputEvent::GestureSwipeUpdate { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_swipe_update( + self, + &GestureSwipeUpdateEvent { + time: event.time_msec(), + delta: event.delta(), + }, + ); + } + } + InputEvent::GestureSwipeEnd { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_swipe_end( + self, + &GestureSwipeEndEvent { + serial, + time: event.time_msec(), + cancelled: event.cancelled(), + }, + ); + } + } + InputEvent::GesturePinchBegin { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_pinch_begin( + self, + &GesturePinchBeginEvent { + serial, + time: event.time_msec(), + fingers: event.fingers(), + }, + ); + } + } + InputEvent::GesturePinchUpdate { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_pinch_update( + self, + &GesturePinchUpdateEvent { + time: event.time_msec(), + delta: event.delta(), + scale: event.scale(), + rotation: event.rotation(), + }, + ); + } + } + InputEvent::GesturePinchEnd { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_pinch_end( + self, + &GesturePinchEndEvent { + serial, + time: event.time_msec(), + cancelled: event.cancelled(), + }, + ); + } + } + InputEvent::GestureHoldBegin { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_hold_begin( + self, + &GestureHoldBeginEvent { + serial, + time: event.time_msec(), + fingers: event.fingers(), + }, + ); + } + } + InputEvent::GestureHoldEnd { event, .. } => { + if let Some(seat) = self.common.seat_with_device(&event.device()) { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = seat.get_pointer().unwrap(); + pointer.gesture_hold_end( + self, + &GestureHoldEndEvent { + serial, + time: event.time_msec(), + cancelled: event.cancelled(), + }, + ); + } + } _ => { /* TODO e.g. tablet or touch events */ } } } diff --git a/src/state.rs b/src/state.rs index f1d1740e..cd8de043 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,6 +7,7 @@ use crate::{ x11::X11State, }, config::{Config, OutputConfig}, + input::Devices, shell::{grabs::SeatMoveGrabState, Shell}, utils::prelude::*, wayland::protocols::{ @@ -30,6 +31,7 @@ use smithay::utils::Rectangle; use smithay::{ backend::{ drm::DrmNode, + input::Device, renderer::{ element::{ default_primary_scanout_output_compare, utils::select_dmabuf_feedback, @@ -63,6 +65,7 @@ use smithay::{ fractional_scale::{with_fractional_scale, FractionalScaleManagerState}, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitState, output::OutputManagerState, + pointer_gestures::PointerGesturesState, presentation::PresentationState, primary_selection::PrimarySelectionState, seat::WaylandFocus, @@ -301,6 +304,7 @@ impl State { let kde_decoration_state = KdeDecorationState::new::(&dh, Mode::Client); let xdg_decoration_state = XdgDecorationState::new::(&dh); XWaylandKeyboardGrabState::new::(&dh); + PointerGesturesState::new::(&dh); let shell = Shell::new(&config, dh); @@ -421,6 +425,14 @@ impl Common { self.seats.iter() } + pub fn seat_with_device(&self, device: &D) -> Option<&Seat> { + self.seats().find(|seat| { + let userdata = seat.user_data(); + let devices = userdata.get::().unwrap(); + devices.has_device(device) + }) + } + pub fn last_active_seat(&self) -> &Seat { self.last_active_seat.as_ref().expect("No seat?") } diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index a7bfff90..f9243fb6 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -10,6 +10,7 @@ pub mod keyboard_shortcuts_inhibit; pub mod layer_shell; pub mod output; pub mod output_configuration; +pub mod pointer_gestures; pub mod presentation; pub mod primary_selection; pub mod relative_pointer; diff --git a/src/wayland/handlers/pointer_gestures.rs b/src/wayland/handlers/pointer_gestures.rs new file mode 100644 index 00000000..dc950d80 --- /dev/null +++ b/src/wayland/handlers/pointer_gestures.rs @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only + +use crate::state::State; +use smithay::delegate_pointer_gestures; + +delegate_pointer_gestures!(State); From 8dce518ba69762b776141a47c6ef98dd88a9d8cc Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 29 Aug 2023 17:00:11 -0700 Subject: [PATCH 3/3] Add security context protocol Currently, excludes some protocols if they have any security context associated. --- src/shell/mod.rs | 7 ++--- src/state.rs | 19 +++++++++++--- src/wayland/handlers/mod.rs | 1 + src/wayland/handlers/security_context.rs | 33 ++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/wayland/handlers/security_context.rs diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 84a3a477..d07046c1 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -37,6 +37,7 @@ use smithay::{ use crate::{ config::{Config, KeyModifiers, KeyPattern, OutputConfig, WorkspaceMode as ConfigMode}, + state::client_has_security_context, utils::prelude::*, wayland::protocols::{ toplevel_info::ToplevelInfoState, @@ -583,7 +584,7 @@ impl Shell { let toplevel_info_state = ToplevelInfoState::new( dh, //|client| client.get_data::().map_or(false, |s| s.privileged), - |_| true, + client_has_security_context, ); let toplevel_management_state = ToplevelManagementState::new::( dh, @@ -592,12 +593,12 @@ impl Shell { ManagementCapabilities::Activate, ], //|client| client.get_data::().map_or(false, |s| s.privileged), - |_| true, + client_has_security_context, ); let mut workspace_state = WorkspaceState::new( dh, //|client| client.get_data::().map_or(false, |s| s.privileged), - |_| true, + client_has_security_context, ); let tiling_enabled = config.static_conf.tiling_enabled; diff --git a/src/state.rs b/src/state.rs index cd8de043..02a3c714 100644 --- a/src/state.rs +++ b/src/state.rs @@ -54,7 +54,7 @@ use smithay::{ wayland_server::{ backend::{ClientData, ClientId, DisconnectReason}, protocol::wl_shm, - Display, DisplayHandle, + Client, Display, DisplayHandle, }, }, utils::{Clock, IsAlive, Monotonic}, @@ -69,6 +69,7 @@ use smithay::{ presentation::PresentationState, primary_selection::PrimarySelectionState, seat::WaylandFocus, + security_context::{SecurityContext, SecurityContextState}, shell::{kde::decoration::KdeDecorationState, xdg::decoration::XdgDecorationState}, shm::ShmState, viewporter::ViewporterState, @@ -103,6 +104,7 @@ pub struct ClientState { pub drm_node: Option, pub privileged: bool, pub evls: LoopSignal, + pub security_context: Option, } impl ClientData for ClientState { fn initialized(&self, _client_id: ClientId) {} @@ -268,6 +270,12 @@ impl BackendData { } } +pub fn client_has_security_context(client: &Client) -> bool { + client + .get_data::() + .map_or(true, |client_state| client_state.security_context.is_none()) +} + impl State { pub fn new( dh: &DisplayHandle, @@ -288,13 +296,14 @@ impl State { let fractional_scale_state = FractionalScaleManagerState::new::(dh); let keyboard_shortcuts_inhibit_state = KeyboardShortcutsInhibitState::new::(dh); let output_state = OutputManagerState::new_with_xdg_output::(dh); - let output_configuration_state = OutputConfigurationState::new(dh, |_| true); + let output_configuration_state = + OutputConfigurationState::new(dh, client_has_security_context); let presentation_state = PresentationState::new::(dh, clock.id() as u32); let primary_selection_state = PrimarySelectionState::new::(dh); let screencopy_state = ScreencopyState::new::( dh, vec![CursorMode::Embedded, CursorMode::Hidden], - |_| true, + client_has_security_context, ); // TODO: privileged let shm_state = ShmState::new::(dh, vec![wl_shm::Format::Xbgr8888, wl_shm::Format::Abgr8888]); @@ -305,6 +314,7 @@ impl State { let xdg_decoration_state = XdgDecorationState::new::(&dh); XWaylandKeyboardGrabState::new::(&dh); PointerGesturesState::new::(&dh); + SecurityContextState::new::(&dh, client_has_security_context); let shell = Shell::new(&config, dh); @@ -377,6 +387,7 @@ impl State { }, privileged: false, evls: self.common.event_loop_signal.clone(), + security_context: None, } } @@ -387,6 +398,7 @@ impl State { drm_node: Some(drm_node), privileged: false, evls: self.common.event_loop_signal.clone(), + security_context: None, } } @@ -400,6 +412,7 @@ impl State { }, privileged: true, evls: self.common.event_loop_signal.clone(), + security_context: None, } } } diff --git a/src/wayland/handlers/mod.rs b/src/wayland/handlers/mod.rs index f9243fb6..d8eac626 100644 --- a/src/wayland/handlers/mod.rs +++ b/src/wayland/handlers/mod.rs @@ -16,6 +16,7 @@ pub mod primary_selection; pub mod relative_pointer; pub mod screencopy; pub mod seat; +pub mod security_context; pub mod shm; pub mod toplevel_info; pub mod toplevel_management; diff --git a/src/wayland/handlers/security_context.rs b/src/wayland/handlers/security_context.rs new file mode 100644 index 00000000..0695f70e --- /dev/null +++ b/src/wayland/handlers/security_context.rs @@ -0,0 +1,33 @@ +use crate::state::{ClientState, State}; +use smithay::{ + delegate_security_context, + wayland::security_context::{ + SecurityContext, SecurityContextHandler, SecurityContextListenerSource, + }, +}; +use std::sync::Arc; +use tracing::warn; + +impl SecurityContextHandler for State { + fn context_created( + &mut self, + source: SecurityContextListenerSource, + security_context: SecurityContext, + ) { + self.common + .event_loop_handle + .insert_source(source, move |client_stream, _, data| { + if let Err(err) = data.display.handle().insert_client( + client_stream, + Arc::new(ClientState { + security_context: Some(security_context.clone()), + ..data.state.new_client_state() + }), + ) { + warn!(?err, "Error adding wayland client"); + }; + }) + .expect("Failed to init the wayland socket source."); + } +} +delegate_security_context!(State);