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