From bddfba464c4ab7d8f7f6f3c3bfe8a2a003ee677c Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 5 Apr 2024 16:15:47 -0700 Subject: [PATCH] shell: Add touch support to `ResizeSurfaceGrab` Seems to work well with GTK. --- src/shell/grabs/mod.rs | 90 +++++++++++++++-- src/shell/layout/floating/grabs/resize.rs | 112 ++++++++++++++++++---- src/shell/layout/floating/mod.rs | 6 +- src/shell/mod.rs | 64 ++++++++----- 4 files changed, 219 insertions(+), 53 deletions(-) diff --git a/src/shell/grabs/mod.rs b/src/shell/grabs/mod.rs index 1535e8b8..8306ef54 100644 --- a/src/shell/grabs/mod.rs +++ b/src/shell/grabs/mod.rs @@ -7,10 +7,13 @@ use smithay::{ GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, - touch::GrabStartData as TouchGrabStartData, + touch::{ + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + TouchGrab, TouchInnerHandle, UpEvent, + }, }, reexports::wayland_protocols::xdg::shell::server::xdg_toplevel, - utils::{Logical, Point}, + utils::{Logical, Point, Serial}, xwayland::xwm, }; @@ -48,6 +51,13 @@ impl GrabStartData { Self::Pointer(pointer) => pointer.location, } } + + pub fn set_location(&mut self, location: Point) { + match self { + Self::Touch(touch) => touch.location = location, + Self::Pointer(pointer) => pointer.location = location, + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -152,8 +162,8 @@ impl PointerGrab for ResizeGrab { event: &MotionEvent, ) { match self { - ResizeGrab::Floating(grab) => grab.motion(data, handle, focus, event), - ResizeGrab::Tiling(grab) => grab.motion(data, handle, focus, event), + ResizeGrab::Floating(grab) => PointerGrab::motion(grab, data, handle, focus, event), + ResizeGrab::Tiling(grab) => PointerGrab::motion(grab, data, handle, focus, event), } } @@ -196,8 +206,8 @@ impl PointerGrab for ResizeGrab { fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) { match self { - ResizeGrab::Floating(grab) => grab.frame(data, handle), - ResizeGrab::Tiling(grab) => grab.frame(data, handle), + ResizeGrab::Floating(grab) => PointerGrab::frame(grab, data, handle), + ResizeGrab::Tiling(grab) => PointerGrab::frame(grab, data, handle), } } @@ -299,8 +309,72 @@ impl PointerGrab for ResizeGrab { fn start_data(&self) -> &PointerGrabStartData { match self { - ResizeGrab::Floating(grab) => grab.start_data(), - ResizeGrab::Tiling(grab) => grab.start_data(), + ResizeGrab::Floating(grab) => PointerGrab::start_data(grab), + ResizeGrab::Tiling(grab) => PointerGrab::start_data(grab), + } + } +} + +impl TouchGrab for ResizeGrab { + fn down( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &DownEvent, + seq: Serial, + ) { + match self { + ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event, seq), + ResizeGrab::Tiling(grab) => TouchGrab::down(grab, data, handle, focus, event, seq), + } + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &UpEvent, + seq: Serial, + ) { + match self { + ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event, seq), + ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event, seq), + } + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &TouchMotionEvent, + seq: Serial, + ) { + match self { + ResizeGrab::Floating(grab) => TouchGrab::motion(grab, data, handle, focus, event, seq), + ResizeGrab::Tiling(grab) => TouchGrab::motion(grab, data, handle, focus, event, seq), + } + } + + fn frame(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) { + match self { + ResizeGrab::Floating(grab) => TouchGrab::frame(grab, data, handle, seq), + ResizeGrab::Tiling(grab) => TouchGrab::frame(grab, data, handle, seq), + } + } + + fn cancel(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) { + match self { + ResizeGrab::Floating(grab) => TouchGrab::cancel(grab, data, handle, seq), + ResizeGrab::Tiling(grab) => TouchGrab::cancel(grab, data, handle, seq), + } + } + + fn start_data(&self) -> &TouchGrabStartData { + match self { + ResizeGrab::Floating(grab) => TouchGrab::start_data(grab), + ResizeGrab::Tiling(grab) => TouchGrab::start_data(grab), } } } diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index 0c453e62..0c2d23ac 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -6,7 +6,7 @@ use crate::{ shell::{ element::CosmicMapped, focus::target::PointerFocusTarget, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabStartData, ReleaseMode, ResizeEdge}, }, utils::prelude::*, }; @@ -21,6 +21,10 @@ use smithay::{ GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, + touch::{ + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + TouchGrab, TouchInnerHandle, UpEvent, + }, Seat, }, utils::{IsAlive, Logical, Point, Rectangle, Serial, Size}, @@ -47,7 +51,7 @@ pub enum ResizeState { } pub struct ResizeSurfaceGrab { - start_data: PointerGrabStartData, + start_data: GrabStartData, seat: Seat, window: CosmicMapped, edges: ResizeEdge, @@ -56,17 +60,9 @@ pub struct ResizeSurfaceGrab { release: ReleaseMode, } -impl PointerGrab for ResizeSurfaceGrab { - fn motion( - &mut self, - data: &mut State, - handle: &mut PointerInnerHandle<'_, State>, - _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, - ) { - // While the grab is active, no client has pointer focus - handle.motion(data, None, event); - +impl ResizeSurfaceGrab { + // Returns `true` if grab should be unset + fn update_location(&mut self, location: Point) -> bool { // It is impossible to get `min_size` and `max_size` of dead toplevel, so we return early. if !self.window.alive() { self.seat @@ -75,11 +71,10 @@ impl PointerGrab for ResizeSurfaceGrab { .unwrap() .0 .store(false, Ordering::SeqCst); - handle.unset_grab(data, event.serial, event.time, true); - return; + return true; } - let (mut dx, mut dy) = (event.location - self.start_data.location).into(); + let (mut dx, mut dy) = (location - self.start_data.location()).into(); let mut new_window_width = self.initial_window_size.w; let mut new_window_height = self.initial_window_size.h; @@ -125,6 +120,25 @@ impl PointerGrab for ResizeSurfaceGrab { self.last_window_size.as_global(), )); self.window.configure(); + + false + } +} + +impl PointerGrab for ResizeSurfaceGrab { + fn motion( + &mut self, + data: &mut State, + handle: &mut PointerInnerHandle<'_, State>, + _focus: Option<(PointerFocusTarget, Point)>, + event: &MotionEvent, + ) { + // While the grab is active, no client has pointer focus + handle.motion(data, None, event); + + if self.update_location(event.location) { + handle.unset_grab(data, event.serial, event.time, true); + } } fn relative_motion( @@ -245,7 +259,69 @@ impl PointerGrab for ResizeSurfaceGrab { } fn start_data(&self) -> &PointerGrabStartData { - &self.start_data + match &self.start_data { + GrabStartData::Pointer(start_data) => start_data, + _ => unreachable!(), + } + } +} + +impl TouchGrab for ResizeSurfaceGrab { + fn down( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + _focus: Option<(PointerFocusTarget, Point)>, + event: &DownEvent, + seq: Serial, + ) { + handle.down(data, None, event, seq) + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &UpEvent, + seq: Serial, + ) { + if event.slot == >::start_data(self).slot { + handle.unset_grab(data); + } + + handle.up(data, event, seq); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + _focus: Option<(PointerFocusTarget, Point)>, + event: &TouchMotionEvent, + seq: Serial, + ) { + if event.slot == >::start_data(self).slot { + if self.update_location(event.location) { + handle.unset_grab(data); + } + } + + handle.motion(data, None, event, seq); + } + + fn frame(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, seq: Serial) { + handle.frame(data, seq) + } + + fn cancel(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _seq: Serial) { + handle.unset_grab(data); + } + + fn start_data(&self) -> &TouchGrabStartData { + match &self.start_data { + GrabStartData::Touch(start_data) => start_data, + _ => unreachable!(), + } } } @@ -259,7 +335,7 @@ impl ResizeGrabMarker { impl ResizeSurfaceGrab { pub fn new( - start_data: PointerGrabStartData, + start_data: GrabStartData, mapped: CosmicMapped, edges: ResizeEdge, initial_window_location: Point, diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index e3921999..b8bbd5b8 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -16,7 +16,7 @@ use smithay::{ ImportAll, ImportMem, Renderer, }, desktop::{layer_map_for_output, space::SpaceElement, PopupKind, Space, WindowSurfaceType}, - input::{pointer::GrabStartData as PointerGrabStartData, Seat}, + input::Seat, output::Output, utils::{IsAlive, Logical, Point, Rectangle, Scale, Size}, wayland::seat::WaylandFocus, @@ -35,7 +35,7 @@ use crate::{ target::{KeyboardFocusTarget, PointerFocusTarget}, FocusStackMut, }, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabStartData, ReleaseMode, ResizeEdge}, CosmicSurface, Direction, ManagedLayer, MoveResult, ResizeDirection, ResizeMode, }, state::State, @@ -739,7 +739,7 @@ impl FloatingLayout { &mut self, mapped: &CosmicMapped, seat: &Seat, - start_data: PointerGrabStartData, + start_data: GrabStartData, edges: ResizeEdge, release: ReleaseMode, ) -> Option { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 9a4f74bd..d61f3bb0 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -2842,7 +2842,7 @@ impl Shell { return; } - if let Some(GrabStartData::Pointer(mut start_data)) = + if let Some(mut start_data) = check_grab_preconditions(&seat, &surface, None, ReleaseMode::Click) { let (floating_layer, geometry) = if let Some(set) = state @@ -2891,8 +2891,10 @@ impl Shell { let focus = mapped .focus_under(element_offset.to_f64()) .map(|(target, surface_offset)| (target, (surface_offset + element_offset))); - start_data.location = new_loc.as_logical().to_f64(); - start_data.focus = focus.clone(); + start_data.set_location(new_loc.as_logical().to_f64()); + start_data.set_focus(focus.clone()); + + let is_touch_grab = matches!(start_data, GrabStartData::Touch(_)); let grab: ResizeGrab = if let Some(grab) = floating_layer.resize_request( mapped, @@ -2912,7 +2914,7 @@ impl Shell { return; }; ResizeForkGrab::new( - GrabStartData::Pointer(start_data), + start_data, new_loc.to_f64(), node, left_up_idx, @@ -2925,19 +2927,23 @@ impl Shell { return; }; - let ptr = seat.get_pointer().unwrap(); let serial = SERIAL_COUNTER.next_serial(); - ptr.motion( - state, - focus, - &MotionEvent { - location: new_loc.as_logical().to_f64(), - serial, - time: 0, - }, - ); - ptr.frame(state); - ptr.set_grab(state, grab, serial, Focus::Keep); + if is_touch_grab { + seat.get_touch().unwrap().set_grab(state, grab, serial); + } else { + let ptr = seat.get_pointer().unwrap(); + ptr.motion( + state, + focus, + &MotionEvent { + location: new_loc.as_logical().to_f64(), + serial, + time: 0, + }, + ); + ptr.frame(state); + ptr.set_grab(state, grab, serial, Focus::Keep); + } } } @@ -3100,7 +3106,7 @@ impl Shell { edges: ResizeEdge, ) { let serial = serial.into(); - if let Some(GrabStartData::Pointer(start_data)) = + if let Some(start_data) = check_grab_preconditions(&seat, surface, serial, ReleaseMode::NoMouseButtons) { if let Some(mapped) = state.common.shell.element_for_surface(surface).cloned() { @@ -3123,6 +3129,8 @@ impl Shell { return; }; + let is_touch_grab = matches!(start_data, GrabStartData::Touch(_)); + let grab: ResizeGrab = if let Some(grab) = floating_layer.resize_request( &mapped, seat, @@ -3141,7 +3149,7 @@ impl Shell { return; }; ResizeForkGrab::new( - GrabStartData::Pointer(start_data), + start_data, seat.get_pointer().unwrap().current_location().as_global(), node, left_up_idx, @@ -3154,12 +3162,20 @@ impl Shell { return; }; - seat.get_pointer().unwrap().set_grab( - state, - grab, - serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()), - Focus::Clear, - ); + if is_touch_grab { + seat.get_touch().unwrap().set_grab( + state, + grab, + serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()), + ); + } else { + seat.get_pointer().unwrap().set_grab( + state, + grab, + serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()), + Focus::Clear, + ); + } } } }