1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.Gesture;
26 
27 private import gdk.Device;
28 private import gdk.Event;
29 private import gdk.Window;
30 private import glib.ListG;
31 private import gobject.ObjectG;
32 private import gobject.Signals;
33 private import gtk.EventController;
34 private import gtk.c.functions;
35 public  import gtk.c.types;
36 public  import gtkc.gtktypes;
37 private import std.algorithm;
38 
39 
40 /**
41  * #GtkGesture is the base object for gesture recognition, although this
42  * object is quite generalized to serve as a base for multi-touch gestures,
43  * it is suitable to implement single-touch and pointer-based gestures (using
44  * the special %NULL #GdkEventSequence value for these).
45  * 
46  * The number of touches that a #GtkGesture need to be recognized is controlled
47  * by the #GtkGesture:n-points property, if a gesture is keeping track of less
48  * or more than that number of sequences, it won't check wether the gesture
49  * is recognized.
50  * 
51  * As soon as the gesture has the expected number of touches, the gesture will
52  * run the #GtkGesture::check signal regularly on input events until the gesture
53  * is recognized, the criteria to consider a gesture as "recognized" is left to
54  * #GtkGesture subclasses.
55  * 
56  * A recognized gesture will then emit the following signals:
57  * - #GtkGesture::begin when the gesture is recognized.
58  * - A number of #GtkGesture::update, whenever an input event is processed.
59  * - #GtkGesture::end when the gesture is no longer recognized.
60  * 
61  * ## Event propagation
62  * 
63  * In order to receive events, a gesture needs to either set a propagation phase
64  * through gtk_event_controller_set_propagation_phase(), or feed those manually
65  * through gtk_event_controller_handle_event().
66  * 
67  * In the capture phase, events are propagated from the toplevel down to the
68  * target widget, and gestures that are attached to containers above the widget
69  * get a chance to interact with the event before it reaches the target.
70  * 
71  * After the capture phase, GTK+ emits the traditional #GtkWidget::button-press-event,
72  * #GtkWidget::button-release-event, #GtkWidget::touch-event, etc signals. Gestures
73  * with the %GTK_PHASE_TARGET phase are fed events from the default #GtkWidget::event
74  * handlers.
75  * 
76  * In the bubble phase, events are propagated up from the target widget to the
77  * toplevel, and gestures that are attached to containers above the widget get
78  * a chance to interact with events that have not been handled yet.
79  * 
80  * ## States of a sequence # {#touch-sequence-states}
81  * 
82  * Whenever input interaction happens, a single event may trigger a cascade of
83  * #GtkGestures, both across the parents of the widget receiving the event and
84  * in parallel within an individual widget. It is a responsibility of the
85  * widgets using those gestures to set the state of touch sequences accordingly
86  * in order to enable cooperation of gestures around the #GdkEventSequences
87  * triggering those.
88  * 
89  * Within a widget, gestures can be grouped through gtk_gesture_group(),
90  * grouped gestures synchronize the state of sequences, so calling
91  * gtk_gesture_set_sequence_state() on one will effectively propagate
92  * the state throughout the group.
93  * 
94  * By default, all sequences start out in the #GTK_EVENT_SEQUENCE_NONE state,
95  * sequences in this state trigger the gesture event handler, but event
96  * propagation will continue unstopped by gestures.
97  * 
98  * If a sequence enters into the #GTK_EVENT_SEQUENCE_DENIED state, the gesture
99  * group will effectively ignore the sequence, letting events go unstopped
100  * through the gesture, but the "slot" will still remain occupied while
101  * the touch is active.
102  * 
103  * If a sequence enters in the #GTK_EVENT_SEQUENCE_CLAIMED state, the gesture
104  * group will grab all interaction on the sequence, by:
105  * - Setting the same sequence to #GTK_EVENT_SEQUENCE_DENIED on every other gesture
106  * group within the widget, and every gesture on parent widgets in the propagation
107  * chain.
108  * - calling #GtkGesture::cancel on every gesture in widgets underneath in the
109  * propagation chain.
110  * - Stopping event propagation after the gesture group handles the event.
111  * 
112  * Note: if a sequence is set early to #GTK_EVENT_SEQUENCE_CLAIMED on
113  * #GDK_TOUCH_BEGIN/#GDK_BUTTON_PRESS (so those events are captured before
114  * reaching the event widget, this implies #GTK_PHASE_CAPTURE), one similar
115  * event will emulated if the sequence changes to #GTK_EVENT_SEQUENCE_DENIED.
116  * This way event coherence is preserved before event propagation is unstopped
117  * again.
118  * 
119  * Sequence states can't be changed freely, see gtk_gesture_set_sequence_state()
120  * to know about the possible lifetimes of a #GdkEventSequence.
121  * 
122  * ## Touchpad gestures
123  * 
124  * On the platforms that support it, #GtkGesture will handle transparently
125  * touchpad gesture events. The only precautions users of #GtkGesture should do
126  * to enable this support are:
127  * - Enabling %GDK_TOUCHPAD_GESTURE_MASK on their #GdkWindows
128  * - If the gesture has %GTK_PHASE_NONE, ensuring events of type
129  * %GDK_TOUCHPAD_SWIPE and %GDK_TOUCHPAD_PINCH are handled by the #GtkGesture
130  */
131 public class Gesture : EventController
132 {
133 	/** the main Gtk struct */
134 	protected GtkGesture* gtkGesture;
135 
136 	/** Get the main Gtk struct */
137 	public GtkGesture* getGestureStruct(bool transferOwnership = false)
138 	{
139 		if (transferOwnership)
140 			ownedRef = false;
141 		return gtkGesture;
142 	}
143 
144 	/** the main Gtk struct as a void* */
145 	protected override void* getStruct()
146 	{
147 		return cast(void*)gtkGesture;
148 	}
149 
150 	protected override void setStruct(GObject* obj)
151 	{
152 		gtkGesture = cast(GtkGesture*)obj;
153 		super.setStruct(obj);
154 	}
155 
156 	/**
157 	 * Sets our main struct and passes it to the parent class.
158 	 */
159 	public this (GtkGesture* gtkGesture, bool ownedRef = false)
160 	{
161 		this.gtkGesture = gtkGesture;
162 		super(cast(GtkEventController*)gtkGesture, ownedRef);
163 	}
164 
165 
166 	/** */
167 	public static GType getType()
168 	{
169 		return gtk_gesture_get_type();
170 	}
171 
172 	/**
173 	 * If there are touch sequences being currently handled by @gesture,
174 	 * this function returns %TRUE and fills in @rect with the bounding
175 	 * box containing all active touches. Otherwise, %FALSE will be
176 	 * returned.
177 	 *
178 	 * Note: This function will yield unexpected results on touchpad
179 	 * gestures. Since there is no correlation between physical and
180 	 * pixel distances, these will look as if constrained in an
181 	 * infinitely small area, @rect width and height will thus be 0
182 	 * regardless of the number of touchpoints.
183 	 *
184 	 * Params:
185 	 *     rect = bounding box containing all active touches.
186 	 *
187 	 * Returns: %TRUE if there are active touches, %FALSE otherwise
188 	 *
189 	 * Since: 3.14
190 	 */
191 	public bool getBoundingBox(out GdkRectangle rect)
192 	{
193 		return gtk_gesture_get_bounding_box(gtkGesture, &rect) != 0;
194 	}
195 
196 	/**
197 	 * If there are touch sequences being currently handled by @gesture,
198 	 * this function returns %TRUE and fills in @x and @y with the center
199 	 * of the bounding box containing all active touches. Otherwise, %FALSE
200 	 * will be returned.
201 	 *
202 	 * Params:
203 	 *     x = X coordinate for the bounding box center
204 	 *     y = Y coordinate for the bounding box center
205 	 *
206 	 * Returns: %FALSE if no active touches are present, %TRUE otherwise
207 	 *
208 	 * Since: 3.14
209 	 */
210 	public bool getBoundingBoxCenter(out double x, out double y)
211 	{
212 		return gtk_gesture_get_bounding_box_center(gtkGesture, &x, &y) != 0;
213 	}
214 
215 	/**
216 	 * Returns the master #GdkDevice that is currently operating
217 	 * on @gesture, or %NULL if the gesture is not being interacted.
218 	 *
219 	 * Returns: a #GdkDevice, or %NULL
220 	 *
221 	 * Since: 3.14
222 	 */
223 	public Device getDevice()
224 	{
225 		auto p = gtk_gesture_get_device(gtkGesture);
226 
227 		if(p is null)
228 		{
229 			return null;
230 		}
231 
232 		return ObjectG.getDObject!(Device)(cast(GdkDevice*) p);
233 	}
234 
235 	/**
236 	 * Returns all gestures in the group of @gesture
237 	 *
238 	 * Returns: The list
239 	 *     of #GtkGestures, free with g_list_free()
240 	 *
241 	 * Since: 3.14
242 	 */
243 	public ListG getGroup()
244 	{
245 		auto p = gtk_gesture_get_group(gtkGesture);
246 
247 		if(p is null)
248 		{
249 			return null;
250 		}
251 
252 		return new ListG(cast(GList*) p);
253 	}
254 
255 	/**
256 	 * Returns the last event that was processed for @sequence.
257 	 *
258 	 * Note that the returned pointer is only valid as long as the @sequence
259 	 * is still interpreted by the @gesture. If in doubt, you should make
260 	 * a copy of the event.
261 	 *
262 	 * Params:
263 	 *     sequence = a #GdkEventSequence
264 	 *
265 	 * Returns: The last event from @sequence
266 	 */
267 	public Event getLastEvent(GdkEventSequence* sequence)
268 	{
269 		auto p = gtk_gesture_get_last_event(gtkGesture, sequence);
270 
271 		if(p is null)
272 		{
273 			return null;
274 		}
275 
276 		return ObjectG.getDObject!(Event)(cast(GdkEvent*) p);
277 	}
278 
279 	/**
280 	 * Returns the #GdkEventSequence that was last updated on @gesture.
281 	 *
282 	 * Returns: The last updated sequence
283 	 *
284 	 * Since: 3.14
285 	 */
286 	public GdkEventSequence* getLastUpdatedSequence()
287 	{
288 		return gtk_gesture_get_last_updated_sequence(gtkGesture);
289 	}
290 
291 	/**
292 	 * If @sequence is currently being interpreted by @gesture, this
293 	 * function returns %TRUE and fills in @x and @y with the last coordinates
294 	 * stored for that event sequence. The coordinates are always relative to the
295 	 * widget allocation.
296 	 *
297 	 * Params:
298 	 *     sequence = a #GdkEventSequence, or %NULL for pointer events
299 	 *     x = return location for X axis of the sequence coordinates
300 	 *     y = return location for Y axis of the sequence coordinates
301 	 *
302 	 * Returns: %TRUE if @sequence is currently interpreted
303 	 *
304 	 * Since: 3.14
305 	 */
306 	public bool getPoint(GdkEventSequence* sequence, out double x, out double y)
307 	{
308 		return gtk_gesture_get_point(gtkGesture, sequence, &x, &y) != 0;
309 	}
310 
311 	/**
312 	 * Returns the @sequence state, as seen by @gesture.
313 	 *
314 	 * Params:
315 	 *     sequence = a #GdkEventSequence
316 	 *
317 	 * Returns: The sequence state in @gesture
318 	 *
319 	 * Since: 3.14
320 	 */
321 	public GtkEventSequenceState getSequenceState(GdkEventSequence* sequence)
322 	{
323 		return gtk_gesture_get_sequence_state(gtkGesture, sequence);
324 	}
325 
326 	/**
327 	 * Returns the list of #GdkEventSequences currently being interpreted
328 	 * by @gesture.
329 	 *
330 	 * Returns: A list
331 	 *     of #GdkEventSequences, the list elements are owned by GTK+
332 	 *     and must not be freed or modified, the list itself must be deleted
333 	 *     through g_list_free()
334 	 *
335 	 * Since: 3.14
336 	 */
337 	public ListG getSequences()
338 	{
339 		auto p = gtk_gesture_get_sequences(gtkGesture);
340 
341 		if(p is null)
342 		{
343 			return null;
344 		}
345 
346 		return new ListG(cast(GList*) p);
347 	}
348 
349 	/**
350 	 * Returns the user-defined window that receives the events
351 	 * handled by @gesture. See gtk_gesture_set_window() for more
352 	 * information.
353 	 *
354 	 * Returns: the user defined window, or %NULL if none
355 	 *
356 	 * Since: 3.14
357 	 */
358 	public Window getWindow()
359 	{
360 		auto p = gtk_gesture_get_window(gtkGesture);
361 
362 		if(p is null)
363 		{
364 			return null;
365 		}
366 
367 		return ObjectG.getDObject!(Window)(cast(GdkWindow*) p);
368 	}
369 
370 	/**
371 	 * Adds @gesture to the same group than @group_gesture. Gestures
372 	 * are by default isolated in their own groups.
373 	 *
374 	 * When gestures are grouped, the state of #GdkEventSequences
375 	 * is kept in sync for all of those, so calling gtk_gesture_set_sequence_state(),
376 	 * on one will transfer the same value to the others.
377 	 *
378 	 * Groups also perform an "implicit grabbing" of sequences, if a
379 	 * #GdkEventSequence state is set to #GTK_EVENT_SEQUENCE_CLAIMED on one group,
380 	 * every other gesture group attached to the same #GtkWidget will switch the
381 	 * state for that sequence to #GTK_EVENT_SEQUENCE_DENIED.
382 	 *
383 	 * Params:
384 	 *     gesture = a #GtkGesture
385 	 *
386 	 * Since: 3.14
387 	 */
388 	public void group(Gesture gesture)
389 	{
390 		gtk_gesture_group(gtkGesture, (gesture is null) ? null : gesture.getGestureStruct());
391 	}
392 
393 	/**
394 	 * Returns %TRUE if @gesture is currently handling events corresponding to
395 	 * @sequence.
396 	 *
397 	 * Params:
398 	 *     sequence = a #GdkEventSequence or %NULL
399 	 *
400 	 * Returns: %TRUE if @gesture is handling @sequence, %FALSE otherwise
401 	 *
402 	 * Since: 3.14
403 	 */
404 	public bool handlesSequence(GdkEventSequence* sequence)
405 	{
406 		return gtk_gesture_handles_sequence(gtkGesture, sequence) != 0;
407 	}
408 
409 	/**
410 	 * Returns %TRUE if the gesture is currently active.
411 	 * A gesture is active meanwhile there are touch sequences
412 	 * interacting with it.
413 	 *
414 	 * Returns: %TRUE if gesture is active
415 	 *
416 	 * Since: 3.14
417 	 */
418 	public bool isActive()
419 	{
420 		return gtk_gesture_is_active(gtkGesture) != 0;
421 	}
422 
423 	/**
424 	 * Returns %TRUE if both gestures pertain to the same group.
425 	 *
426 	 * Params:
427 	 *     other = another #GtkGesture
428 	 *
429 	 * Returns: whether the gestures are grouped
430 	 *
431 	 * Since: 3.14
432 	 */
433 	public bool isGroupedWith(Gesture other)
434 	{
435 		return gtk_gesture_is_grouped_with(gtkGesture, (other is null) ? null : other.getGestureStruct()) != 0;
436 	}
437 
438 	/**
439 	 * Returns %TRUE if the gesture is currently recognized.
440 	 * A gesture is recognized if there are as many interacting
441 	 * touch sequences as required by @gesture, and #GtkGesture::check
442 	 * returned %TRUE for the sequences being currently interpreted.
443 	 *
444 	 * Returns: %TRUE if gesture is recognized
445 	 *
446 	 * Since: 3.14
447 	 */
448 	public bool isRecognized()
449 	{
450 		return gtk_gesture_is_recognized(gtkGesture) != 0;
451 	}
452 
453 	/**
454 	 * Sets the state of @sequence in @gesture. Sequences start
455 	 * in state #GTK_EVENT_SEQUENCE_NONE, and whenever they change
456 	 * state, they can never go back to that state. Likewise,
457 	 * sequences in state #GTK_EVENT_SEQUENCE_DENIED cannot turn
458 	 * back to a not denied state. With these rules, the lifetime
459 	 * of an event sequence is constrained to the next four:
460 	 *
461 	 * * None
462 	 * * None → Denied
463 	 * * None → Claimed
464 	 * * None → Claimed → Denied
465 	 *
466 	 * Note: Due to event handling ordering, it may be unsafe to
467 	 * set the state on another gesture within a #GtkGesture::begin
468 	 * signal handler, as the callback might be executed before
469 	 * the other gesture knows about the sequence. A safe way to
470 	 * perform this could be:
471 	 *
472 	 * |[
473 	 * static void
474 	 * first_gesture_begin_cb (GtkGesture       *first_gesture,
475 	 * GdkEventSequence *sequence,
476 	 * gpointer          user_data)
477 	 * {
478 	 * gtk_gesture_set_sequence_state (first_gesture, sequence, GTK_EVENT_SEQUENCE_ACCEPTED);
479 	 * gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
480 	 * }
481 	 *
482 	 * static void
483 	 * second_gesture_begin_cb (GtkGesture       *second_gesture,
484 	 * GdkEventSequence *sequence,
485 	 * gpointer          user_data)
486 	 * {
487 	 * if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_ACCEPTED)
488 	 * gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
489 	 * }
490 	 * ]|
491 	 *
492 	 * If both gestures are in the same group, just set the state on
493 	 * the gesture emitting the event, the sequence will be already
494 	 * be initialized to the group's global state when the second
495 	 * gesture processes the event.
496 	 *
497 	 * Params:
498 	 *     sequence = a #GdkEventSequence
499 	 *     state = the sequence state
500 	 *
501 	 * Returns: %TRUE if @sequence is handled by @gesture,
502 	 *     and the state is changed successfully
503 	 *
504 	 * Since: 3.14
505 	 */
506 	public bool setSequenceState(GdkEventSequence* sequence, GtkEventSequenceState state)
507 	{
508 		return gtk_gesture_set_sequence_state(gtkGesture, sequence, state) != 0;
509 	}
510 
511 	/**
512 	 * Sets the state of all sequences that @gesture is currently
513 	 * interacting with. See gtk_gesture_set_sequence_state()
514 	 * for more details on sequence states.
515 	 *
516 	 * Params:
517 	 *     state = the sequence state
518 	 *
519 	 * Returns: %TRUE if the state of at least one sequence
520 	 *     was changed successfully
521 	 *
522 	 * Since: 3.14
523 	 */
524 	public bool setState(GtkEventSequenceState state)
525 	{
526 		return gtk_gesture_set_state(gtkGesture, state) != 0;
527 	}
528 
529 	/**
530 	 * Sets a specific window to receive events about, so @gesture
531 	 * will effectively handle only events targeting @window, or
532 	 * a child of it. @window must pertain to gtk_event_controller_get_widget().
533 	 *
534 	 * Params:
535 	 *     window = a #GdkWindow, or %NULL
536 	 *
537 	 * Since: 3.14
538 	 */
539 	public void setWindow(Window window)
540 	{
541 		gtk_gesture_set_window(gtkGesture, (window is null) ? null : window.getWindowStruct());
542 	}
543 
544 	/**
545 	 * Separates @gesture into an isolated group.
546 	 *
547 	 * Since: 3.14
548 	 */
549 	public void ungroup()
550 	{
551 		gtk_gesture_ungroup(gtkGesture);
552 	}
553 
554 	protected class OnBeginDelegateWrapper
555 	{
556 		void delegate(GdkEventSequence*, Gesture) dlg;
557 		gulong handlerId;
558 
559 		this(void delegate(GdkEventSequence*, Gesture) dlg)
560 		{
561 			this.dlg = dlg;
562 			onBeginListeners ~= this;
563 		}
564 
565 		void remove(OnBeginDelegateWrapper source)
566 		{
567 			foreach(index, wrapper; onBeginListeners)
568 			{
569 				if (wrapper.handlerId == source.handlerId)
570 				{
571 					onBeginListeners[index] = null;
572 					onBeginListeners = std.algorithm.remove(onBeginListeners, index);
573 					break;
574 				}
575 			}
576 		}
577 	}
578 	OnBeginDelegateWrapper[] onBeginListeners;
579 
580 	/**
581 	 * This signal is emitted when the gesture is recognized. This means the
582 	 * number of touch sequences matches #GtkGesture:n-points, and the #GtkGesture::check
583 	 * handler(s) returned #TRUE.
584 	 *
585 	 * Note: These conditions may also happen when an extra touch (eg. a third touch
586 	 * on a 2-touches gesture) is lifted, in that situation @sequence won't pertain
587 	 * to the current set of active touches, so don't rely on this being true.
588 	 *
589 	 * Params:
590 	 *     sequence = the #GdkEventSequence that made the gesture to be recognized
591 	 *
592 	 * Since: 3.14
593 	 */
594 	gulong addOnBegin(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
595 	{
596 		auto wrapper = new OnBeginDelegateWrapper(dlg);
597 		wrapper.handlerId = Signals.connectData(
598 			this,
599 			"begin",
600 			cast(GCallback)&callBackBegin,
601 			cast(void*)wrapper,
602 			cast(GClosureNotify)&callBackBeginDestroy,
603 			connectFlags);
604 		return wrapper.handlerId;
605 	}
606 
607 	extern(C) static void callBackBegin(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnBeginDelegateWrapper wrapper)
608 	{
609 		wrapper.dlg(sequence, wrapper.outer);
610 	}
611 
612 	extern(C) static void callBackBeginDestroy(OnBeginDelegateWrapper wrapper, GClosure* closure)
613 	{
614 		wrapper.remove(wrapper);
615 	}
616 
617 	protected class OnBeginGenericDelegateWrapper
618 	{
619 		void delegate(Event, Gesture) dlg;
620 		gulong handlerId;
621 
622 		this(void delegate(Event, Gesture) dlg)
623 		{
624 			this.dlg = dlg;
625 			onBeginGenericListeners ~= this;
626 		}
627 
628 		void remove(OnBeginGenericDelegateWrapper source)
629 		{
630 			foreach(index, wrapper; onBeginGenericListeners)
631 			{
632 				if (wrapper.handlerId == source.handlerId)
633 				{
634 					onBeginGenericListeners[index] = null;
635 					onBeginGenericListeners = std.algorithm.remove(onBeginGenericListeners, index);
636 					break;
637 				}
638 			}
639 		}
640 	}
641 	OnBeginGenericDelegateWrapper[] onBeginGenericListeners;
642 
643 	/**
644 	 * This signal is emitted when the gesture is recognized. This means the
645 	 * number of touch sequences matches #GtkGesture:n-points, and the #GtkGesture::check
646 	 * handler(s) returned #TRUE.
647 	 *
648 	 * Note: These conditions may also happen when an extra touch (eg. a third touch
649 	 * on a 2-touches gesture) is lifted, in that situation @sequence won't pertain
650 	 * to the current set of active touches, so don't rely on this being true.
651 	 *
652 	 * Params:
653 	 *     sequence = the #GdkEventSequence that made the gesture to be recognized
654 	 *
655 	 * Since: 3.14
656 	 */
657 	gulong addOnBegin(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
658 	{
659 		auto wrapper = new OnBeginGenericDelegateWrapper(dlg);
660 		wrapper.handlerId = Signals.connectData(
661 			this,
662 			"begin",
663 			cast(GCallback)&callBackBeginGeneric,
664 			cast(void*)wrapper,
665 			cast(GClosureNotify)&callBackBeginGenericDestroy,
666 			connectFlags);
667 		return wrapper.handlerId;
668 	}
669 
670 	extern(C) static void callBackBeginGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnBeginGenericDelegateWrapper wrapper)
671 	{
672 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
673 	}
674 
675 	extern(C) static void callBackBeginGenericDestroy(OnBeginGenericDelegateWrapper wrapper, GClosure* closure)
676 	{
677 		wrapper.remove(wrapper);
678 	}
679 
680 	protected class OnCancelDelegateWrapper
681 	{
682 		void delegate(GdkEventSequence*, Gesture) dlg;
683 		gulong handlerId;
684 
685 		this(void delegate(GdkEventSequence*, Gesture) dlg)
686 		{
687 			this.dlg = dlg;
688 			onCancelListeners ~= this;
689 		}
690 
691 		void remove(OnCancelDelegateWrapper source)
692 		{
693 			foreach(index, wrapper; onCancelListeners)
694 			{
695 				if (wrapper.handlerId == source.handlerId)
696 				{
697 					onCancelListeners[index] = null;
698 					onCancelListeners = std.algorithm.remove(onCancelListeners, index);
699 					break;
700 				}
701 			}
702 		}
703 	}
704 	OnCancelDelegateWrapper[] onCancelListeners;
705 
706 	/**
707 	 * This signal is emitted whenever a sequence is cancelled. This usually
708 	 * happens on active touches when gtk_event_controller_reset() is called
709 	 * on @gesture (manually, due to grabs...), or the individual @sequence
710 	 * was claimed by parent widgets' controllers (see gtk_gesture_set_sequence_state()).
711 	 *
712 	 * @gesture must forget everything about @sequence as a reaction to this signal.
713 	 *
714 	 * Params:
715 	 *     sequence = the #GdkEventSequence that was cancelled
716 	 *
717 	 * Since: 3.14
718 	 */
719 	gulong addOnCancel(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
720 	{
721 		auto wrapper = new OnCancelDelegateWrapper(dlg);
722 		wrapper.handlerId = Signals.connectData(
723 			this,
724 			"cancel",
725 			cast(GCallback)&callBackCancel,
726 			cast(void*)wrapper,
727 			cast(GClosureNotify)&callBackCancelDestroy,
728 			connectFlags);
729 		return wrapper.handlerId;
730 	}
731 
732 	extern(C) static void callBackCancel(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnCancelDelegateWrapper wrapper)
733 	{
734 		wrapper.dlg(sequence, wrapper.outer);
735 	}
736 
737 	extern(C) static void callBackCancelDestroy(OnCancelDelegateWrapper wrapper, GClosure* closure)
738 	{
739 		wrapper.remove(wrapper);
740 	}
741 
742 	protected class OnCancelGenericDelegateWrapper
743 	{
744 		void delegate(Event, Gesture) dlg;
745 		gulong handlerId;
746 
747 		this(void delegate(Event, Gesture) dlg)
748 		{
749 			this.dlg = dlg;
750 			onCancelGenericListeners ~= this;
751 		}
752 
753 		void remove(OnCancelGenericDelegateWrapper source)
754 		{
755 			foreach(index, wrapper; onCancelGenericListeners)
756 			{
757 				if (wrapper.handlerId == source.handlerId)
758 				{
759 					onCancelGenericListeners[index] = null;
760 					onCancelGenericListeners = std.algorithm.remove(onCancelGenericListeners, index);
761 					break;
762 				}
763 			}
764 		}
765 	}
766 	OnCancelGenericDelegateWrapper[] onCancelGenericListeners;
767 
768 	/**
769 	 * This signal is emitted whenever a sequence is cancelled. This usually
770 	 * happens on active touches when gtk_event_controller_reset() is called
771 	 * on @gesture (manually, due to grabs...), or the individual @sequence
772 	 * was claimed by parent widgets' controllers (see gtk_gesture_set_sequence_state()).
773 	 *
774 	 * @gesture must forget everything about @sequence as a reaction to this signal.
775 	 *
776 	 * Params:
777 	 *     sequence = the #GdkEventSequence that was cancelled
778 	 *
779 	 * Since: 3.14
780 	 */
781 	gulong addOnCancel(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
782 	{
783 		auto wrapper = new OnCancelGenericDelegateWrapper(dlg);
784 		wrapper.handlerId = Signals.connectData(
785 			this,
786 			"cancel",
787 			cast(GCallback)&callBackCancelGeneric,
788 			cast(void*)wrapper,
789 			cast(GClosureNotify)&callBackCancelGenericDestroy,
790 			connectFlags);
791 		return wrapper.handlerId;
792 	}
793 
794 	extern(C) static void callBackCancelGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnCancelGenericDelegateWrapper wrapper)
795 	{
796 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
797 	}
798 
799 	extern(C) static void callBackCancelGenericDestroy(OnCancelGenericDelegateWrapper wrapper, GClosure* closure)
800 	{
801 		wrapper.remove(wrapper);
802 	}
803 
804 	protected class OnEndDelegateWrapper
805 	{
806 		void delegate(GdkEventSequence*, Gesture) dlg;
807 		gulong handlerId;
808 
809 		this(void delegate(GdkEventSequence*, Gesture) dlg)
810 		{
811 			this.dlg = dlg;
812 			onEndListeners ~= this;
813 		}
814 
815 		void remove(OnEndDelegateWrapper source)
816 		{
817 			foreach(index, wrapper; onEndListeners)
818 			{
819 				if (wrapper.handlerId == source.handlerId)
820 				{
821 					onEndListeners[index] = null;
822 					onEndListeners = std.algorithm.remove(onEndListeners, index);
823 					break;
824 				}
825 			}
826 		}
827 	}
828 	OnEndDelegateWrapper[] onEndListeners;
829 
830 	/**
831 	 * This signal is emitted when @gesture either stopped recognizing the event
832 	 * sequences as something to be handled (the #GtkGesture::check handler returned
833 	 * %FALSE), or the number of touch sequences became higher or lower than
834 	 * #GtkGesture:n-points.
835 	 *
836 	 * Note: @sequence might not pertain to the group of sequences that were
837 	 * previously triggering recognition on @gesture (ie. a just pressed touch
838 	 * sequence that exceeds #GtkGesture:n-points). This situation may be detected
839 	 * by checking through gtk_gesture_handles_sequence().
840 	 *
841 	 * Params:
842 	 *     sequence = the #GdkEventSequence that made gesture recognition to finish
843 	 *
844 	 * Since: 3.14
845 	 */
846 	gulong addOnEnd(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
847 	{
848 		auto wrapper = new OnEndDelegateWrapper(dlg);
849 		wrapper.handlerId = Signals.connectData(
850 			this,
851 			"end",
852 			cast(GCallback)&callBackEnd,
853 			cast(void*)wrapper,
854 			cast(GClosureNotify)&callBackEndDestroy,
855 			connectFlags);
856 		return wrapper.handlerId;
857 	}
858 
859 	extern(C) static void callBackEnd(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnEndDelegateWrapper wrapper)
860 	{
861 		wrapper.dlg(sequence, wrapper.outer);
862 	}
863 
864 	extern(C) static void callBackEndDestroy(OnEndDelegateWrapper wrapper, GClosure* closure)
865 	{
866 		wrapper.remove(wrapper);
867 	}
868 
869 	protected class OnEndGenericDelegateWrapper
870 	{
871 		void delegate(Event, Gesture) dlg;
872 		gulong handlerId;
873 
874 		this(void delegate(Event, Gesture) dlg)
875 		{
876 			this.dlg = dlg;
877 			onEndGenericListeners ~= this;
878 		}
879 
880 		void remove(OnEndGenericDelegateWrapper source)
881 		{
882 			foreach(index, wrapper; onEndGenericListeners)
883 			{
884 				if (wrapper.handlerId == source.handlerId)
885 				{
886 					onEndGenericListeners[index] = null;
887 					onEndGenericListeners = std.algorithm.remove(onEndGenericListeners, index);
888 					break;
889 				}
890 			}
891 		}
892 	}
893 	OnEndGenericDelegateWrapper[] onEndGenericListeners;
894 
895 	/**
896 	 * This signal is emitted when @gesture either stopped recognizing the event
897 	 * sequences as something to be handled (the #GtkGesture::check handler returned
898 	 * %FALSE), or the number of touch sequences became higher or lower than
899 	 * #GtkGesture:n-points.
900 	 *
901 	 * Note: @sequence might not pertain to the group of sequences that were
902 	 * previously triggering recognition on @gesture (ie. a just pressed touch
903 	 * sequence that exceeds #GtkGesture:n-points). This situation may be detected
904 	 * by checking through gtk_gesture_handles_sequence().
905 	 *
906 	 * Params:
907 	 *     sequence = the #GdkEventSequence that made gesture recognition to finish
908 	 *
909 	 * Since: 3.14
910 	 */
911 	gulong addOnEnd(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
912 	{
913 		auto wrapper = new OnEndGenericDelegateWrapper(dlg);
914 		wrapper.handlerId = Signals.connectData(
915 			this,
916 			"end",
917 			cast(GCallback)&callBackEndGeneric,
918 			cast(void*)wrapper,
919 			cast(GClosureNotify)&callBackEndGenericDestroy,
920 			connectFlags);
921 		return wrapper.handlerId;
922 	}
923 
924 	extern(C) static void callBackEndGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnEndGenericDelegateWrapper wrapper)
925 	{
926 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
927 	}
928 
929 	extern(C) static void callBackEndGenericDestroy(OnEndGenericDelegateWrapper wrapper, GClosure* closure)
930 	{
931 		wrapper.remove(wrapper);
932 	}
933 
934 	protected class OnSequenceStateChangedDelegateWrapper
935 	{
936 		void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg;
937 		gulong handlerId;
938 
939 		this(void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg)
940 		{
941 			this.dlg = dlg;
942 			onSequenceStateChangedListeners ~= this;
943 		}
944 
945 		void remove(OnSequenceStateChangedDelegateWrapper source)
946 		{
947 			foreach(index, wrapper; onSequenceStateChangedListeners)
948 			{
949 				if (wrapper.handlerId == source.handlerId)
950 				{
951 					onSequenceStateChangedListeners[index] = null;
952 					onSequenceStateChangedListeners = std.algorithm.remove(onSequenceStateChangedListeners, index);
953 					break;
954 				}
955 			}
956 		}
957 	}
958 	OnSequenceStateChangedDelegateWrapper[] onSequenceStateChangedListeners;
959 
960 	/**
961 	 * This signal is emitted whenever a sequence state changes. See
962 	 * gtk_gesture_set_sequence_state() to know more about the expectable
963 	 * sequence lifetimes.
964 	 *
965 	 * Params:
966 	 *     sequence = the #GdkEventSequence that was cancelled
967 	 *     state = the new sequence state
968 	 *
969 	 * Since: 3.14
970 	 */
971 	gulong addOnSequenceStateChanged(void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
972 	{
973 		auto wrapper = new OnSequenceStateChangedDelegateWrapper(dlg);
974 		wrapper.handlerId = Signals.connectData(
975 			this,
976 			"sequence-state-changed",
977 			cast(GCallback)&callBackSequenceStateChanged,
978 			cast(void*)wrapper,
979 			cast(GClosureNotify)&callBackSequenceStateChangedDestroy,
980 			connectFlags);
981 		return wrapper.handlerId;
982 	}
983 
984 	extern(C) static void callBackSequenceStateChanged(GtkGesture* gestureStruct, GdkEventSequence* sequence, GtkEventSequenceState state, OnSequenceStateChangedDelegateWrapper wrapper)
985 	{
986 		wrapper.dlg(sequence, state, wrapper.outer);
987 	}
988 
989 	extern(C) static void callBackSequenceStateChangedDestroy(OnSequenceStateChangedDelegateWrapper wrapper, GClosure* closure)
990 	{
991 		wrapper.remove(wrapper);
992 	}
993 
994 	protected class OnSequenceStateChangedGenericDelegateWrapper
995 	{
996 		void delegate(Event, GtkEventSequenceState, Gesture) dlg;
997 		gulong handlerId;
998 
999 		this(void delegate(Event, GtkEventSequenceState, Gesture) dlg)
1000 		{
1001 			this.dlg = dlg;
1002 			onSequenceStateChangedGenericListeners ~= this;
1003 		}
1004 
1005 		void remove(OnSequenceStateChangedGenericDelegateWrapper source)
1006 		{
1007 			foreach(index, wrapper; onSequenceStateChangedGenericListeners)
1008 			{
1009 				if (wrapper.handlerId == source.handlerId)
1010 				{
1011 					onSequenceStateChangedGenericListeners[index] = null;
1012 					onSequenceStateChangedGenericListeners = std.algorithm.remove(onSequenceStateChangedGenericListeners, index);
1013 					break;
1014 				}
1015 			}
1016 		}
1017 	}
1018 	OnSequenceStateChangedGenericDelegateWrapper[] onSequenceStateChangedGenericListeners;
1019 
1020 	/**
1021 	 * This signal is emitted whenever a sequence state changes. See
1022 	 * gtk_gesture_set_sequence_state() to know more about the expectable
1023 	 * sequence lifetimes.
1024 	 *
1025 	 * Params:
1026 	 *     sequence = the #GdkEventSequence that was cancelled
1027 	 *     state = the new sequence state
1028 	 *
1029 	 * Since: 3.14
1030 	 */
1031 	gulong addOnSequenceStateChanged(void delegate(Event, GtkEventSequenceState, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1032 	{
1033 		auto wrapper = new OnSequenceStateChangedGenericDelegateWrapper(dlg);
1034 		wrapper.handlerId = Signals.connectData(
1035 			this,
1036 			"sequence-state-changed",
1037 			cast(GCallback)&callBackSequenceStateChangedGeneric,
1038 			cast(void*)wrapper,
1039 			cast(GClosureNotify)&callBackSequenceStateChangedGenericDestroy,
1040 			connectFlags);
1041 		return wrapper.handlerId;
1042 	}
1043 
1044 	extern(C) static void callBackSequenceStateChangedGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, GtkEventSequenceState state, OnSequenceStateChangedGenericDelegateWrapper wrapper)
1045 	{
1046 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), state, wrapper.outer);
1047 	}
1048 
1049 	extern(C) static void callBackSequenceStateChangedGenericDestroy(OnSequenceStateChangedGenericDelegateWrapper wrapper, GClosure* closure)
1050 	{
1051 		wrapper.remove(wrapper);
1052 	}
1053 
1054 	protected class OnUpdateDelegateWrapper
1055 	{
1056 		void delegate(GdkEventSequence*, Gesture) dlg;
1057 		gulong handlerId;
1058 
1059 		this(void delegate(GdkEventSequence*, Gesture) dlg)
1060 		{
1061 			this.dlg = dlg;
1062 			onUpdateListeners ~= this;
1063 		}
1064 
1065 		void remove(OnUpdateDelegateWrapper source)
1066 		{
1067 			foreach(index, wrapper; onUpdateListeners)
1068 			{
1069 				if (wrapper.handlerId == source.handlerId)
1070 				{
1071 					onUpdateListeners[index] = null;
1072 					onUpdateListeners = std.algorithm.remove(onUpdateListeners, index);
1073 					break;
1074 				}
1075 			}
1076 		}
1077 	}
1078 	OnUpdateDelegateWrapper[] onUpdateListeners;
1079 
1080 	/**
1081 	 * This signal is emitted whenever an event is handled while the gesture is
1082 	 * recognized. @sequence is guaranteed to pertain to the set of active touches.
1083 	 *
1084 	 * Params:
1085 	 *     sequence = the #GdkEventSequence that was updated
1086 	 *
1087 	 * Since: 3.14
1088 	 */
1089 	gulong addOnUpdate(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1090 	{
1091 		auto wrapper = new OnUpdateDelegateWrapper(dlg);
1092 		wrapper.handlerId = Signals.connectData(
1093 			this,
1094 			"update",
1095 			cast(GCallback)&callBackUpdate,
1096 			cast(void*)wrapper,
1097 			cast(GClosureNotify)&callBackUpdateDestroy,
1098 			connectFlags);
1099 		return wrapper.handlerId;
1100 	}
1101 
1102 	extern(C) static void callBackUpdate(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnUpdateDelegateWrapper wrapper)
1103 	{
1104 		wrapper.dlg(sequence, wrapper.outer);
1105 	}
1106 
1107 	extern(C) static void callBackUpdateDestroy(OnUpdateDelegateWrapper wrapper, GClosure* closure)
1108 	{
1109 		wrapper.remove(wrapper);
1110 	}
1111 
1112 	protected class OnUpdateGenericDelegateWrapper
1113 	{
1114 		void delegate(Event, Gesture) dlg;
1115 		gulong handlerId;
1116 
1117 		this(void delegate(Event, Gesture) dlg)
1118 		{
1119 			this.dlg = dlg;
1120 			onUpdateGenericListeners ~= this;
1121 		}
1122 
1123 		void remove(OnUpdateGenericDelegateWrapper source)
1124 		{
1125 			foreach(index, wrapper; onUpdateGenericListeners)
1126 			{
1127 				if (wrapper.handlerId == source.handlerId)
1128 				{
1129 					onUpdateGenericListeners[index] = null;
1130 					onUpdateGenericListeners = std.algorithm.remove(onUpdateGenericListeners, index);
1131 					break;
1132 				}
1133 			}
1134 		}
1135 	}
1136 	OnUpdateGenericDelegateWrapper[] onUpdateGenericListeners;
1137 
1138 	/**
1139 	 * This signal is emitted whenever an event is handled while the gesture is
1140 	 * recognized. @sequence is guaranteed to pertain to the set of active touches.
1141 	 *
1142 	 * Params:
1143 	 *     sequence = the #GdkEventSequence that was updated
1144 	 *
1145 	 * Since: 3.14
1146 	 */
1147 	gulong addOnUpdate(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1148 	{
1149 		auto wrapper = new OnUpdateGenericDelegateWrapper(dlg);
1150 		wrapper.handlerId = Signals.connectData(
1151 			this,
1152 			"update",
1153 			cast(GCallback)&callBackUpdateGeneric,
1154 			cast(void*)wrapper,
1155 			cast(GClosureNotify)&callBackUpdateGenericDestroy,
1156 			connectFlags);
1157 		return wrapper.handlerId;
1158 	}
1159 
1160 	extern(C) static void callBackUpdateGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnUpdateGenericDelegateWrapper wrapper)
1161 	{
1162 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
1163 	}
1164 
1165 	extern(C) static void callBackUpdateGenericDestroy(OnUpdateGenericDelegateWrapper wrapper, GClosure* closure)
1166 	{
1167 		wrapper.remove(wrapper);
1168 	}
1169 }