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 	/**
151 	 * Sets our main struct and passes it to the parent class.
152 	 */
153 	public this (GtkGesture* gtkGesture, bool ownedRef = false)
154 	{
155 		this.gtkGesture = gtkGesture;
156 		super(cast(GtkEventController*)gtkGesture, ownedRef);
157 	}
158 
159 
160 	/** */
161 	public static GType getType()
162 	{
163 		return gtk_gesture_get_type();
164 	}
165 
166 	/**
167 	 * If there are touch sequences being currently handled by @gesture,
168 	 * this function returns %TRUE and fills in @rect with the bounding
169 	 * box containing all active touches. Otherwise, %FALSE will be
170 	 * returned.
171 	 *
172 	 * Note: This function will yield unexpected results on touchpad
173 	 * gestures. Since there is no correlation between physical and
174 	 * pixel distances, these will look as if constrained in an
175 	 * infinitely small area, @rect width and height will thus be 0
176 	 * regardless of the number of touchpoints.
177 	 *
178 	 * Params:
179 	 *     rect = bounding box containing all active touches.
180 	 *
181 	 * Returns: %TRUE if there are active touches, %FALSE otherwise
182 	 *
183 	 * Since: 3.14
184 	 */
185 	public bool getBoundingBox(out GdkRectangle rect)
186 	{
187 		return gtk_gesture_get_bounding_box(gtkGesture, &rect) != 0;
188 	}
189 
190 	/**
191 	 * If there are touch sequences being currently handled by @gesture,
192 	 * this function returns %TRUE and fills in @x and @y with the center
193 	 * of the bounding box containing all active touches. Otherwise, %FALSE
194 	 * will be returned.
195 	 *
196 	 * Params:
197 	 *     x = X coordinate for the bounding box center
198 	 *     y = Y coordinate for the bounding box center
199 	 *
200 	 * Returns: %FALSE if no active touches are present, %TRUE otherwise
201 	 *
202 	 * Since: 3.14
203 	 */
204 	public bool getBoundingBoxCenter(out double x, out double y)
205 	{
206 		return gtk_gesture_get_bounding_box_center(gtkGesture, &x, &y) != 0;
207 	}
208 
209 	/**
210 	 * Returns the master #GdkDevice that is currently operating
211 	 * on @gesture, or %NULL if the gesture is not being interacted.
212 	 *
213 	 * Returns: a #GdkDevice, or %NULL
214 	 *
215 	 * Since: 3.14
216 	 */
217 	public Device getDevice()
218 	{
219 		auto p = gtk_gesture_get_device(gtkGesture);
220 
221 		if(p is null)
222 		{
223 			return null;
224 		}
225 
226 		return ObjectG.getDObject!(Device)(cast(GdkDevice*) p);
227 	}
228 
229 	/**
230 	 * Returns all gestures in the group of @gesture
231 	 *
232 	 * Returns: The list
233 	 *     of #GtkGestures, free with g_list_free()
234 	 *
235 	 * Since: 3.14
236 	 */
237 	public ListG getGroup()
238 	{
239 		auto p = gtk_gesture_get_group(gtkGesture);
240 
241 		if(p is null)
242 		{
243 			return null;
244 		}
245 
246 		return new ListG(cast(GList*) p);
247 	}
248 
249 	/**
250 	 * Returns the last event that was processed for @sequence.
251 	 *
252 	 * Note that the returned pointer is only valid as long as the @sequence
253 	 * is still interpreted by the @gesture. If in doubt, you should make
254 	 * a copy of the event.
255 	 *
256 	 * Params:
257 	 *     sequence = a #GdkEventSequence
258 	 *
259 	 * Returns: The last event from @sequence
260 	 */
261 	public Event getLastEvent(GdkEventSequence* sequence)
262 	{
263 		auto p = gtk_gesture_get_last_event(gtkGesture, sequence);
264 
265 		if(p is null)
266 		{
267 			return null;
268 		}
269 
270 		return ObjectG.getDObject!(Event)(cast(GdkEvent*) p);
271 	}
272 
273 	/**
274 	 * Returns the #GdkEventSequence that was last updated on @gesture.
275 	 *
276 	 * Returns: The last updated sequence
277 	 *
278 	 * Since: 3.14
279 	 */
280 	public GdkEventSequence* getLastUpdatedSequence()
281 	{
282 		return gtk_gesture_get_last_updated_sequence(gtkGesture);
283 	}
284 
285 	/**
286 	 * If @sequence is currently being interpreted by @gesture, this
287 	 * function returns %TRUE and fills in @x and @y with the last coordinates
288 	 * stored for that event sequence. The coordinates are always relative to the
289 	 * widget allocation.
290 	 *
291 	 * Params:
292 	 *     sequence = a #GdkEventSequence, or %NULL for pointer events
293 	 *     x = return location for X axis of the sequence coordinates
294 	 *     y = return location for Y axis of the sequence coordinates
295 	 *
296 	 * Returns: %TRUE if @sequence is currently interpreted
297 	 *
298 	 * Since: 3.14
299 	 */
300 	public bool getPoint(GdkEventSequence* sequence, out double x, out double y)
301 	{
302 		return gtk_gesture_get_point(gtkGesture, sequence, &x, &y) != 0;
303 	}
304 
305 	/**
306 	 * Returns the @sequence state, as seen by @gesture.
307 	 *
308 	 * Params:
309 	 *     sequence = a #GdkEventSequence
310 	 *
311 	 * Returns: The sequence state in @gesture
312 	 *
313 	 * Since: 3.14
314 	 */
315 	public GtkEventSequenceState getSequenceState(GdkEventSequence* sequence)
316 	{
317 		return gtk_gesture_get_sequence_state(gtkGesture, sequence);
318 	}
319 
320 	/**
321 	 * Returns the list of #GdkEventSequences currently being interpreted
322 	 * by @gesture.
323 	 *
324 	 * Returns: A list
325 	 *     of #GdkEventSequences, the list elements are owned by GTK+
326 	 *     and must not be freed or modified, the list itself must be deleted
327 	 *     through g_list_free()
328 	 *
329 	 * Since: 3.14
330 	 */
331 	public ListG getSequences()
332 	{
333 		auto p = gtk_gesture_get_sequences(gtkGesture);
334 
335 		if(p is null)
336 		{
337 			return null;
338 		}
339 
340 		return new ListG(cast(GList*) p);
341 	}
342 
343 	/**
344 	 * Returns the user-defined window that receives the events
345 	 * handled by @gesture. See gtk_gesture_set_window() for more
346 	 * information.
347 	 *
348 	 * Returns: the user defined window, or %NULL if none
349 	 *
350 	 * Since: 3.14
351 	 */
352 	public Window getWindow()
353 	{
354 		auto p = gtk_gesture_get_window(gtkGesture);
355 
356 		if(p is null)
357 		{
358 			return null;
359 		}
360 
361 		return ObjectG.getDObject!(Window)(cast(GdkWindow*) p);
362 	}
363 
364 	/**
365 	 * Adds @gesture to the same group than @group_gesture. Gestures
366 	 * are by default isolated in their own groups.
367 	 *
368 	 * When gestures are grouped, the state of #GdkEventSequences
369 	 * is kept in sync for all of those, so calling gtk_gesture_set_sequence_state(),
370 	 * on one will transfer the same value to the others.
371 	 *
372 	 * Groups also perform an "implicit grabbing" of sequences, if a
373 	 * #GdkEventSequence state is set to #GTK_EVENT_SEQUENCE_CLAIMED on one group,
374 	 * every other gesture group attached to the same #GtkWidget will switch the
375 	 * state for that sequence to #GTK_EVENT_SEQUENCE_DENIED.
376 	 *
377 	 * Params:
378 	 *     gesture = a #GtkGesture
379 	 *
380 	 * Since: 3.14
381 	 */
382 	public void group(Gesture gesture)
383 	{
384 		gtk_gesture_group(gtkGesture, (gesture is null) ? null : gesture.getGestureStruct());
385 	}
386 
387 	/**
388 	 * Returns %TRUE if @gesture is currently handling events corresponding to
389 	 * @sequence.
390 	 *
391 	 * Params:
392 	 *     sequence = a #GdkEventSequence or %NULL
393 	 *
394 	 * Returns: %TRUE if @gesture is handling @sequence, %FALSE otherwise
395 	 *
396 	 * Since: 3.14
397 	 */
398 	public bool handlesSequence(GdkEventSequence* sequence)
399 	{
400 		return gtk_gesture_handles_sequence(gtkGesture, sequence) != 0;
401 	}
402 
403 	/**
404 	 * Returns %TRUE if the gesture is currently active.
405 	 * A gesture is active meanwhile there are touch sequences
406 	 * interacting with it.
407 	 *
408 	 * Returns: %TRUE if gesture is active
409 	 *
410 	 * Since: 3.14
411 	 */
412 	public bool isActive()
413 	{
414 		return gtk_gesture_is_active(gtkGesture) != 0;
415 	}
416 
417 	/**
418 	 * Returns %TRUE if both gestures pertain to the same group.
419 	 *
420 	 * Params:
421 	 *     other = another #GtkGesture
422 	 *
423 	 * Returns: whether the gestures are grouped
424 	 *
425 	 * Since: 3.14
426 	 */
427 	public bool isGroupedWith(Gesture other)
428 	{
429 		return gtk_gesture_is_grouped_with(gtkGesture, (other is null) ? null : other.getGestureStruct()) != 0;
430 	}
431 
432 	/**
433 	 * Returns %TRUE if the gesture is currently recognized.
434 	 * A gesture is recognized if there are as many interacting
435 	 * touch sequences as required by @gesture, and #GtkGesture::check
436 	 * returned %TRUE for the sequences being currently interpreted.
437 	 *
438 	 * Returns: %TRUE if gesture is recognized
439 	 *
440 	 * Since: 3.14
441 	 */
442 	public bool isRecognized()
443 	{
444 		return gtk_gesture_is_recognized(gtkGesture) != 0;
445 	}
446 
447 	/**
448 	 * Sets the state of @sequence in @gesture. Sequences start
449 	 * in state #GTK_EVENT_SEQUENCE_NONE, and whenever they change
450 	 * state, they can never go back to that state. Likewise,
451 	 * sequences in state #GTK_EVENT_SEQUENCE_DENIED cannot turn
452 	 * back to a not denied state. With these rules, the lifetime
453 	 * of an event sequence is constrained to the next four:
454 	 *
455 	 * * None
456 	 * * None → Denied
457 	 * * None → Claimed
458 	 * * None → Claimed → Denied
459 	 *
460 	 * Note: Due to event handling ordering, it may be unsafe to
461 	 * set the state on another gesture within a #GtkGesture::begin
462 	 * signal handler, as the callback might be executed before
463 	 * the other gesture knows about the sequence. A safe way to
464 	 * perform this could be:
465 	 *
466 	 * |[
467 	 * static void
468 	 * first_gesture_begin_cb (GtkGesture       *first_gesture,
469 	 * GdkEventSequence *sequence,
470 	 * gpointer          user_data)
471 	 * {
472 	 * gtk_gesture_set_sequence_state (first_gesture, sequence, GTK_EVENT_SEQUENCE_ACCEPTED);
473 	 * gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
474 	 * }
475 	 *
476 	 * static void
477 	 * second_gesture_begin_cb (GtkGesture       *second_gesture,
478 	 * GdkEventSequence *sequence,
479 	 * gpointer          user_data)
480 	 * {
481 	 * if (gtk_gesture_get_sequence_state (first_gesture, sequence) == GTK_EVENT_SEQUENCE_ACCEPTED)
482 	 * gtk_gesture_set_sequence_state (second_gesture, sequence, GTK_EVENT_SEQUENCE_DENIED);
483 	 * }
484 	 * ]|
485 	 *
486 	 * If both gestures are in the same group, just set the state on
487 	 * the gesture emitting the event, the sequence will be already
488 	 * be initialized to the group's global state when the second
489 	 * gesture processes the event.
490 	 *
491 	 * Params:
492 	 *     sequence = a #GdkEventSequence
493 	 *     state = the sequence state
494 	 *
495 	 * Returns: %TRUE if @sequence is handled by @gesture,
496 	 *     and the state is changed successfully
497 	 *
498 	 * Since: 3.14
499 	 */
500 	public bool setSequenceState(GdkEventSequence* sequence, GtkEventSequenceState state)
501 	{
502 		return gtk_gesture_set_sequence_state(gtkGesture, sequence, state) != 0;
503 	}
504 
505 	/**
506 	 * Sets the state of all sequences that @gesture is currently
507 	 * interacting with. See gtk_gesture_set_sequence_state()
508 	 * for more details on sequence states.
509 	 *
510 	 * Params:
511 	 *     state = the sequence state
512 	 *
513 	 * Returns: %TRUE if the state of at least one sequence
514 	 *     was changed successfully
515 	 *
516 	 * Since: 3.14
517 	 */
518 	public bool setState(GtkEventSequenceState state)
519 	{
520 		return gtk_gesture_set_state(gtkGesture, state) != 0;
521 	}
522 
523 	/**
524 	 * Sets a specific window to receive events about, so @gesture
525 	 * will effectively handle only events targeting @window, or
526 	 * a child of it. @window must pertain to gtk_event_controller_get_widget().
527 	 *
528 	 * Params:
529 	 *     window = a #GdkWindow, or %NULL
530 	 *
531 	 * Since: 3.14
532 	 */
533 	public void setWindow(Window window)
534 	{
535 		gtk_gesture_set_window(gtkGesture, (window is null) ? null : window.getWindowStruct());
536 	}
537 
538 	/**
539 	 * Separates @gesture into an isolated group.
540 	 *
541 	 * Since: 3.14
542 	 */
543 	public void ungroup()
544 	{
545 		gtk_gesture_ungroup(gtkGesture);
546 	}
547 
548 	protected class OnBeginDelegateWrapper
549 	{
550 		void delegate(GdkEventSequence*, Gesture) dlg;
551 		gulong handlerId;
552 
553 		this(void delegate(GdkEventSequence*, Gesture) dlg)
554 		{
555 			this.dlg = dlg;
556 			onBeginListeners ~= this;
557 		}
558 
559 		void remove(OnBeginDelegateWrapper source)
560 		{
561 			foreach(index, wrapper; onBeginListeners)
562 			{
563 				if (wrapper.handlerId == source.handlerId)
564 				{
565 					onBeginListeners[index] = null;
566 					onBeginListeners = std.algorithm.remove(onBeginListeners, index);
567 					break;
568 				}
569 			}
570 		}
571 	}
572 	OnBeginDelegateWrapper[] onBeginListeners;
573 
574 	/**
575 	 * This signal is emitted when the gesture is recognized. This means the
576 	 * number of touch sequences matches #GtkGesture:n-points, and the #GtkGesture::check
577 	 * handler(s) returned #TRUE.
578 	 *
579 	 * Note: These conditions may also happen when an extra touch (eg. a third touch
580 	 * on a 2-touches gesture) is lifted, in that situation @sequence won't pertain
581 	 * to the current set of active touches, so don't rely on this being true.
582 	 *
583 	 * Params:
584 	 *     sequence = the #GdkEventSequence that made the gesture to be recognized
585 	 *
586 	 * Since: 3.14
587 	 */
588 	gulong addOnBegin(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
589 	{
590 		auto wrapper = new OnBeginDelegateWrapper(dlg);
591 		wrapper.handlerId = Signals.connectData(
592 			this,
593 			"begin",
594 			cast(GCallback)&callBackBegin,
595 			cast(void*)wrapper,
596 			cast(GClosureNotify)&callBackBeginDestroy,
597 			connectFlags);
598 		return wrapper.handlerId;
599 	}
600 
601 	extern(C) static void callBackBegin(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnBeginDelegateWrapper wrapper)
602 	{
603 		wrapper.dlg(sequence, wrapper.outer);
604 	}
605 
606 	extern(C) static void callBackBeginDestroy(OnBeginDelegateWrapper wrapper, GClosure* closure)
607 	{
608 		wrapper.remove(wrapper);
609 	}
610 
611 	protected class OnBeginGenericDelegateWrapper
612 	{
613 		void delegate(Event, Gesture) dlg;
614 		gulong handlerId;
615 
616 		this(void delegate(Event, Gesture) dlg)
617 		{
618 			this.dlg = dlg;
619 			onBeginGenericListeners ~= this;
620 		}
621 
622 		void remove(OnBeginGenericDelegateWrapper source)
623 		{
624 			foreach(index, wrapper; onBeginGenericListeners)
625 			{
626 				if (wrapper.handlerId == source.handlerId)
627 				{
628 					onBeginGenericListeners[index] = null;
629 					onBeginGenericListeners = std.algorithm.remove(onBeginGenericListeners, index);
630 					break;
631 				}
632 			}
633 		}
634 	}
635 	OnBeginGenericDelegateWrapper[] onBeginGenericListeners;
636 
637 	/**
638 	 * This signal is emitted when the gesture is recognized. This means the
639 	 * number of touch sequences matches #GtkGesture:n-points, and the #GtkGesture::check
640 	 * handler(s) returned #TRUE.
641 	 *
642 	 * Note: These conditions may also happen when an extra touch (eg. a third touch
643 	 * on a 2-touches gesture) is lifted, in that situation @sequence won't pertain
644 	 * to the current set of active touches, so don't rely on this being true.
645 	 *
646 	 * Params:
647 	 *     sequence = the #GdkEventSequence that made the gesture to be recognized
648 	 *
649 	 * Since: 3.14
650 	 */
651 	gulong addOnBegin(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
652 	{
653 		auto wrapper = new OnBeginGenericDelegateWrapper(dlg);
654 		wrapper.handlerId = Signals.connectData(
655 			this,
656 			"begin",
657 			cast(GCallback)&callBackBeginGeneric,
658 			cast(void*)wrapper,
659 			cast(GClosureNotify)&callBackBeginGenericDestroy,
660 			connectFlags);
661 		return wrapper.handlerId;
662 	}
663 
664 	extern(C) static void callBackBeginGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnBeginGenericDelegateWrapper wrapper)
665 	{
666 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
667 	}
668 
669 	extern(C) static void callBackBeginGenericDestroy(OnBeginGenericDelegateWrapper wrapper, GClosure* closure)
670 	{
671 		wrapper.remove(wrapper);
672 	}
673 
674 	protected class OnCancelDelegateWrapper
675 	{
676 		void delegate(GdkEventSequence*, Gesture) dlg;
677 		gulong handlerId;
678 
679 		this(void delegate(GdkEventSequence*, Gesture) dlg)
680 		{
681 			this.dlg = dlg;
682 			onCancelListeners ~= this;
683 		}
684 
685 		void remove(OnCancelDelegateWrapper source)
686 		{
687 			foreach(index, wrapper; onCancelListeners)
688 			{
689 				if (wrapper.handlerId == source.handlerId)
690 				{
691 					onCancelListeners[index] = null;
692 					onCancelListeners = std.algorithm.remove(onCancelListeners, index);
693 					break;
694 				}
695 			}
696 		}
697 	}
698 	OnCancelDelegateWrapper[] onCancelListeners;
699 
700 	/**
701 	 * This signal is emitted whenever a sequence is cancelled. This usually
702 	 * happens on active touches when gtk_event_controller_reset() is called
703 	 * on @gesture (manually, due to grabs...), or the individual @sequence
704 	 * was claimed by parent widgets' controllers (see gtk_gesture_set_sequence_state()).
705 	 *
706 	 * @gesture must forget everything about @sequence as a reaction to this signal.
707 	 *
708 	 * Params:
709 	 *     sequence = the #GdkEventSequence that was cancelled
710 	 *
711 	 * Since: 3.14
712 	 */
713 	gulong addOnCancel(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
714 	{
715 		auto wrapper = new OnCancelDelegateWrapper(dlg);
716 		wrapper.handlerId = Signals.connectData(
717 			this,
718 			"cancel",
719 			cast(GCallback)&callBackCancel,
720 			cast(void*)wrapper,
721 			cast(GClosureNotify)&callBackCancelDestroy,
722 			connectFlags);
723 		return wrapper.handlerId;
724 	}
725 
726 	extern(C) static void callBackCancel(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnCancelDelegateWrapper wrapper)
727 	{
728 		wrapper.dlg(sequence, wrapper.outer);
729 	}
730 
731 	extern(C) static void callBackCancelDestroy(OnCancelDelegateWrapper wrapper, GClosure* closure)
732 	{
733 		wrapper.remove(wrapper);
734 	}
735 
736 	protected class OnCancelGenericDelegateWrapper
737 	{
738 		void delegate(Event, Gesture) dlg;
739 		gulong handlerId;
740 
741 		this(void delegate(Event, Gesture) dlg)
742 		{
743 			this.dlg = dlg;
744 			onCancelGenericListeners ~= this;
745 		}
746 
747 		void remove(OnCancelGenericDelegateWrapper source)
748 		{
749 			foreach(index, wrapper; onCancelGenericListeners)
750 			{
751 				if (wrapper.handlerId == source.handlerId)
752 				{
753 					onCancelGenericListeners[index] = null;
754 					onCancelGenericListeners = std.algorithm.remove(onCancelGenericListeners, index);
755 					break;
756 				}
757 			}
758 		}
759 	}
760 	OnCancelGenericDelegateWrapper[] onCancelGenericListeners;
761 
762 	/**
763 	 * This signal is emitted whenever a sequence is cancelled. This usually
764 	 * happens on active touches when gtk_event_controller_reset() is called
765 	 * on @gesture (manually, due to grabs...), or the individual @sequence
766 	 * was claimed by parent widgets' controllers (see gtk_gesture_set_sequence_state()).
767 	 *
768 	 * @gesture must forget everything about @sequence as a reaction to this signal.
769 	 *
770 	 * Params:
771 	 *     sequence = the #GdkEventSequence that was cancelled
772 	 *
773 	 * Since: 3.14
774 	 */
775 	gulong addOnCancel(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
776 	{
777 		auto wrapper = new OnCancelGenericDelegateWrapper(dlg);
778 		wrapper.handlerId = Signals.connectData(
779 			this,
780 			"cancel",
781 			cast(GCallback)&callBackCancelGeneric,
782 			cast(void*)wrapper,
783 			cast(GClosureNotify)&callBackCancelGenericDestroy,
784 			connectFlags);
785 		return wrapper.handlerId;
786 	}
787 
788 	extern(C) static void callBackCancelGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnCancelGenericDelegateWrapper wrapper)
789 	{
790 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
791 	}
792 
793 	extern(C) static void callBackCancelGenericDestroy(OnCancelGenericDelegateWrapper wrapper, GClosure* closure)
794 	{
795 		wrapper.remove(wrapper);
796 	}
797 
798 	protected class OnEndDelegateWrapper
799 	{
800 		void delegate(GdkEventSequence*, Gesture) dlg;
801 		gulong handlerId;
802 
803 		this(void delegate(GdkEventSequence*, Gesture) dlg)
804 		{
805 			this.dlg = dlg;
806 			onEndListeners ~= this;
807 		}
808 
809 		void remove(OnEndDelegateWrapper source)
810 		{
811 			foreach(index, wrapper; onEndListeners)
812 			{
813 				if (wrapper.handlerId == source.handlerId)
814 				{
815 					onEndListeners[index] = null;
816 					onEndListeners = std.algorithm.remove(onEndListeners, index);
817 					break;
818 				}
819 			}
820 		}
821 	}
822 	OnEndDelegateWrapper[] onEndListeners;
823 
824 	/**
825 	 * This signal is emitted when @gesture either stopped recognizing the event
826 	 * sequences as something to be handled (the #GtkGesture::check handler returned
827 	 * %FALSE), or the number of touch sequences became higher or lower than
828 	 * #GtkGesture:n-points.
829 	 *
830 	 * Note: @sequence might not pertain to the group of sequences that were
831 	 * previously triggering recognition on @gesture (ie. a just pressed touch
832 	 * sequence that exceeds #GtkGesture:n-points). This situation may be detected
833 	 * by checking through gtk_gesture_handles_sequence().
834 	 *
835 	 * Params:
836 	 *     sequence = the #GdkEventSequence that made gesture recognition to finish
837 	 *
838 	 * Since: 3.14
839 	 */
840 	gulong addOnEnd(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
841 	{
842 		auto wrapper = new OnEndDelegateWrapper(dlg);
843 		wrapper.handlerId = Signals.connectData(
844 			this,
845 			"end",
846 			cast(GCallback)&callBackEnd,
847 			cast(void*)wrapper,
848 			cast(GClosureNotify)&callBackEndDestroy,
849 			connectFlags);
850 		return wrapper.handlerId;
851 	}
852 
853 	extern(C) static void callBackEnd(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnEndDelegateWrapper wrapper)
854 	{
855 		wrapper.dlg(sequence, wrapper.outer);
856 	}
857 
858 	extern(C) static void callBackEndDestroy(OnEndDelegateWrapper wrapper, GClosure* closure)
859 	{
860 		wrapper.remove(wrapper);
861 	}
862 
863 	protected class OnEndGenericDelegateWrapper
864 	{
865 		void delegate(Event, Gesture) dlg;
866 		gulong handlerId;
867 
868 		this(void delegate(Event, Gesture) dlg)
869 		{
870 			this.dlg = dlg;
871 			onEndGenericListeners ~= this;
872 		}
873 
874 		void remove(OnEndGenericDelegateWrapper source)
875 		{
876 			foreach(index, wrapper; onEndGenericListeners)
877 			{
878 				if (wrapper.handlerId == source.handlerId)
879 				{
880 					onEndGenericListeners[index] = null;
881 					onEndGenericListeners = std.algorithm.remove(onEndGenericListeners, index);
882 					break;
883 				}
884 			}
885 		}
886 	}
887 	OnEndGenericDelegateWrapper[] onEndGenericListeners;
888 
889 	/**
890 	 * This signal is emitted when @gesture either stopped recognizing the event
891 	 * sequences as something to be handled (the #GtkGesture::check handler returned
892 	 * %FALSE), or the number of touch sequences became higher or lower than
893 	 * #GtkGesture:n-points.
894 	 *
895 	 * Note: @sequence might not pertain to the group of sequences that were
896 	 * previously triggering recognition on @gesture (ie. a just pressed touch
897 	 * sequence that exceeds #GtkGesture:n-points). This situation may be detected
898 	 * by checking through gtk_gesture_handles_sequence().
899 	 *
900 	 * Params:
901 	 *     sequence = the #GdkEventSequence that made gesture recognition to finish
902 	 *
903 	 * Since: 3.14
904 	 */
905 	gulong addOnEnd(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
906 	{
907 		auto wrapper = new OnEndGenericDelegateWrapper(dlg);
908 		wrapper.handlerId = Signals.connectData(
909 			this,
910 			"end",
911 			cast(GCallback)&callBackEndGeneric,
912 			cast(void*)wrapper,
913 			cast(GClosureNotify)&callBackEndGenericDestroy,
914 			connectFlags);
915 		return wrapper.handlerId;
916 	}
917 
918 	extern(C) static void callBackEndGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnEndGenericDelegateWrapper wrapper)
919 	{
920 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
921 	}
922 
923 	extern(C) static void callBackEndGenericDestroy(OnEndGenericDelegateWrapper wrapper, GClosure* closure)
924 	{
925 		wrapper.remove(wrapper);
926 	}
927 
928 	protected class OnSequenceStateChangedDelegateWrapper
929 	{
930 		void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg;
931 		gulong handlerId;
932 
933 		this(void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg)
934 		{
935 			this.dlg = dlg;
936 			onSequenceStateChangedListeners ~= this;
937 		}
938 
939 		void remove(OnSequenceStateChangedDelegateWrapper source)
940 		{
941 			foreach(index, wrapper; onSequenceStateChangedListeners)
942 			{
943 				if (wrapper.handlerId == source.handlerId)
944 				{
945 					onSequenceStateChangedListeners[index] = null;
946 					onSequenceStateChangedListeners = std.algorithm.remove(onSequenceStateChangedListeners, index);
947 					break;
948 				}
949 			}
950 		}
951 	}
952 	OnSequenceStateChangedDelegateWrapper[] onSequenceStateChangedListeners;
953 
954 	/**
955 	 * This signal is emitted whenever a sequence state changes. See
956 	 * gtk_gesture_set_sequence_state() to know more about the expectable
957 	 * sequence lifetimes.
958 	 *
959 	 * Params:
960 	 *     sequence = the #GdkEventSequence that was cancelled
961 	 *     state = the new sequence state
962 	 *
963 	 * Since: 3.14
964 	 */
965 	gulong addOnSequenceStateChanged(void delegate(GdkEventSequence*, GtkEventSequenceState, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
966 	{
967 		auto wrapper = new OnSequenceStateChangedDelegateWrapper(dlg);
968 		wrapper.handlerId = Signals.connectData(
969 			this,
970 			"sequence-state-changed",
971 			cast(GCallback)&callBackSequenceStateChanged,
972 			cast(void*)wrapper,
973 			cast(GClosureNotify)&callBackSequenceStateChangedDestroy,
974 			connectFlags);
975 		return wrapper.handlerId;
976 	}
977 
978 	extern(C) static void callBackSequenceStateChanged(GtkGesture* gestureStruct, GdkEventSequence* sequence, GtkEventSequenceState state, OnSequenceStateChangedDelegateWrapper wrapper)
979 	{
980 		wrapper.dlg(sequence, state, wrapper.outer);
981 	}
982 
983 	extern(C) static void callBackSequenceStateChangedDestroy(OnSequenceStateChangedDelegateWrapper wrapper, GClosure* closure)
984 	{
985 		wrapper.remove(wrapper);
986 	}
987 
988 	protected class OnSequenceStateChangedGenericDelegateWrapper
989 	{
990 		void delegate(Event, GtkEventSequenceState, Gesture) dlg;
991 		gulong handlerId;
992 
993 		this(void delegate(Event, GtkEventSequenceState, Gesture) dlg)
994 		{
995 			this.dlg = dlg;
996 			onSequenceStateChangedGenericListeners ~= this;
997 		}
998 
999 		void remove(OnSequenceStateChangedGenericDelegateWrapper source)
1000 		{
1001 			foreach(index, wrapper; onSequenceStateChangedGenericListeners)
1002 			{
1003 				if (wrapper.handlerId == source.handlerId)
1004 				{
1005 					onSequenceStateChangedGenericListeners[index] = null;
1006 					onSequenceStateChangedGenericListeners = std.algorithm.remove(onSequenceStateChangedGenericListeners, index);
1007 					break;
1008 				}
1009 			}
1010 		}
1011 	}
1012 	OnSequenceStateChangedGenericDelegateWrapper[] onSequenceStateChangedGenericListeners;
1013 
1014 	/**
1015 	 * This signal is emitted whenever a sequence state changes. See
1016 	 * gtk_gesture_set_sequence_state() to know more about the expectable
1017 	 * sequence lifetimes.
1018 	 *
1019 	 * Params:
1020 	 *     sequence = the #GdkEventSequence that was cancelled
1021 	 *     state = the new sequence state
1022 	 *
1023 	 * Since: 3.14
1024 	 */
1025 	gulong addOnSequenceStateChanged(void delegate(Event, GtkEventSequenceState, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1026 	{
1027 		auto wrapper = new OnSequenceStateChangedGenericDelegateWrapper(dlg);
1028 		wrapper.handlerId = Signals.connectData(
1029 			this,
1030 			"sequence-state-changed",
1031 			cast(GCallback)&callBackSequenceStateChangedGeneric,
1032 			cast(void*)wrapper,
1033 			cast(GClosureNotify)&callBackSequenceStateChangedGenericDestroy,
1034 			connectFlags);
1035 		return wrapper.handlerId;
1036 	}
1037 
1038 	extern(C) static void callBackSequenceStateChangedGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, GtkEventSequenceState state, OnSequenceStateChangedGenericDelegateWrapper wrapper)
1039 	{
1040 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), state, wrapper.outer);
1041 	}
1042 
1043 	extern(C) static void callBackSequenceStateChangedGenericDestroy(OnSequenceStateChangedGenericDelegateWrapper wrapper, GClosure* closure)
1044 	{
1045 		wrapper.remove(wrapper);
1046 	}
1047 
1048 	protected class OnUpdateDelegateWrapper
1049 	{
1050 		void delegate(GdkEventSequence*, Gesture) dlg;
1051 		gulong handlerId;
1052 
1053 		this(void delegate(GdkEventSequence*, Gesture) dlg)
1054 		{
1055 			this.dlg = dlg;
1056 			onUpdateListeners ~= this;
1057 		}
1058 
1059 		void remove(OnUpdateDelegateWrapper source)
1060 		{
1061 			foreach(index, wrapper; onUpdateListeners)
1062 			{
1063 				if (wrapper.handlerId == source.handlerId)
1064 				{
1065 					onUpdateListeners[index] = null;
1066 					onUpdateListeners = std.algorithm.remove(onUpdateListeners, index);
1067 					break;
1068 				}
1069 			}
1070 		}
1071 	}
1072 	OnUpdateDelegateWrapper[] onUpdateListeners;
1073 
1074 	/**
1075 	 * This signal is emitted whenever an event is handled while the gesture is
1076 	 * recognized. @sequence is guaranteed to pertain to the set of active touches.
1077 	 *
1078 	 * Params:
1079 	 *     sequence = the #GdkEventSequence that was updated
1080 	 *
1081 	 * Since: 3.14
1082 	 */
1083 	gulong addOnUpdate(void delegate(GdkEventSequence*, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1084 	{
1085 		auto wrapper = new OnUpdateDelegateWrapper(dlg);
1086 		wrapper.handlerId = Signals.connectData(
1087 			this,
1088 			"update",
1089 			cast(GCallback)&callBackUpdate,
1090 			cast(void*)wrapper,
1091 			cast(GClosureNotify)&callBackUpdateDestroy,
1092 			connectFlags);
1093 		return wrapper.handlerId;
1094 	}
1095 
1096 	extern(C) static void callBackUpdate(GtkGesture* gestureStruct, GdkEventSequence* sequence, OnUpdateDelegateWrapper wrapper)
1097 	{
1098 		wrapper.dlg(sequence, wrapper.outer);
1099 	}
1100 
1101 	extern(C) static void callBackUpdateDestroy(OnUpdateDelegateWrapper wrapper, GClosure* closure)
1102 	{
1103 		wrapper.remove(wrapper);
1104 	}
1105 
1106 	protected class OnUpdateGenericDelegateWrapper
1107 	{
1108 		void delegate(Event, Gesture) dlg;
1109 		gulong handlerId;
1110 
1111 		this(void delegate(Event, Gesture) dlg)
1112 		{
1113 			this.dlg = dlg;
1114 			onUpdateGenericListeners ~= this;
1115 		}
1116 
1117 		void remove(OnUpdateGenericDelegateWrapper source)
1118 		{
1119 			foreach(index, wrapper; onUpdateGenericListeners)
1120 			{
1121 				if (wrapper.handlerId == source.handlerId)
1122 				{
1123 					onUpdateGenericListeners[index] = null;
1124 					onUpdateGenericListeners = std.algorithm.remove(onUpdateGenericListeners, index);
1125 					break;
1126 				}
1127 			}
1128 		}
1129 	}
1130 	OnUpdateGenericDelegateWrapper[] onUpdateGenericListeners;
1131 
1132 	/**
1133 	 * This signal is emitted whenever an event is handled while the gesture is
1134 	 * recognized. @sequence is guaranteed to pertain to the set of active touches.
1135 	 *
1136 	 * Params:
1137 	 *     sequence = the #GdkEventSequence that was updated
1138 	 *
1139 	 * Since: 3.14
1140 	 */
1141 	gulong addOnUpdate(void delegate(Event, Gesture) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1142 	{
1143 		auto wrapper = new OnUpdateGenericDelegateWrapper(dlg);
1144 		wrapper.handlerId = Signals.connectData(
1145 			this,
1146 			"update",
1147 			cast(GCallback)&callBackUpdateGeneric,
1148 			cast(void*)wrapper,
1149 			cast(GClosureNotify)&callBackUpdateGenericDestroy,
1150 			connectFlags);
1151 		return wrapper.handlerId;
1152 	}
1153 
1154 	extern(C) static void callBackUpdateGeneric(GtkGesture* gestureStruct, GdkEvent* sequence, OnUpdateGenericDelegateWrapper wrapper)
1155 	{
1156 		wrapper.dlg(ObjectG.getDObject!(Event)(sequence), wrapper.outer);
1157 	}
1158 
1159 	extern(C) static void callBackUpdateGenericDestroy(OnUpdateGenericDelegateWrapper wrapper, GClosure* closure)
1160 	{
1161 		wrapper.remove(wrapper);
1162 	}
1163 }