use smithay::{ input::{ Seat, SeatHandler, pointer::{ AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, touch::{ DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, }, }, utils::{Logical, Point, SERIAL_COUNTER, Serial}, }; use crate::state::State; use super::GrabStartData; pub struct DelayGrab { grab_factory: Option Option<(G, Focus)>>>, seat: Seat, serial: Option, start_data: GrabStartData, } unsafe impl Send for DelayGrab {} impl DelayGrab { pub fn new( factory: impl FnOnce(&mut State) -> Option<(G, Focus)> + 'static, seat: Seat, serial: Option, start_data: GrabStartData, ) -> Self { DelayGrab { grab_factory: Some(Box::new(factory)), seat, serial, start_data, } } pub fn is_touch_grab(&self) -> bool { match self.start_data { GrabStartData::Touch(_) => true, GrabStartData::Pointer(_) => false, } } } impl> PointerGrab for DelayGrab { fn motion( &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, focus: Option<(::PointerFocus, Point)>, event: &PointerMotionEvent, ) { handle.motion(data, focus, event); let distance = self.start_data.distance(event.location); if distance >= 1. && let Some(factory) = self.grab_factory.take() { let serial = self.serial.unwrap_or(event.serial); let seat = self.seat.clone(); data.common.event_loop_handle.insert_idle(move |data| { if let Some((grab, focus)) = factory(data) { seat.get_pointer() .unwrap() .set_grab(data, grab, serial, focus); } }); } } fn relative_motion( &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, focus: Option<(::PointerFocus, Point)>, event: &RelativeMotionEvent, ) { handle.relative_motion(data, focus, event); } fn button( &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, event: &ButtonEvent, ) { handle.button(data, event); if handle.current_pressed().is_empty() { handle.unset_grab(self, data, event.serial, event.time, true); } } fn axis( &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, details: AxisFrame, ) { handle.axis(data, details); } fn frame(&mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>) { handle.frame(data); } 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 { match &self.start_data { GrabStartData::Pointer(start_data) => start_data, _ => unreachable!(), } } fn unset(&mut self, _data: &mut State) {} } impl> TouchGrab for DelayGrab { fn down( &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(::TouchFocus, Point)>, event: &DownEvent, seq: Serial, ) { handle.down(data, focus, event, seq); } fn up( &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent, seq: Serial, ) { handle.up(data, event, seq); if event.slot == TouchGrab::start_data(self).slot { handle.unset_grab(self, data); } } fn motion( &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(::TouchFocus, Point)>, event: &TouchMotionEvent, seq: Serial, ) { handle.motion(data, focus, event, seq); let distance = self.start_data.distance(event.location); if distance >= 1. && let Some(factory) = self.grab_factory.take() { let seat = self.seat.clone(); let serial = self.serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()); data.common.event_loop_handle.insert_idle(move |data| { if let Some((grab, _)) = factory(data) { seat.get_touch().unwrap().set_grab(data, grab, serial); } }); } } 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.cancel(data, seq); handle.unset_grab(self, data); } fn shape( &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &ShapeEvent, seq: Serial, ) { handle.shape(data, event, seq) } fn orientation( &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &OrientationEvent, seq: Serial, ) { handle.orientation(data, event, seq); } fn start_data(&self) -> &TouchGrabStartData { match &self.start_data { GrabStartData::Touch(start_data) => start_data, _ => unreachable!(), } } fn unset(&mut self, _data: &mut State) {} }