smithay/input/pointer/
grab.rs

1use std::fmt;
2
3use downcast_rs::{impl_downcast, Downcast};
4
5use crate::{
6    backend::input::ButtonState,
7    input::SeatHandler,
8    utils::{Logical, Point},
9};
10
11use super::{
12    AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent,
13    GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent,
14    GestureSwipeUpdateEvent, MotionEvent, PointerInnerHandle, RelativeMotionEvent,
15};
16
17/// A trait to implement a pointer grab
18///
19/// In some context, it is necessary to temporarily change the behavior of the pointer. This is
20/// typically known as a pointer grab. A typical example would be, during a drag'n'drop operation,
21/// the underlying surfaces will no longer receive classic pointer event, but rather special events.
22///
23/// This trait is the interface to intercept regular pointer events and change them as needed, its
24/// interface mimics the [`PointerHandle`](super::PointerHandle) interface.
25///
26/// Any interactions with [`PointerHandle`](super::PointerHandle)
27/// should be done using [`PointerInnerHandle`], as handle is borrowed/locked before grab methods are called,
28/// so calling methods on [`PointerHandle`](super::PointerHandle) would result in a deadlock.
29///
30/// If your logic decides that the grab should end, both [`PointerInnerHandle`]
31/// and [`PointerHandle`](super::PointerHandle) have
32/// a method to change it.
33///
34/// When your grab ends (either as you requested it or if it was forcefully cancelled by the server),
35/// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor,
36/// rather than trying to guess when the grab will end.
37pub trait PointerGrab<D: SeatHandler>: Send + Downcast {
38    /// A motion was reported
39    ///
40    /// This method allows you attach additional behavior to a motion event, possibly altering it.
41    /// You generally will want to invoke `PointerInnerHandle::motion()` as part of your processing. If you
42    /// don't, the rest of the compositor will behave as if the motion event never occurred.
43    ///
44    /// Some grabs (such as drag'n'drop, shell resize and motion) unset the focus while they are active,
45    /// this is achieved by just setting the focus to `None` when invoking `PointerInnerHandle::motion()`.
46    fn motion(
47        &mut self,
48        data: &mut D,
49        handle: &mut PointerInnerHandle<'_, D>,
50        focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
51        event: &MotionEvent,
52    );
53    /// Relative motion was reported
54    ///
55    /// This method allows you attach additional behavior to a relative motion event, possibly altering it.
56    /// You generally will want to invoke `PointerInnerHandle::relative_motion()` as part of your processing.
57    /// If you don't, the rest of the compositor will behave as if the motion event never occurred.
58    fn relative_motion(
59        &mut self,
60        data: &mut D,
61        handle: &mut PointerInnerHandle<'_, D>,
62        focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
63        event: &RelativeMotionEvent,
64    );
65    /// A button press was reported
66    ///
67    /// This method allows you attach additional behavior to a button event, possibly altering it.
68    /// You generally will want to invoke `PointerInnerHandle::button()` as part of your processing. If you
69    /// don't, the rest of the compositor will behave as if the button event never occurred.
70    fn button(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, event: &ButtonEvent);
71    /// An axis scroll was reported
72    ///
73    /// This method allows you attach additional behavior to an axis event, possibly altering it.
74    /// You generally will want to invoke `PointerInnerHandle::axis()` as part of your processing. If you
75    /// don't, the rest of the compositor will behave as if the axis event never occurred.
76    fn axis(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, details: AxisFrame);
77    /// End of a pointer frame
78    ///
79    /// A frame groups associated events. This terminates the frame.
80    fn frame(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>);
81    /// A pointer of a given seat started a swipe gesture
82    ///
83    /// This method allows you attach additional behavior to a swipe gesture begin event, possibly altering it.
84    /// You generally will want to invoke `PointerInnerHandle::gesture_swipe_begin()` as part of your processing.
85    /// If you don't, the rest of the compositor will behave as if the event never occurred.
86    fn gesture_swipe_begin(
87        &mut self,
88        data: &mut D,
89        handle: &mut PointerInnerHandle<'_, D>,
90        event: &GestureSwipeBeginEvent,
91    );
92    /// A pointer of a given seat updated a swipe gesture
93    ///
94    /// This method allows you attach additional behavior to a swipe gesture update event, possibly altering it.
95    /// You generally will want to invoke `PointerInnerHandle::gesture_swipe_update()` as part of your processing.
96    /// If you don't, the rest of the compositor will behave as if the event never occurred.
97    fn gesture_swipe_update(
98        &mut self,
99        data: &mut D,
100        handle: &mut PointerInnerHandle<'_, D>,
101        event: &GestureSwipeUpdateEvent,
102    );
103    /// A pointer of a given seat ended a swipe gesture
104    ///
105    /// This method allows you attach additional behavior to a swipe gesture end event, possibly altering it.
106    /// You generally will want to invoke `PointerInnerHandle::gesture_swipe_end()` as part of your processing.
107    /// If you don't, the rest of the compositor will behave as if the event never occurred.
108    fn gesture_swipe_end(
109        &mut self,
110        data: &mut D,
111        handle: &mut PointerInnerHandle<'_, D>,
112        event: &GestureSwipeEndEvent,
113    );
114    /// A pointer of a given seat started a pinch gesture
115    ///
116    /// This method allows you attach additional behavior to a pinch gesture begin event, possibly altering it.
117    /// You generally will want to invoke `PointerInnerHandle::gesture_pinch_begin()` as part of your processing.
118    /// If you don't, the rest of the compositor will behave as if the event never occurred.
119    fn gesture_pinch_begin(
120        &mut self,
121        data: &mut D,
122        handle: &mut PointerInnerHandle<'_, D>,
123        event: &GesturePinchBeginEvent,
124    );
125    /// A pointer of a given seat updated a pinch gesture
126    ///
127    /// This method allows you attach additional behavior to a pinch gesture update event, possibly altering it.
128    /// You generally will want to invoke `PointerInnerHandle::gesture_pinch_update()` as part of your processing.
129    /// If you don't, the rest of the compositor will behave as if the event never occurred.
130    fn gesture_pinch_update(
131        &mut self,
132        data: &mut D,
133        handle: &mut PointerInnerHandle<'_, D>,
134        event: &GesturePinchUpdateEvent,
135    );
136    /// A pointer of a given seat ended a pinch gesture
137    ///
138    /// This method allows you attach additional behavior to a pinch gesture end event, possibly altering it.
139    /// You generally will want to invoke `PointerInnerHandle::gesture_pinch_end()` as part of your processing.
140    /// If you don't, the rest of the compositor will behave as if the event never occurred.
141    fn gesture_pinch_end(
142        &mut self,
143        data: &mut D,
144        handle: &mut PointerInnerHandle<'_, D>,
145        event: &GesturePinchEndEvent,
146    );
147    /// A pointer of a given seat started a hold gesture
148    ///
149    /// This method allows you attach additional behavior to a hold gesture begin event, possibly altering it.
150    /// You generally will want to invoke `PointerInnerHandle::gesture_hold_begin()` as part of your processing.
151    /// If you don't, the rest of the compositor will behave as if the event never occurred.
152    fn gesture_hold_begin(
153        &mut self,
154        data: &mut D,
155        handle: &mut PointerInnerHandle<'_, D>,
156        event: &GestureHoldBeginEvent,
157    );
158    /// A pointer of a given seat ended a hold gesture
159    ///
160    /// This method allows you attach additional behavior to a hold gesture end event, possibly altering it.
161    /// You generally will want to invoke `PointerInnerHandle::gesture_hold_end()` as part of your processing.
162    /// If you don't, the rest of the compositor will behave as if the event never occurred.
163    fn gesture_hold_end(
164        &mut self,
165        data: &mut D,
166        handle: &mut PointerInnerHandle<'_, D>,
167        event: &GestureHoldEndEvent,
168    );
169    /// The data about the event that started the grab.
170    fn start_data(&self) -> &GrabStartData<D>;
171    /// The grab has been unset or replaced with another grab.
172    fn unset(&mut self, data: &mut D);
173}
174
175impl_downcast!(PointerGrab<D> where D: SeatHandler);
176
177/// Data about the event that started the grab.
178pub struct GrabStartData<D: SeatHandler> {
179    /// The focused surface and its location, if any, at the start of the grab.
180    ///
181    /// The location coordinates are in the global compositor space.
182    pub focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
183    /// The button that initiated the grab.
184    pub button: u32,
185    /// The location of the click that initiated the grab, in the global compositor space.
186    pub location: Point<f64, Logical>,
187}
188
189impl<D: SeatHandler + 'static> fmt::Debug for GrabStartData<D> {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        f.debug_struct("GrabStartData")
192            .field("focus", &self.focus.as_ref().map(|_| "..."))
193            .field("button", &self.button)
194            .field("location", &self.location)
195            .finish()
196    }
197}
198
199impl<D: SeatHandler + 'static> Clone for GrabStartData<D> {
200    fn clone(&self) -> Self {
201        GrabStartData {
202            focus: self.focus.clone(),
203            button: self.button,
204            location: self.location,
205        }
206    }
207}
208
209// The default grab, the behavior when no particular grab is in progress
210pub(super) struct DefaultGrab;
211
212impl<D: SeatHandler + 'static> PointerGrab<D> for DefaultGrab {
213    fn motion(
214        &mut self,
215        data: &mut D,
216        handle: &mut PointerInnerHandle<'_, D>,
217        focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
218        event: &MotionEvent,
219    ) {
220        handle.motion(data, focus, event);
221    }
222
223    fn relative_motion(
224        &mut self,
225        data: &mut D,
226        handle: &mut PointerInnerHandle<'_, D>,
227        focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
228        event: &RelativeMotionEvent,
229    ) {
230        handle.relative_motion(data, focus, event);
231    }
232
233    fn button(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, event: &ButtonEvent) {
234        handle.button(data, event);
235        if event.state == ButtonState::Pressed {
236            handle.set_grab(
237                self,
238                data,
239                event.serial,
240                Focus::Keep,
241                ClickGrab {
242                    start_data: GrabStartData {
243                        focus: handle.current_focus(),
244                        button: event.button,
245                        location: handle.current_location(),
246                    },
247                },
248            );
249        }
250    }
251
252    fn axis(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, details: AxisFrame) {
253        handle.axis(data, details);
254    }
255
256    fn frame(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>) {
257        handle.frame(data);
258    }
259
260    fn gesture_swipe_begin(
261        &mut self,
262        data: &mut D,
263        handle: &mut PointerInnerHandle<'_, D>,
264        event: &GestureSwipeBeginEvent,
265    ) {
266        handle.gesture_swipe_begin(data, event);
267    }
268
269    fn gesture_swipe_update(
270        &mut self,
271        data: &mut D,
272        handle: &mut PointerInnerHandle<'_, D>,
273        event: &GestureSwipeUpdateEvent,
274    ) {
275        handle.gesture_swipe_update(data, event);
276    }
277
278    fn gesture_swipe_end(
279        &mut self,
280        data: &mut D,
281        handle: &mut PointerInnerHandle<'_, D>,
282        event: &GestureSwipeEndEvent,
283    ) {
284        handle.gesture_swipe_end(data, event);
285    }
286
287    fn gesture_pinch_begin(
288        &mut self,
289        data: &mut D,
290        handle: &mut PointerInnerHandle<'_, D>,
291        event: &GesturePinchBeginEvent,
292    ) {
293        handle.gesture_pinch_begin(data, event);
294    }
295
296    fn gesture_pinch_update(
297        &mut self,
298        data: &mut D,
299        handle: &mut PointerInnerHandle<'_, D>,
300        event: &GesturePinchUpdateEvent,
301    ) {
302        handle.gesture_pinch_update(data, event);
303    }
304
305    fn gesture_pinch_end(
306        &mut self,
307        data: &mut D,
308        handle: &mut PointerInnerHandle<'_, D>,
309        event: &GesturePinchEndEvent,
310    ) {
311        handle.gesture_pinch_end(data, event);
312    }
313
314    fn gesture_hold_begin(
315        &mut self,
316        data: &mut D,
317        handle: &mut PointerInnerHandle<'_, D>,
318        event: &GestureHoldBeginEvent,
319    ) {
320        handle.gesture_hold_begin(data, event);
321    }
322
323    fn gesture_hold_end(
324        &mut self,
325        data: &mut D,
326        handle: &mut PointerInnerHandle<'_, D>,
327        event: &GestureHoldEndEvent,
328    ) {
329        handle.gesture_hold_end(data, event);
330    }
331
332    fn start_data(&self) -> &GrabStartData<D> {
333        unreachable!()
334    }
335
336    fn unset(&mut self, _data: &mut D) {}
337}
338
339/// A click grab, basic grab started when an user clicks a surface
340/// to maintain it focused until the user releases the click.
341///
342/// In case the user maintains several simultaneous clicks, release
343/// the grab once all are released.
344pub struct ClickGrab<D: SeatHandler> {
345    start_data: GrabStartData<D>,
346}
347
348impl<D: SeatHandler + 'static> fmt::Debug for ClickGrab<D> {
349    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350        f.debug_struct("ClickGrab")
351            .field("start_data", &self.start_data)
352            .finish()
353    }
354}
355
356impl<D: SeatHandler + 'static> PointerGrab<D> for ClickGrab<D> {
357    fn motion(
358        &mut self,
359        data: &mut D,
360        handle: &mut PointerInnerHandle<'_, D>,
361        _focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
362        event: &MotionEvent,
363    ) {
364        handle.motion(data, self.start_data.focus.clone(), event);
365    }
366
367    fn relative_motion(
368        &mut self,
369        data: &mut D,
370        handle: &mut PointerInnerHandle<'_, D>,
371        focus: Option<(<D as SeatHandler>::PointerFocus, Point<f64, Logical>)>,
372        event: &RelativeMotionEvent,
373    ) {
374        handle.relative_motion(data, focus, event);
375    }
376
377    fn button(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, event: &ButtonEvent) {
378        handle.button(data, event);
379        if handle.current_pressed().is_empty() {
380            // no more buttons are pressed, release the grab
381            handle.unset_grab(self, data, event.serial, event.time, false);
382        }
383    }
384
385    fn axis(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>, details: AxisFrame) {
386        handle.axis(data, details);
387    }
388
389    fn frame(&mut self, data: &mut D, handle: &mut PointerInnerHandle<'_, D>) {
390        handle.frame(data);
391    }
392
393    fn gesture_swipe_begin(
394        &mut self,
395        data: &mut D,
396        handle: &mut PointerInnerHandle<'_, D>,
397        event: &GestureSwipeBeginEvent,
398    ) {
399        handle.gesture_swipe_begin(data, event);
400    }
401
402    fn gesture_swipe_update(
403        &mut self,
404        data: &mut D,
405        handle: &mut PointerInnerHandle<'_, D>,
406        event: &GestureSwipeUpdateEvent,
407    ) {
408        handle.gesture_swipe_update(data, event);
409    }
410
411    fn gesture_swipe_end(
412        &mut self,
413        data: &mut D,
414        handle: &mut PointerInnerHandle<'_, D>,
415        event: &GestureSwipeEndEvent,
416    ) {
417        handle.gesture_swipe_end(data, event);
418    }
419
420    fn gesture_pinch_begin(
421        &mut self,
422        data: &mut D,
423        handle: &mut PointerInnerHandle<'_, D>,
424        event: &GesturePinchBeginEvent,
425    ) {
426        handle.gesture_pinch_begin(data, event);
427    }
428
429    fn gesture_pinch_update(
430        &mut self,
431        data: &mut D,
432        handle: &mut PointerInnerHandle<'_, D>,
433        event: &GesturePinchUpdateEvent,
434    ) {
435        handle.gesture_pinch_update(data, event);
436    }
437
438    fn gesture_pinch_end(
439        &mut self,
440        data: &mut D,
441        handle: &mut PointerInnerHandle<'_, D>,
442        event: &GesturePinchEndEvent,
443    ) {
444        handle.gesture_pinch_end(data, event);
445    }
446
447    fn gesture_hold_begin(
448        &mut self,
449        data: &mut D,
450        handle: &mut PointerInnerHandle<'_, D>,
451        event: &GestureHoldBeginEvent,
452    ) {
453        handle.gesture_hold_begin(data, event);
454    }
455
456    fn gesture_hold_end(
457        &mut self,
458        data: &mut D,
459        handle: &mut PointerInnerHandle<'_, D>,
460        event: &GestureHoldEndEvent,
461    ) {
462        handle.gesture_hold_end(data, event);
463    }
464
465    fn start_data(&self) -> &GrabStartData<D> {
466        &self.start_data
467    }
468
469    fn unset(&mut self, _data: &mut D) {}
470}