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::{EventController, EventSequenceState, ffi};
7use glib::{
8 object::ObjectType as _,
9 prelude::*,
10 signal::{SignalHandlerId, connect_raw},
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`], [`EventControllerExtManual`][trait@crate::prelude::EventControllerExtManual]
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 { Some(rect) } else { None }
254 }
255 }
256
257 /// If there are touch sequences being currently handled by @self,
258 /// returns [`true`] and fills in @x and @y with the center of the bounding
259 /// box containing all active touches.
260 ///
261 /// Otherwise, [`false`] will be returned.
262 ///
263 /// # Returns
264 ///
265 /// [`false`] if no active touches are present, [`true`] otherwise
266 ///
267 /// ## `x`
268 /// X coordinate for the bounding box center
269 ///
270 /// ## `y`
271 /// Y coordinate for the bounding box center
272 #[doc(alias = "gtk_gesture_get_bounding_box_center")]
273 #[doc(alias = "get_bounding_box_center")]
274 fn bounding_box_center(&self) -> Option<(f64, f64)> {
275 unsafe {
276 let mut x = std::mem::MaybeUninit::uninit();
277 let mut y = std::mem::MaybeUninit::uninit();
278 let ret = from_glib(ffi::gtk_gesture_get_bounding_box_center(
279 self.as_ref().to_glib_none().0,
280 x.as_mut_ptr(),
281 y.as_mut_ptr(),
282 ));
283 if ret {
284 Some((x.assume_init(), y.assume_init()))
285 } else {
286 None
287 }
288 }
289 }
290
291 /// Returns the logical [`gdk::Device`][crate::gdk::Device] that is currently operating
292 /// on @self.
293 ///
294 /// This returns [`None`] if the gesture is not being interacted.
295 ///
296 /// # Returns
297 ///
298 /// a [`gdk::Device`][crate::gdk::Device]
299 #[doc(alias = "gtk_gesture_get_device")]
300 #[doc(alias = "get_device")]
301 fn device(&self) -> Option<gdk::Device> {
302 unsafe { from_glib_none(ffi::gtk_gesture_get_device(self.as_ref().to_glib_none().0)) }
303 }
304
305 /// Returns all gestures in the group of @self
306 ///
307 /// # Returns
308 ///
309 /// The list
310 /// of [`Gesture`][crate::Gesture]s, free with g_list_free()
311 #[doc(alias = "gtk_gesture_get_group")]
312 #[doc(alias = "get_group")]
313 fn group(&self) -> Vec<Gesture> {
314 unsafe {
315 FromGlibPtrContainer::from_glib_container(ffi::gtk_gesture_get_group(
316 self.as_ref().to_glib_none().0,
317 ))
318 }
319 }
320
321 /// Returns the last event that was processed for @sequence.
322 ///
323 /// Note that the returned pointer is only valid as long as the
324 /// @sequence is still interpreted by the @self. If in doubt,
325 /// you should make a copy of the event.
326 /// ## `sequence`
327 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
328 ///
329 /// # Returns
330 ///
331 /// The last event from @sequence
332 #[doc(alias = "gtk_gesture_get_last_event")]
333 #[doc(alias = "get_last_event")]
334 fn last_event(&self, sequence: Option<&gdk::EventSequence>) -> Option<gdk::Event> {
335 unsafe {
336 from_glib_none(ffi::gtk_gesture_get_last_event(
337 self.as_ref().to_glib_none().0,
338 mut_override(sequence.to_glib_none().0),
339 ))
340 }
341 }
342
343 /// Returns the [`gdk::EventSequence`][crate::gdk::EventSequence] that was last updated on @self.
344 ///
345 /// # Returns
346 ///
347 /// The last updated sequence
348 #[doc(alias = "gtk_gesture_get_last_updated_sequence")]
349 #[doc(alias = "get_last_updated_sequence")]
350 fn last_updated_sequence(&self) -> Option<gdk::EventSequence> {
351 unsafe {
352 from_glib_none(ffi::gtk_gesture_get_last_updated_sequence(
353 self.as_ref().to_glib_none().0,
354 ))
355 }
356 }
357
358 /// If @sequence is currently being interpreted by @self,
359 /// returns [`true`] and fills in @x and @y with the last coordinates
360 /// stored for that event sequence.
361 ///
362 /// The coordinates are always relative to the widget allocation.
363 /// ## `sequence`
364 /// a [`gdk::EventSequence`][crate::gdk::EventSequence], or [`None`] for pointer events
365 ///
366 /// # Returns
367 ///
368 /// [`true`] if @sequence is currently interpreted
369 ///
370 /// ## `x`
371 /// return location for X axis of the sequence coordinates
372 ///
373 /// ## `y`
374 /// return location for Y axis of the sequence coordinates
375 #[doc(alias = "gtk_gesture_get_point")]
376 #[doc(alias = "get_point")]
377 fn point(&self, sequence: Option<&gdk::EventSequence>) -> Option<(f64, f64)> {
378 unsafe {
379 let mut x = std::mem::MaybeUninit::uninit();
380 let mut y = std::mem::MaybeUninit::uninit();
381 let ret = from_glib(ffi::gtk_gesture_get_point(
382 self.as_ref().to_glib_none().0,
383 mut_override(sequence.to_glib_none().0),
384 x.as_mut_ptr(),
385 y.as_mut_ptr(),
386 ));
387 if ret {
388 Some((x.assume_init(), y.assume_init()))
389 } else {
390 None
391 }
392 }
393 }
394
395 /// Returns the @sequence state, as seen by @self.
396 /// ## `sequence`
397 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
398 ///
399 /// # Returns
400 ///
401 /// The sequence state in @self
402 #[doc(alias = "gtk_gesture_get_sequence_state")]
403 #[doc(alias = "get_sequence_state")]
404 fn sequence_state(&self, sequence: &gdk::EventSequence) -> EventSequenceState {
405 unsafe {
406 from_glib(ffi::gtk_gesture_get_sequence_state(
407 self.as_ref().to_glib_none().0,
408 mut_override(sequence.to_glib_none().0),
409 ))
410 }
411 }
412
413 /// Returns the list of `GdkEventSequences` currently being interpreted
414 /// by @self.
415 ///
416 /// # Returns
417 ///
418 /// A list
419 /// of [`gdk::EventSequence`][crate::gdk::EventSequence], the list elements are owned by GTK and must
420 /// not be freed or modified, the list itself must be deleted
421 /// through g_list_free()
422 #[doc(alias = "gtk_gesture_get_sequences")]
423 #[doc(alias = "get_sequences")]
424 fn sequences(&self) -> Vec<gdk::EventSequence> {
425 unsafe {
426 FromGlibPtrContainer::from_glib_container(ffi::gtk_gesture_get_sequences(
427 self.as_ref().to_glib_none().0,
428 ))
429 }
430 }
431
432 /// Adds @gesture to the same group than @self.
433 ///
434 /// Gestures are by default isolated in their own groups.
435 ///
436 /// Both gestures must have been added to the same widget before
437 /// they can be grouped.
438 ///
439 /// When gestures are grouped, the state of `GdkEventSequences`
440 /// is kept in sync for all of those, so calling
441 /// [`set_sequence_state()`][Self::set_sequence_state()], on one will transfer
442 /// the same value to the others.
443 ///
444 /// Groups also perform an "implicit grabbing" of sequences, if a
445 /// [`gdk::EventSequence`][crate::gdk::EventSequence] state is set to [`EventSequenceState::Claimed`][crate::EventSequenceState::Claimed]
446 /// on one group, every other gesture group attached to the same
447 /// [`Widget`][crate::Widget] will switch the state for that sequence to
448 /// [`EventSequenceState::Denied`][crate::EventSequenceState::Denied].
449 /// ## `gesture`
450 /// a [`Gesture`][crate::Gesture]
451 #[doc(alias = "gtk_gesture_group")]
452 #[doc(alias = "group")]
453 fn group_with(&self, gesture: &impl IsA<Gesture>) {
454 unsafe {
455 ffi::gtk_gesture_group(
456 self.as_ref().to_glib_none().0,
457 gesture.as_ref().to_glib_none().0,
458 );
459 }
460 }
461
462 /// Returns [`true`] if @self is currently handling events
463 /// corresponding to @sequence.
464 /// ## `sequence`
465 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
466 ///
467 /// # Returns
468 ///
469 /// [`true`] if @self is handling @sequence, [`false`] otherwise
470 #[doc(alias = "gtk_gesture_handles_sequence")]
471 fn handles_sequence(&self, sequence: Option<&gdk::EventSequence>) -> bool {
472 unsafe {
473 from_glib(ffi::gtk_gesture_handles_sequence(
474 self.as_ref().to_glib_none().0,
475 mut_override(sequence.to_glib_none().0),
476 ))
477 }
478 }
479
480 /// Returns [`true`] if the gesture is currently active.
481 ///
482 /// A gesture is active while there are touch sequences
483 /// interacting with it.
484 ///
485 /// # Returns
486 ///
487 /// [`true`] if gesture is active
488 #[doc(alias = "gtk_gesture_is_active")]
489 fn is_active(&self) -> bool {
490 unsafe { from_glib(ffi::gtk_gesture_is_active(self.as_ref().to_glib_none().0)) }
491 }
492
493 /// Returns [`true`] if both gestures pertain to the same group.
494 /// ## `other`
495 /// another [`Gesture`][crate::Gesture]
496 ///
497 /// # Returns
498 ///
499 /// whether the gestures are grouped
500 #[doc(alias = "gtk_gesture_is_grouped_with")]
501 fn is_grouped_with(&self, other: &impl IsA<Gesture>) -> bool {
502 unsafe {
503 from_glib(ffi::gtk_gesture_is_grouped_with(
504 self.as_ref().to_glib_none().0,
505 other.as_ref().to_glib_none().0,
506 ))
507 }
508 }
509
510 /// Returns [`true`] if the gesture is currently recognized.
511 ///
512 /// A gesture is recognized if there are as many interacting
513 /// touch sequences as required by @self.
514 ///
515 /// # Returns
516 ///
517 /// [`true`] if gesture is recognized
518 #[doc(alias = "gtk_gesture_is_recognized")]
519 fn is_recognized(&self) -> bool {
520 unsafe {
521 from_glib(ffi::gtk_gesture_is_recognized(
522 self.as_ref().to_glib_none().0,
523 ))
524 }
525 }
526
527 /// Sets the state of @sequence in @self.
528 ///
529 /// Sequences start in state [`EventSequenceState::None`][crate::EventSequenceState::None], and whenever
530 /// they change state, they can never go back to that state. Likewise,
531 /// sequences in state [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] cannot turn back to
532 /// a not denied state. With these rules, the lifetime of an event
533 /// sequence is constrained to the next four:
534 ///
535 /// * None
536 /// * None → Denied
537 /// * None → Claimed
538 /// * None → Claimed → Denied
539 ///
540 /// Note: Due to event handling ordering, it may be unsafe to set the
541 /// state on another gesture within a [`begin`][struct@crate::Gesture#begin] signal
542 /// handler, as the callback might be executed before the other gesture
543 /// knows about the sequence. A safe way to perform this could be:
544 ///
545 /// **⚠️ The following code is in c ⚠️**
546 ///
547 /// ```c
548 /// static void
549 /// first_gesture_begin_cb (GtkGesture *first_gesture,
550 /// GdkEventSequence *sequence,
551 /// gpointer user_data)
552 /// {
553 /// gtk_gesture_set_sequence_state (first_gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
554 /// gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
555 /// }
556 ///
557 /// static void
558 /// second_gesture_begin_cb (GtkGesture *second_gesture,
559 /// GdkEventSequence *sequence,
560 /// gpointer user_data)
561 /// {
562 /// if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED)
563 /// gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
564 /// }
565 /// ```
566 ///
567 /// If both gestures are in the same group, just set the state on
568 /// the gesture emitting the event, the sequence will be already
569 /// be initialized to the group's global state when the second
570 /// gesture processes the event.
571 ///
572 /// # Deprecated since 4.10
573 ///
574 /// Use [`set_state()`][Self::set_state()]
575 /// ## `sequence`
576 /// a [`gdk::EventSequence`][crate::gdk::EventSequence]
577 /// ## `state`
578 /// the sequence state
579 ///
580 /// # Returns
581 ///
582 /// [`true`] if @sequence is handled by @self,
583 /// and the state is changed successfully
584 #[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
585 #[allow(deprecated)]
586 #[doc(alias = "gtk_gesture_set_sequence_state")]
587 fn set_sequence_state(&self, sequence: &gdk::EventSequence, state: EventSequenceState) -> bool {
588 unsafe {
589 from_glib(ffi::gtk_gesture_set_sequence_state(
590 self.as_ref().to_glib_none().0,
591 mut_override(sequence.to_glib_none().0),
592 state.into_glib(),
593 ))
594 }
595 }
596
597 /// Sets the state of all sequences that @self is currently
598 /// interacting with.
599 ///
600 /// Sequences start in state [`EventSequenceState::None`][crate::EventSequenceState::None], and whenever
601 /// they change state, they can never go back to that state. Likewise,
602 /// sequences in state [`EventSequenceState::Denied`][crate::EventSequenceState::Denied] cannot turn back to
603 /// a not denied state. With these rules, the lifetime of an event
604 /// sequence is constrained to the next four:
605 ///
606 /// * None
607 /// * None → Denied
608 /// * None → Claimed
609 /// * None → Claimed → Denied
610 ///
611 /// Note: Due to event handling ordering, it may be unsafe to set the
612 /// state on another gesture within a [`begin`][struct@crate::Gesture#begin] signal
613 /// handler, as the callback might be executed before the other gesture
614 /// knows about the sequence. A safe way to perform this could be:
615 ///
616 /// **⚠️ The following code is in c ⚠️**
617 ///
618 /// ```c
619 /// static void
620 /// first_gesture_begin_cb (GtkGesture *first_gesture,
621 /// GdkEventSequence *sequence,
622 /// gpointer user_data)
623 /// {
624 /// gtk_gesture_set_state (first_gesture, GTK_EVENT_SEQUENCE_CLAIMED);
625 /// gtk_gesture_set_state (second_gesture, GTK_EVENT_SEQUENCE_DENIED);
626 /// }
627 ///
628 /// static void
629 /// second_gesture_begin_cb (GtkGesture *second_gesture,
630 /// GdkEventSequence *sequence,
631 /// gpointer user_data)
632 /// {
633 /// if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED)
634 /// gtk_gesture_set_state (second_gesture, GTK_EVENT_SEQUENCE_DENIED);
635 /// }
636 /// ```
637 ///
638 /// If both gestures are in the same group, just set the state on
639 /// the gesture emitting the event, the sequence will be already
640 /// be initialized to the group's global state when the second
641 /// gesture processes the event.
642 /// ## `state`
643 /// the sequence state
644 ///
645 /// # Returns
646 ///
647 /// [`true`] if the state of at least one sequence
648 /// was changed successfully
649 #[doc(alias = "gtk_gesture_set_state")]
650 fn set_state(&self, state: EventSequenceState) -> bool {
651 unsafe {
652 from_glib(ffi::gtk_gesture_set_state(
653 self.as_ref().to_glib_none().0,
654 state.into_glib(),
655 ))
656 }
657 }
658
659 /// Separates @self into an isolated group.
660 #[doc(alias = "gtk_gesture_ungroup")]
661 fn ungroup(&self) {
662 unsafe {
663 ffi::gtk_gesture_ungroup(self.as_ref().to_glib_none().0);
664 }
665 }
666
667 /// The number of touch points that trigger
668 /// recognition on this gesture.
669 #[doc(alias = "n-points")]
670 fn n_points(&self) -> u32 {
671 ObjectExt::property(self.as_ref(), "n-points")
672 }
673
674 /// Emitted when the gesture is recognized.
675 ///
676 /// This means the number of touch sequences matches
677 /// [`n-points`][struct@crate::Gesture#n-points].
678 ///
679 /// Note: These conditions may also happen when an extra touch
680 /// (eg. a third touch on a 2-touches gesture) is lifted, in that
681 /// situation @sequence won't pertain to the current set of active
682 /// touches, so don't rely on this being true.
683 /// ## `sequence`
684 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that made the gesture
685 /// to be recognized
686 #[doc(alias = "begin")]
687 fn connect_begin<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
688 &self,
689 f: F,
690 ) -> SignalHandlerId {
691 unsafe extern "C" fn begin_trampoline<
692 P: IsA<Gesture>,
693 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
694 >(
695 this: *mut ffi::GtkGesture,
696 sequence: *mut gdk::ffi::GdkEventSequence,
697 f: glib::ffi::gpointer,
698 ) {
699 unsafe {
700 let f: &F = &*(f as *const F);
701 f(
702 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
703 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
704 .as_ref()
705 .as_ref(),
706 )
707 }
708 }
709 unsafe {
710 let f: Box_<F> = Box_::new(f);
711 connect_raw(
712 self.as_ptr() as *mut _,
713 c"begin".as_ptr() as *const _,
714 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
715 begin_trampoline::<Self, F> as *const (),
716 )),
717 Box_::into_raw(f),
718 )
719 }
720 }
721
722 /// Emitted whenever a sequence is cancelled.
723 ///
724 /// This usually happens on active touches when
725 /// [`EventControllerExt::reset()`][crate::prelude::EventControllerExt::reset()] is called on @gesture
726 /// (manually, due to grabs...), or the individual @sequence
727 /// was claimed by parent widgets' controllers (see
728 /// [`set_sequence_state()`][Self::set_sequence_state()]).
729 ///
730 /// @gesture must forget everything about @sequence as in
731 /// response to this signal.
732 /// ## `sequence`
733 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was cancelled
734 #[doc(alias = "cancel")]
735 fn connect_cancel<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
736 &self,
737 f: F,
738 ) -> SignalHandlerId {
739 unsafe extern "C" fn cancel_trampoline<
740 P: IsA<Gesture>,
741 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
742 >(
743 this: *mut ffi::GtkGesture,
744 sequence: *mut gdk::ffi::GdkEventSequence,
745 f: glib::ffi::gpointer,
746 ) {
747 unsafe {
748 let f: &F = &*(f as *const F);
749 f(
750 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
751 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
752 .as_ref()
753 .as_ref(),
754 )
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 unsafe {
796 let f: &F = &*(f as *const F);
797 f(
798 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
799 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
800 .as_ref()
801 .as_ref(),
802 )
803 }
804 }
805 unsafe {
806 let f: Box_<F> = Box_::new(f);
807 connect_raw(
808 self.as_ptr() as *mut _,
809 c"end".as_ptr() as *const _,
810 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
811 end_trampoline::<Self, F> as *const (),
812 )),
813 Box_::into_raw(f),
814 )
815 }
816 }
817
818 /// Emitted whenever a sequence state changes.
819 ///
820 /// See [`set_sequence_state()`][Self::set_sequence_state()] to know
821 /// more about the expectable sequence lifetimes.
822 /// ## `sequence`
823 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was cancelled
824 /// ## `state`
825 /// the new sequence state
826 #[doc(alias = "sequence-state-changed")]
827 fn connect_sequence_state_changed<
828 F: Fn(&Self, Option<&gdk::EventSequence>, EventSequenceState) + 'static,
829 >(
830 &self,
831 f: F,
832 ) -> SignalHandlerId {
833 unsafe extern "C" fn sequence_state_changed_trampoline<
834 P: IsA<Gesture>,
835 F: Fn(&P, Option<&gdk::EventSequence>, EventSequenceState) + 'static,
836 >(
837 this: *mut ffi::GtkGesture,
838 sequence: *mut gdk::ffi::GdkEventSequence,
839 state: ffi::GtkEventSequenceState,
840 f: glib::ffi::gpointer,
841 ) {
842 unsafe {
843 let f: &F = &*(f as *const F);
844 f(
845 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
846 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
847 .as_ref()
848 .as_ref(),
849 from_glib(state),
850 )
851 }
852 }
853 unsafe {
854 let f: Box_<F> = Box_::new(f);
855 connect_raw(
856 self.as_ptr() as *mut _,
857 c"sequence-state-changed".as_ptr() as *const _,
858 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
859 sequence_state_changed_trampoline::<Self, F> as *const (),
860 )),
861 Box_::into_raw(f),
862 )
863 }
864 }
865
866 /// Emitted whenever an event is handled while the gesture is recognized.
867 ///
868 /// @sequence is guaranteed to pertain to the set of active touches.
869 /// ## `sequence`
870 /// the [`gdk::EventSequence`][crate::gdk::EventSequence] that was updated
871 #[doc(alias = "update")]
872 fn connect_update<F: Fn(&Self, Option<&gdk::EventSequence>) + 'static>(
873 &self,
874 f: F,
875 ) -> SignalHandlerId {
876 unsafe extern "C" fn update_trampoline<
877 P: IsA<Gesture>,
878 F: Fn(&P, Option<&gdk::EventSequence>) + 'static,
879 >(
880 this: *mut ffi::GtkGesture,
881 sequence: *mut gdk::ffi::GdkEventSequence,
882 f: glib::ffi::gpointer,
883 ) {
884 unsafe {
885 let f: &F = &*(f as *const F);
886 f(
887 Gesture::from_glib_borrow(this).unsafe_cast_ref(),
888 Option::<gdk::EventSequence>::from_glib_borrow(sequence)
889 .as_ref()
890 .as_ref(),
891 )
892 }
893 }
894 unsafe {
895 let f: Box_<F> = Box_::new(f);
896 connect_raw(
897 self.as_ptr() as *mut _,
898 c"update".as_ptr() as *const _,
899 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
900 update_trampoline::<Self, F> as *const (),
901 )),
902 Box_::into_raw(f),
903 )
904 }
905 }
906}
907
908impl<O: IsA<Gesture>> GestureExt for O {}