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