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