gtk4/auto/gesture.rs
1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4#![allow(deprecated)]
5
6use crate::{ffi, EventController, EventSequenceState};
7use glib::{
8 object::ObjectType as _,
9 prelude::*,
10 signal::{connect_raw, SignalHandlerId},
11 translate::*,
12};
13use std::boxed::Box as Box_;
14
15glib::wrapper! {
16 /// The base class for gesture recognition.
17 ///
18 /// Although [`Gesture`][crate::Gesture] is quite generalized to serve as a base for
19 /// multi-touch gestures, it is suitable to implement single-touch and
20 /// pointer-based gestures (using the special [`None`] [`gdk::EventSequence`][crate::gdk::EventSequence]
21 /// value for these).
22 ///
23 /// The number of touches that a [`Gesture`][crate::Gesture] need to be recognized is
24 /// controlled by the [`n-points`][struct@crate::Gesture#n-points] property, if a
25 /// gesture is keeping track of less or more than that number of sequences,
26 /// it won't check whether the gesture is recognized.
27 ///
28 /// As soon as the gesture has the expected number of touches, it will check
29 /// regularly if it is recognized, the criteria to consider a gesture as
30 /// "recognized" is left to [`Gesture`][crate::Gesture] subclasses.
31 ///
32 /// A recognized gesture will then emit the following signals:
33 ///
34 /// - [`begin`][struct@crate::Gesture#begin] when the gesture is recognized.
35 /// - [`update`][struct@crate::Gesture#update], whenever an input event is processed.
36 /// - [`end`][struct@crate::Gesture#end] when the gesture is no longer recognized.
37 ///
38 /// ## Event propagation
39 ///
40 /// In order to receive events, a gesture needs to set a propagation phase
41 /// through [`EventControllerExt::set_propagation_phase()`][crate::prelude::EventControllerExt::set_propagation_phase()].
42 ///
43 /// In the capture phase, events are propagated from the toplevel down
44 /// to the target widget, and gestures that are attached to containers
45 /// above the widget get a chance to interact with the event before it
46 /// reaches the target.
47 ///
48 /// In the bubble phase, events are propagated up from the target widget
49 /// to the toplevel, and gestures that are attached to containers above
50 /// the widget get a chance to interact with events that have not been
51 /// handled yet.
52 ///
53 /// ## States of a sequence
54 ///
55 /// Whenever input interaction happens, a single event may trigger a cascade
56 /// of [`Gesture`][crate::Gesture]s, both across the parents of the widget receiving the
57 /// event and in parallel within an individual widget. It is a responsibility
58 /// of the widgets using those gestures to set the state of touch sequences
59 /// accordingly in order to enable cooperation of gestures around the
60 /// [`gdk::EventSequence`][crate::gdk::EventSequence]s triggering those.
61 ///
62 /// Within a widget, gestures can be grouped through [`GestureExt::group_with()`][crate::prelude::GestureExt::group_with()].
63 /// Grouped gestures synchronize the state of sequences, so calling
64 /// [`GestureExt::set_state()`][crate::prelude::GestureExt::set_state()] on one will effectively propagate
65 /// the state throughout the group.
66 ///
67 /// By default, all sequences start out in the [`EventSequenceState::None`][crate::EventSequenceState::None] state,
68 /// sequences in this state trigger the gesture event handler, but event
69 /// propagation will continue unstopped by gestures.
70 ///
71 /// If a sequence enters into the [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] state, the gesture
72 /// group will effectively ignore the sequence, letting events go unstopped
73 /// through the gesture, but the "slot" will still remain occupied while
74 /// the touch is active.
75 ///
76 /// If a sequence enters in the [`EventSequenceState::Claimed`][crate::EventSequenceState::Claimed] state, the gesture
77 /// group will grab all interaction on the sequence, by:
78 ///
79 /// - Setting the same sequence to [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] on every other
80 /// gesture group within the widget, and every gesture on parent widgets
81 /// in the propagation chain.
82 /// - Emitting [`cancel`][struct@crate::Gesture#cancel] on every gesture in widgets
83 /// underneath in the propagation chain.
84 /// - Stopping event propagation after the gesture group handles the event.
85 ///
86 /// Note: if a sequence is set early to [`EventSequenceState::Claimed`][crate::EventSequenceState::Claimed] on
87 /// `GDK_TOUCH_BEGIN`/`GDK_BUTTON_PRESS` (so those events are captured before
88 /// reaching the event widget, this implies [`PropagationPhase::Capture`][crate::PropagationPhase::Capture]), one similar
89 /// event will be emulated if the sequence changes to [`EventSequenceState::Denied`][crate::EventSequenceState::Denied].
90 /// This way event coherence is preserved before event propagation is unstopped
91 /// again.
92 ///
93 /// Sequence states can't be changed freely.
94 /// See [`GestureExt::set_state()`][crate::prelude::GestureExt::set_state()] to know about the possible
95 /// lifetimes of a [`gdk::EventSequence`][crate::gdk::EventSequence].
96 ///
97 /// ## Touchpad gestures
98 ///
99 /// On the platforms that support it, [`Gesture`][crate::Gesture] will handle transparently
100 /// touchpad gesture events. The only precautions users of [`Gesture`][crate::Gesture] should
101 /// do to enable this support are:
102 ///
103 /// - If the gesture has [`PropagationPhase::None`][crate::PropagationPhase::None], ensuring events of type
104 /// `GDK_TOUCHPAD_SWIPE` and `GDK_TOUCHPAD_PINCH` are handled by the [`Gesture`][crate::Gesture]
105 ///
106 /// This is an Abstract Base Class, you cannot instantiate it.
107 ///
108 /// ## Properties
109 ///
110 ///
111 /// #### `n-points`
112 /// The number of touch points that trigger
113 /// recognition on this gesture.
114 ///
115 /// Readable | Writeable | Construct Only
116 /// <details><summary><h4>EventController</h4></summary>
117 ///
118 ///
119 /// #### `name`
120 /// The name for this controller, typically used for debugging purposes.
121 ///
122 /// Readable | Writeable
123 ///
124 ///
125 /// #### `propagation-limit`
126 /// The limit for which events this controller will handle.
127 ///
128 /// Readable | Writeable
129 ///
130 ///
131 /// #### `propagation-phase`
132 /// The propagation phase at which this controller will handle events.
133 ///
134 /// Readable | Writeable
135 ///
136 ///
137 /// #### `widget`
138 /// The widget receiving the `GdkEvents` that the controller will handle.
139 ///
140 /// Readable
141 /// </details>
142 ///
143 /// ## Signals
144 ///
145 ///
146 /// #### `begin`
147 /// Emitted when the gesture is recognized.
148 ///
149 /// This means the number of touch sequences matches
150 /// [`n-points`][struct@crate::Gesture#n-points].
151 ///
152 /// Note: These conditions may also happen when an extra touch
153 /// (eg. a third touch on a 2-touches gesture) is lifted, in that
154 /// situation @sequence won't pertain to the current set of active
155 /// touches, so don't rely on this being true.
156 ///
157 ///
158 ///
159 ///
160 /// #### `cancel`
161 /// Emitted whenever a sequence is cancelled.
162 ///
163 /// This usually happens on active touches when
164 /// [`EventControllerExt::reset()`][crate::prelude::EventControllerExt::reset()] is called on @gesture
165 /// (manually, due to grabs...), or the individual @sequence
166 /// was claimed by parent widgets' controllers (see
167 /// [`GestureExt::set_sequence_state()`][crate::prelude::GestureExt::set_sequence_state()]).
168 ///
169 /// @gesture must forget everything about @sequence as in
170 /// response to this signal.
171 ///
172 ///
173 ///
174 ///
175 /// #### `end`
176 /// Emitted when @gesture either stopped recognizing the event
177 /// sequences as something to be handled, or the number of touch
178 /// sequences became higher or lower than [`n-points`][struct@crate::Gesture#n-points].
179 ///
180 /// Note: @sequence might not pertain to the group of sequences that
181 /// were previously triggering recognition on @gesture (ie. a just
182 /// pressed touch sequence that exceeds [`n-points`][struct@crate::Gesture#n-points]).
183 /// This situation may be detected by checking through
184 /// [`GestureExt::handles_sequence()`][crate::prelude::GestureExt::handles_sequence()].
185 ///
186 ///
187 ///
188 ///
189 /// #### `sequence-state-changed`
190 /// Emitted whenever a sequence state changes.
191 ///
192 /// See [`GestureExt::set_sequence_state()`][crate::prelude::GestureExt::set_sequence_state()] to know
193 /// more about the expectable sequence lifetimes.
194 ///
195 ///
196 ///
197 ///
198 /// #### `update`
199 /// Emitted whenever an event is handled while the gesture is recognized.
200 ///
201 /// @sequence is guaranteed to pertain to the set of active touches.
202 ///
203 ///
204 ///
205 /// # Implements
206 ///
207 /// [`GestureExt`][trait@crate::prelude::GestureExt], [`EventControllerExt`][trait@crate::prelude::EventControllerExt], [`trait@glib::ObjectExt`]
208 #[doc(alias = "GtkGesture")]
209 pub struct Gesture(Object<ffi::GtkGesture, ffi::GtkGestureClass>) @extends EventController;
210
211 match fn {
212 type_ => || ffi::gtk_gesture_get_type(),
213 }
214}
215
216impl Gesture {
217 pub const NONE: Option<&'static Gesture> = None;
218}
219
220/// Trait containing all [`struct@Gesture`] methods.
221///
222/// # Implementors
223///
224/// [`GestureRotate`][struct@crate::GestureRotate], [`GestureSingle`][struct@crate::GestureSingle], [`GestureZoom`][struct@crate::GestureZoom], [`Gesture`][struct@crate::Gesture]
225pub trait GestureExt: IsA<Gesture> + 'static {
226 /// If there are touch sequences being currently handled by @self,
227 /// returns [`true`] and fills in @rect with the bounding box containing
228 /// all active touches.
229 ///
230 /// Otherwise, [`false`] will be returned.
231 ///
232 /// Note: This function will yield unexpected results on touchpad
233 /// gestures. Since there is no correlation between physical and
234 /// pixel distances, these will look as if constrained in an
235 /// infinitely small area, @rect width and height will thus be 0
236 /// regardless of the number of touchpoints.
237 ///
238 /// # Returns
239 ///
240 /// [`true`] if there are active touches, [`false`] otherwise
241 ///
242 /// ## `rect`
243 /// bounding box containing all active touches.
244 #[doc(alias = "gtk_gesture_get_bounding_box")]
245 #[doc(alias = "get_bounding_box")]
246 fn bounding_box(&self) -> Option<gdk::Rectangle> {
247 unsafe {
248 let mut rect = gdk::Rectangle::uninitialized();
249 let ret = from_glib(ffi::gtk_gesture_get_bounding_box(
250 self.as_ref().to_glib_none().0,
251 rect.to_glib_none_mut().0,
252 ));
253 if ret {
254 Some(rect)
255 } else {
256 None
257 }
258 }
259 }
260
261 /// If there are touch sequences being currently handled by @self,
262 /// returns [`true`] and fills in @x and @y with the center of the bounding
263 /// box containing all active touches.
264 ///
265 /// Otherwise, [`false`] will be returned.
266 ///
267 /// # Returns
268 ///
269 /// [`false`] if no active touches are present, [`true`] otherwise
270 ///
271 /// ## `x`
272 /// X coordinate for the bounding box center
273 ///
274 /// ## `y`
275 /// Y coordinate for the bounding box center
276 #[doc(alias = "gtk_gesture_get_bounding_box_center")]
277 #[doc(alias = "get_bounding_box_center")]
278 fn bounding_box_center(&self) -> Option<(f64, f64)> {
279 unsafe {
280 let mut x = std::mem::MaybeUninit::uninit();
281 let mut y = std::mem::MaybeUninit::uninit();
282 let ret = from_glib(ffi::gtk_gesture_get_bounding_box_center(
283 self.as_ref().to_glib_none().0,
284 x.as_mut_ptr(),
285 y.as_mut_ptr(),
286 ));
287 if ret {
288 Some((x.assume_init(), y.assume_init()))
289 } else {
290 None
291 }
292 }
293 }
294
295 /// Returns the logical [`gdk::Device`][crate::gdk::Device] that is currently operating
296 /// on @self.
297 ///
298 /// This returns [`None`] if the gesture is not being interacted.
299 ///
300 /// # Returns
301 ///
302 /// a [`gdk::Device`][crate::gdk::Device]
303 #[doc(alias = "gtk_gesture_get_device")]
304 #[doc(alias = "get_device")]
305 fn device(&self) -> Option<gdk::Device> {
306 unsafe { from_glib_none(ffi::gtk_gesture_get_device(self.as_ref().to_glib_none().0)) }
307 }
308
309 /// Returns all gestures in the group of @self
310 ///
311 /// # Returns
312 ///
313 /// The list
314 /// of [`Gesture`][crate::Gesture]s, free with g_list_free()
315 #[doc(alias = "gtk_gesture_get_group")]
316 #[doc(alias = "get_group")]
317 fn group(&self) -> Vec<Gesture> {
318 unsafe {
319 FromGlibPtrContainer::from_glib_container(ffi::gtk_gesture_get_group(
320 self.as_ref().to_glib_none().0,
321 ))
322 }
323 }
324
325 /// Returns the last event that was processed for @sequence.
326 ///
327 /// Note that the returned pointer is only valid as long as the
328 /// @sequence is still interpreted by the @self. If in doubt,
329 /// you should make a copy of the event.
330 /// ## `sequence`
331 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
332 ///
333 /// # Returns
334 ///
335 /// The last event from @sequence
336 #[doc(alias = "gtk_gesture_get_last_event")]
337 #[doc(alias = "get_last_event")]
338 fn last_event(&self, sequence: Option<&gdk::EventSequence>) -> Option<gdk::Event> {
339 unsafe {
340 from_glib_none(ffi::gtk_gesture_get_last_event(
341 self.as_ref().to_glib_none().0,
342 mut_override(sequence.to_glib_none().0),
343 ))
344 }
345 }
346
347 /// Returns the [`gdk::EventSequence`][crate::gdk::EventSequence] that was last updated on @self.
348 ///
349 /// # Returns
350 ///
351 /// The last updated sequence
352 #[doc(alias = "gtk_gesture_get_last_updated_sequence")]
353 #[doc(alias = "get_last_updated_sequence")]
354 fn last_updated_sequence(&self) -> Option<gdk::EventSequence> {
355 unsafe {
356 from_glib_none(ffi::gtk_gesture_get_last_updated_sequence(
357 self.as_ref().to_glib_none().0,
358 ))
359 }
360 }
361
362 /// If @sequence is currently being interpreted by @self,
363 /// returns [`true`] and fills in @x and @y with the last coordinates
364 /// stored for that event sequence.
365 ///
366 /// The coordinates are always relative to the widget allocation.
367 /// ## `sequence`
368 /// a [`gdk::EventSequence`][crate::gdk::EventSequence], or [`None`] for pointer events
369 ///
370 /// # Returns
371 ///
372 /// [`true`] if @sequence is currently interpreted
373 ///
374 /// ## `x`
375 /// return location for X axis of the sequence coordinates
376 ///
377 /// ## `y`
378 /// return location for Y axis of the sequence coordinates
379 #[doc(alias = "gtk_gesture_get_point")]
380 #[doc(alias = "get_point")]
381 fn point(&self, sequence: Option<&gdk::EventSequence>) -> Option<(f64, f64)> {
382 unsafe {
383 let mut x = std::mem::MaybeUninit::uninit();
384 let mut y = std::mem::MaybeUninit::uninit();
385 let ret = from_glib(ffi::gtk_gesture_get_point(
386 self.as_ref().to_glib_none().0,
387 mut_override(sequence.to_glib_none().0),
388 x.as_mut_ptr(),
389 y.as_mut_ptr(),
390 ));
391 if ret {
392 Some((x.assume_init(), y.assume_init()))
393 } else {
394 None
395 }
396 }
397 }
398
399 /// Returns the @sequence state, as seen by @self.
400 /// ## `sequence`
401 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
402 ///
403 /// # Returns
404 ///
405 /// The sequence state in @self
406 #[doc(alias = "gtk_gesture_get_sequence_state")]
407 #[doc(alias = "get_sequence_state")]
408 fn sequence_state(&self, sequence: &gdk::EventSequence) -> EventSequenceState {
409 unsafe {
410 from_glib(ffi::gtk_gesture_get_sequence_state(
411 self.as_ref().to_glib_none().0,
412 mut_override(sequence.to_glib_none().0),
413 ))
414 }
415 }
416
417 /// Returns the list of `GdkEventSequences` currently being interpreted
418 /// by @self.
419 ///
420 /// # Returns
421 ///
422 /// A list
423 /// of [`gdk::EventSequence`][crate::gdk::EventSequence], the list elements are owned by GTK and must
424 /// not be freed or modified, the list itself must be deleted
425 /// through g_list_free()
426 #[doc(alias = "gtk_gesture_get_sequences")]
427 #[doc(alias = "get_sequences")]
428 fn sequences(&self) -> Vec<gdk::EventSequence> {
429 unsafe {
430 FromGlibPtrContainer::from_glib_container(ffi::gtk_gesture_get_sequences(
431 self.as_ref().to_glib_none().0,
432 ))
433 }
434 }
435
436 /// Adds @gesture to the same group than @self.
437 ///
438 /// Gestures are by default isolated in their own groups.
439 ///
440 /// Both gestures must have been added to the same widget before
441 /// they can be grouped.
442 ///
443 /// When gestures are grouped, the state of `GdkEventSequences`
444 /// is kept in sync for all of those, so calling
445 /// [`set_sequence_state()`][Self::set_sequence_state()], on one will transfer
446 /// the same value to the others.
447 ///
448 /// Groups also perform an "implicit grabbing" of sequences, if a
449 /// [`gdk::EventSequence`][crate::gdk::EventSequence] state is set to [`EventSequenceState::Claimed`][crate::EventSequenceState::Claimed]
450 /// on one group, every other gesture group attached to the same
451 /// [`Widget`][crate::Widget] will switch the state for that sequence to
452 /// [`EventSequenceState::Denied`][crate::EventSequenceState::Denied].
453 /// ## `gesture`
454 /// a [`Gesture`][crate::Gesture]
455 #[doc(alias = "gtk_gesture_group")]
456 #[doc(alias = "group")]
457 fn group_with(&self, gesture: &impl IsA<Gesture>) {
458 unsafe {
459 ffi::gtk_gesture_group(
460 self.as_ref().to_glib_none().0,
461 gesture.as_ref().to_glib_none().0,
462 );
463 }
464 }
465
466 /// Returns [`true`] if @self is currently handling events
467 /// corresponding to @sequence.
468 /// ## `sequence`
469 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
470 ///
471 /// # Returns
472 ///
473 /// [`true`] if @self is handling @sequence, [`false`] otherwise
474 #[doc(alias = "gtk_gesture_handles_sequence")]
475 fn handles_sequence(&self, sequence: Option<&gdk::EventSequence>) -> bool {
476 unsafe {
477 from_glib(ffi::gtk_gesture_handles_sequence(
478 self.as_ref().to_glib_none().0,
479 mut_override(sequence.to_glib_none().0),
480 ))
481 }
482 }
483
484 /// Returns [`true`] if the gesture is currently active.
485 ///
486 /// A gesture is active while there are touch sequences
487 /// interacting with it.
488 ///
489 /// # Returns
490 ///
491 /// [`true`] if gesture is active
492 #[doc(alias = "gtk_gesture_is_active")]
493 fn is_active(&self) -> bool {
494 unsafe { from_glib(ffi::gtk_gesture_is_active(self.as_ref().to_glib_none().0)) }
495 }
496
497 /// Returns [`true`] if both gestures pertain to the same group.
498 /// ## `other`
499 /// another [`Gesture`][crate::Gesture]
500 ///
501 /// # Returns
502 ///
503 /// whether the gestures are grouped
504 #[doc(alias = "gtk_gesture_is_grouped_with")]
505 fn is_grouped_with(&self, other: &impl IsA<Gesture>) -> bool {
506 unsafe {
507 from_glib(ffi::gtk_gesture_is_grouped_with(
508 self.as_ref().to_glib_none().0,
509 other.as_ref().to_glib_none().0,
510 ))
511 }
512 }
513
514 /// Returns [`true`] if the gesture is currently recognized.
515 ///
516 /// A gesture is recognized if there are as many interacting
517 /// touch sequences as required by @self.
518 ///
519 /// # Returns
520 ///
521 /// [`true`] if gesture is recognized
522 #[doc(alias = "gtk_gesture_is_recognized")]
523 fn is_recognized(&self) -> bool {
524 unsafe {
525 from_glib(ffi::gtk_gesture_is_recognized(
526 self.as_ref().to_glib_none().0,
527 ))
528 }
529 }
530
531 /// Sets the state of @sequence in @self.
532 ///
533 /// Sequences start in state [`EventSequenceState::None`][crate::EventSequenceState::None], and whenever
534 /// they change state, they can never go back to that state. Likewise,
535 /// sequences in state [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] cannot turn back to
536 /// a not denied state. With these rules, the lifetime of an event
537 /// sequence is constrained to the next four:
538 ///
539 /// * None
540 /// * None → Denied
541 /// * None → Claimed
542 /// * None → Claimed → Denied
543 ///
544 /// Note: Due to event handling ordering, it may be unsafe to set the
545 /// state on another gesture within a [`begin`][struct@crate::Gesture#begin] signal
546 /// handler, as the callback might be executed before the other gesture
547 /// knows about the sequence. A safe way to perform this could be:
548 ///
549 /// **⚠️ The following code is in c ⚠️**
550 ///
551 /// ```c
552 /// static void
553 /// first_gesture_begin_cb (GtkGesture *first_gesture,
554 /// GdkEventSequence *sequence,
555 /// gpointer user_data)
556 /// {
557 /// gtk_gesture_set_sequence_state (first_gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
558 /// gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
559 /// }
560 ///
561 /// static void
562 /// second_gesture_begin_cb (GtkGesture *second_gesture,
563 /// GdkEventSequence *sequence,
564 /// gpointer user_data)
565 /// {
566 /// if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED)
567 /// gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
568 /// }
569 /// ```
570 ///
571 /// If both gestures are in the same group, just set the state on
572 /// the gesture emitting the event, the sequence will be already
573 /// be initialized to the group's global state when the second
574 /// gesture processes the event.
575 ///
576 /// # Deprecated since 4.10
577 ///
578 /// Use [`set_state()`][Self::set_state()]
579 /// ## `sequence`
580 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
581 /// ## `state`
582 /// the sequence state
583 ///
584 /// # Returns
585 ///
586 /// [`true`] if @sequence is handled by @self,
587 /// and the state is changed successfully
588 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
589 #[allow(deprecated)]
590 #[doc(alias = "gtk_gesture_set_sequence_state")]
591 fn set_sequence_state(&self, sequence: &gdk::EventSequence, state: EventSequenceState) -> bool {
592 unsafe {
593 from_glib(ffi::gtk_gesture_set_sequence_state(
594 self.as_ref().to_glib_none().0,
595 mut_override(sequence.to_glib_none().0),
596 state.into_glib(),
597 ))
598 }
599 }
600
601 /// Sets the state of all sequences that @self is currently
602 /// interacting with.
603 ///
604 /// Sequences start in state [`EventSequenceState::None`][crate::EventSequenceState::None], and whenever
605 /// they change state, they can never go back to that state. Likewise,
606 /// sequences in state [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] cannot turn back to
607 /// a not denied state. With these rules, the lifetime of an event
608 /// sequence is constrained to the next four:
609 ///
610 /// * None
611 /// * None → Denied
612 /// * None → Claimed
613 /// * None → Claimed → Denied
614 ///
615 /// Note: Due to event handling ordering, it may be unsafe to set the
616 /// state on another gesture within a [`begin`][struct@crate::Gesture#begin] signal
617 /// handler, as the callback might be executed before the other gesture
618 /// knows about the sequence. A safe way to perform this could be:
619 ///
620 /// **⚠️ The following code is in c ⚠️**
621 ///
622 /// ```c
623 /// static void
624 /// first_gesture_begin_cb (GtkGesture *first_gesture,
625 /// GdkEventSequence *sequence,
626 /// gpointer user_data)
627 /// {
628 /// gtk_gesture_set_state (first_gesture, GTK_EVENT_SEQUENCE_CLAIMED);
629 /// gtk_gesture_set_state (second_gesture, GTK_EVENT_SEQUENCE_DENIED);
630 /// }
631 ///
632 /// static void
633 /// second_gesture_begin_cb (GtkGesture *second_gesture,
634 /// GdkEventSequence *sequence,
635 /// gpointer user_data)
636 /// {
637 /// if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED)
638 /// gtk_gesture_set_state (second_gesture, GTK_EVENT_SEQUENCE_DENIED);
639 /// }
640 /// ```
641 ///
642 /// If both gestures are in the same group, just set the state on
643 /// the gesture emitting the event, the sequence will be already
644 /// be initialized to the group's global state when the second
645 /// gesture processes the event.
646 /// ## `state`
647 /// the sequence state
648 ///
649 /// # Returns
650 ///
651 /// [`true`] if the state of at least one sequence
652 /// was changed successfully
653 #[doc(alias = "gtk_gesture_set_state")]
654 fn set_state(&self, state: EventSequenceState) -> bool {
655 unsafe {
656 from_glib(ffi::gtk_gesture_set_state(
657 self.as_ref().to_glib_none().0,
658 state.into_glib(),
659 ))
660 }
661 }
662
663 /// Separates @self into an isolated group.
664 #[doc(alias = "gtk_gesture_ungroup")]
665 fn ungroup(&self) {
666 unsafe {
667 ffi::gtk_gesture_ungroup(self.as_ref().to_glib_none().0);
668 }
669 }
670
671 /// The number of touch points that trigger
672 /// recognition on this gesture.
673 #[doc(alias = "n-points")]
674 fn n_points(&self) -> u32 {
675 ObjectExt::property(self.as_ref(), "n-points")
676 }
677
678 /// Emitted when the gesture is recognized.
679 ///
680 /// This means the number of touch sequences matches
681 /// [`n-points`][struct@crate::Gesture#n-points].
682 ///
683 /// Note: These conditions may also happen when an extra touch
684 /// (eg. a third touch on a 2-touches gesture) is lifted, in that
685 /// situation @sequence won't pertain to the current set of active
686 /// touches, so don't rely on this being true.
687 /// ## `sequence`
688 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that made the gesture
689 /// to be recognized
690 #[doc(alias = "begin")]
691 fn connect_begin<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
692 &self,
693 f: F,
694 ) -> SignalHandlerId {
695 unsafe extern "C" fn begin_trampoline<
696 P: IsA<Gesture>,
697 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
698 >(
699 this: *mut ffi::GtkGesture,
700 sequence: *mut gdk::ffi::GdkEventSequence,
701 f: glib::ffi::gpointer,
702 ) {
703 let f: &F = &*(f as *const F);
704 f(
705 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
706 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
707 .as_ref()
708 .as_ref(),
709 )
710 }
711 unsafe {
712 let f: Box_<F> = Box_::new(f);
713 connect_raw(
714 self.as_ptr() as *mut _,
715 c"begin".as_ptr() as *const _,
716 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
717 begin_trampoline::<Self, F> as *const (),
718 )),
719 Box_::into_raw(f),
720 )
721 }
722 }
723
724 /// Emitted whenever a sequence is cancelled.
725 ///
726 /// This usually happens on active touches when
727 /// [`EventControllerExt::reset()`][crate::prelude::EventControllerExt::reset()] is called on @gesture
728 /// (manually, due to grabs...), or the individual @sequence
729 /// was claimed by parent widgets' controllers (see
730 /// [`set_sequence_state()`][Self::set_sequence_state()]).
731 ///
732 /// @gesture must forget everything about @sequence as in
733 /// response to this signal.
734 /// ## `sequence`
735 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was cancelled
736 #[doc(alias = "cancel")]
737 fn connect_cancel<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
738 &self,
739 f: F,
740 ) -> SignalHandlerId {
741 unsafe extern "C" fn cancel_trampoline<
742 P: IsA<Gesture>,
743 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
744 >(
745 this: *mut ffi::GtkGesture,
746 sequence: *mut gdk::ffi::GdkEventSequence,
747 f: glib::ffi::gpointer,
748 ) {
749 let f: &F = &*(f as *const F);
750 f(
751 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
752 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
753 .as_ref()
754 .as_ref(),
755 )
756 }
757 unsafe {
758 let f: Box_<F> = Box_::new(f);
759 connect_raw(
760 self.as_ptr() as *mut _,
761 c"cancel".as_ptr() as *const _,
762 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
763 cancel_trampoline::<Self, F> as *const (),
764 )),
765 Box_::into_raw(f),
766 )
767 }
768 }
769
770 /// Emitted when @gesture either stopped recognizing the event
771 /// sequences as something to be handled, or the number of touch
772 /// sequences became higher or lower than [`n-points`][struct@crate::Gesture#n-points].
773 ///
774 /// Note: @sequence might not pertain to the group of sequences that
775 /// were previously triggering recognition on @gesture (ie. a just
776 /// pressed touch sequence that exceeds [`n-points`][struct@crate::Gesture#n-points]).
777 /// This situation may be detected by checking through
778 /// [`handles_sequence()`][Self::handles_sequence()].
779 /// ## `sequence`
780 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that made gesture
781 /// recognition to finish
782 #[doc(alias = "end")]
783 fn connect_end<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
784 &self,
785 f: F,
786 ) -> SignalHandlerId {
787 unsafe extern "C" fn end_trampoline<
788 P: IsA<Gesture>,
789 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
790 >(
791 this: *mut ffi::GtkGesture,
792 sequence: *mut gdk::ffi::GdkEventSequence,
793 f: glib::ffi::gpointer,
794 ) {
795 let f: &F = &*(f as *const F);
796 f(
797 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
798 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
799 .as_ref()
800 .as_ref(),
801 )
802 }
803 unsafe {
804 let f: Box_<F> = Box_::new(f);
805 connect_raw(
806 self.as_ptr() as *mut _,
807 c"end".as_ptr() as *const _,
808 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
809 end_trampoline::<Self, F> as *const (),
810 )),
811 Box_::into_raw(f),
812 )
813 }
814 }
815
816 /// Emitted whenever a sequence state changes.
817 ///
818 /// See [`set_sequence_state()`][Self::set_sequence_state()] to know
819 /// more about the expectable sequence lifetimes.
820 /// ## `sequence`
821 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was cancelled
822 /// ## `state`
823 /// the new sequence state
824 #[doc(alias = "sequence-state-changed")]
825 fn connect_sequence_state_changed<
826 F: Fn(&Self, Option<&gdk::EventSequence>, EventSequenceState) + 'static,
827 >(
828 &self,
829 f: F,
830 ) -> SignalHandlerId {
831 unsafe extern "C" fn sequence_state_changed_trampoline<
832 P: IsA<Gesture>,
833 F: Fn(&P, Option<&gdk::EventSequence>, EventSequenceState) + 'static,
834 >(
835 this: *mut ffi::GtkGesture,
836 sequence: *mut gdk::ffi::GdkEventSequence,
837 state: ffi::GtkEventSequenceState,
838 f: glib::ffi::gpointer,
839 ) {
840 let f: &F = &*(f as *const F);
841 f(
842 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
843 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
844 .as_ref()
845 .as_ref(),
846 from_glib(state),
847 )
848 }
849 unsafe {
850 let f: Box_<F> = Box_::new(f);
851 connect_raw(
852 self.as_ptr() as *mut _,
853 c"sequence-state-changed".as_ptr() as *const _,
854 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
855 sequence_state_changed_trampoline::<Self, F> as *const (),
856 )),
857 Box_::into_raw(f),
858 )
859 }
860 }
861
862 /// Emitted whenever an event is handled while the gesture is recognized.
863 ///
864 /// @sequence is guaranteed to pertain to the set of active touches.
865 /// ## `sequence`
866 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was updated
867 #[doc(alias = "update")]
868 fn connect_update<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
869 &self,
870 f: F,
871 ) -> SignalHandlerId {
872 unsafe extern "C" fn update_trampoline<
873 P: IsA<Gesture>,
874 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
875 >(
876 this: *mut ffi::GtkGesture,
877 sequence: *mut gdk::ffi::GdkEventSequence,
878 f: glib::ffi::gpointer,
879 ) {
880 let f: &F = &*(f as *const F);
881 f(
882 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
883 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
884 .as_ref()
885 .as_ref(),
886 )
887 }
888 unsafe {
889 let f: Box_<F> = Box_::new(f);
890 connect_raw(
891 self.as_ptr() as *mut _,
892 c"update".as_ptr() as *const _,
893 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
894 update_trampoline::<Self, F> as *const (),
895 )),
896 Box_::into_raw(f),
897 )
898 }
899 }
900}
901
902impl<O: IsA<Gesture>> GestureExt for O {}