1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GTK+ Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23  */
24 
25 #include "config.h"
26 
27 #include "gdkinternals.h"
28 #include "gdkdisplayprivate.h"
29 #include "gdkdndprivate.h"
30 
31 #include <string.h>
32 #include <math.h>
33 
34 
35 /**
36  * SECTION:events
37  * @Short_description: Functions for handling events from the window system
38  * @Title: Events
39  * @See_also: [Event Structures][gdk3-Event-Structures]
40  *
41  * This section describes functions dealing with events from the window
42  * system.
43  *
44  * In GTK+ applications the events are handled automatically in
45  * gtk_main_do_event() and passed on to the appropriate widgets, so these
46  * functions are rarely needed. Though some of the fields in the
47  * [Event Structures][gdk3-Event-Structures] are useful.
48  */
49 
50 
51 typedef struct _GdkIOClosure GdkIOClosure;
52 
53 struct _GdkIOClosure
54 {
55   GDestroyNotify notify;
56   gpointer data;
57 };
58 
59 /* Private variable declarations
60  */
61 
62 static GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
63 static gpointer       _gdk_event_data = NULL;
64 static GDestroyNotify _gdk_event_notify = NULL;
65 
66 void
_gdk_event_emit(GdkEvent * event)67 _gdk_event_emit (GdkEvent *event)
68 {
69   if (gdk_drag_context_handle_source_event (event))
70     return;
71 
72   if (_gdk_event_func)
73     (*_gdk_event_func) (event, _gdk_event_data);
74 
75   if (gdk_drag_context_handle_dest_event (event))
76     return;
77 }
78 
79 /*********************************************
80  * Functions for maintaining the event queue *
81  *********************************************/
82 
83 /**
84  * _gdk_event_queue_find_first:
85  * @display: a #GdkDisplay
86  *
87  * Find the first event on the queue that is not still
88  * being filled in.
89  *
90  * Returns: (nullable): Pointer to the list node for that event, or
91  *   %NULL.
92  **/
93 GList*
_gdk_event_queue_find_first(GdkDisplay * display)94 _gdk_event_queue_find_first (GdkDisplay *display)
95 {
96   GList *tmp_list;
97   GList *pending_motion = NULL;
98 
99   gboolean paused = display->event_pause_count > 0;
100 
101   tmp_list = display->queued_events;
102   while (tmp_list)
103     {
104       GdkEventPrivate *event = tmp_list->data;
105 
106       if ((event->flags & GDK_EVENT_PENDING) == 0 &&
107 	  (!paused || (event->flags & GDK_EVENT_FLUSHED) != 0))
108         {
109           if (pending_motion)
110             return pending_motion;
111 
112           if (event->event.type == GDK_MOTION_NOTIFY && (event->flags & GDK_EVENT_FLUSHED) == 0)
113             pending_motion = tmp_list;
114           else
115             return tmp_list;
116         }
117 
118       tmp_list = tmp_list->next;
119     }
120 
121   return NULL;
122 }
123 
124 /**
125  * _gdk_event_queue_append:
126  * @display: a #GdkDisplay
127  * @event: Event to append.
128  *
129  * Appends an event onto the tail of the event queue.
130  *
131  * Returns: the newly appended list node.
132  **/
133 GList *
_gdk_event_queue_append(GdkDisplay * display,GdkEvent * event)134 _gdk_event_queue_append (GdkDisplay *display,
135 			 GdkEvent   *event)
136 {
137   display->queued_tail = g_list_append (display->queued_tail, event);
138 
139   if (!display->queued_events)
140     display->queued_events = display->queued_tail;
141   else
142     display->queued_tail = display->queued_tail->next;
143 
144   return display->queued_tail;
145 }
146 
147 /**
148  * _gdk_event_queue_insert_after:
149  * @display: a #GdkDisplay
150  * @sibling: Append after this event.
151  * @event: Event to append.
152  *
153  * Appends an event after the specified event, or if it isn’t in
154  * the queue, onto the tail of the event queue.
155  *
156  * Returns: the newly appended list node.
157  *
158  * Since: 2.16
159  */
160 GList*
_gdk_event_queue_insert_after(GdkDisplay * display,GdkEvent * sibling,GdkEvent * event)161 _gdk_event_queue_insert_after (GdkDisplay *display,
162                                GdkEvent   *sibling,
163                                GdkEvent   *event)
164 {
165   GList *prev = g_list_find (display->queued_events, sibling);
166   if (prev && prev->next)
167     {
168       display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
169       return prev->next;
170     }
171   else
172     return _gdk_event_queue_append (display, event);
173 }
174 
175 /**
176  * _gdk_event_queue_insert_before:
177  * @display: a #GdkDisplay
178  * @sibling: Append before this event
179  * @event: Event to prepend
180  *
181  * Prepends an event before the specified event, or if it isn’t in
182  * the queue, onto the head of the event queue.
183  *
184  * Returns: the newly prepended list node.
185  *
186  * Since: 2.16
187  */
188 GList*
_gdk_event_queue_insert_before(GdkDisplay * display,GdkEvent * sibling,GdkEvent * event)189 _gdk_event_queue_insert_before (GdkDisplay *display,
190 				GdkEvent   *sibling,
191 				GdkEvent   *event)
192 {
193   GList *next = g_list_find (display->queued_events, sibling);
194   if (next)
195     {
196       display->queued_events = g_list_insert_before (display->queued_events, next, event);
197       return next->prev;
198     }
199   else
200     return _gdk_event_queue_append (display, event);
201 }
202 
203 
204 /**
205  * _gdk_event_queue_remove_link:
206  * @display: a #GdkDisplay
207  * @node: node to remove
208  *
209  * Removes a specified list node from the event queue.
210  **/
211 void
_gdk_event_queue_remove_link(GdkDisplay * display,GList * node)212 _gdk_event_queue_remove_link (GdkDisplay *display,
213 			      GList      *node)
214 {
215   if (node->prev)
216     node->prev->next = node->next;
217   else
218     display->queued_events = node->next;
219 
220   if (node->next)
221     node->next->prev = node->prev;
222   else
223     display->queued_tail = node->prev;
224 }
225 
226 /**
227  * _gdk_event_unqueue:
228  * @display: a #GdkDisplay
229  *
230  * Removes and returns the first event from the event
231  * queue that is not still being filled in.
232  *
233  * Returns: (nullable): the event, or %NULL. Ownership is transferred
234  * to the caller.
235  **/
236 GdkEvent*
_gdk_event_unqueue(GdkDisplay * display)237 _gdk_event_unqueue (GdkDisplay *display)
238 {
239   GdkEvent *event = NULL;
240   GList *tmp_list;
241 
242   tmp_list = _gdk_event_queue_find_first (display);
243 
244   if (tmp_list)
245     {
246       event = tmp_list->data;
247       _gdk_event_queue_remove_link (display, tmp_list);
248       g_list_free_1 (tmp_list);
249     }
250 
251   return event;
252 }
253 
254 void
_gdk_event_queue_handle_motion_compression(GdkDisplay * display)255 _gdk_event_queue_handle_motion_compression (GdkDisplay *display)
256 {
257   GList *tmp_list;
258   GList *pending_motions = NULL;
259   GdkWindow *pending_motion_window = NULL;
260   GdkDevice *pending_motion_device = NULL;
261 
262   /* If the last N events in the event queue are motion notify
263    * events for the same window, drop all but the last */
264 
265   tmp_list = display->queued_tail;
266 
267   while (tmp_list)
268     {
269       GdkEventPrivate *event = tmp_list->data;
270 
271       if (event->flags & GDK_EVENT_PENDING)
272         break;
273 
274       if (event->event.type != GDK_MOTION_NOTIFY)
275         break;
276 
277       if (pending_motion_window != NULL &&
278           pending_motion_window != event->event.motion.window)
279         break;
280 
281       if (pending_motion_device != NULL &&
282           pending_motion_device != event->event.motion.device)
283         break;
284 
285       if (!event->event.motion.window->event_compression)
286         break;
287 
288       pending_motion_window = event->event.motion.window;
289       pending_motion_device = event->event.motion.device;
290       pending_motions = tmp_list;
291 
292       tmp_list = tmp_list->prev;
293     }
294 
295   while (pending_motions && pending_motions->next != NULL)
296     {
297       GList *next = pending_motions->next;
298       gdk_event_free (pending_motions->data);
299       display->queued_events = g_list_delete_link (display->queued_events,
300                                                    pending_motions);
301       pending_motions = next;
302     }
303 
304   if (pending_motions &&
305       pending_motions == display->queued_events &&
306       pending_motions == display->queued_tail)
307     {
308       GdkFrameClock *clock = gdk_window_get_frame_clock (pending_motion_window);
309       if (clock) /* might be NULL if window was destroyed */
310 	gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS);
311     }
312 }
313 
314 void
_gdk_event_queue_flush(GdkDisplay * display)315 _gdk_event_queue_flush (GdkDisplay *display)
316 {
317   GList *tmp_list;
318 
319   for (tmp_list = display->queued_events; tmp_list; tmp_list = tmp_list->next)
320     {
321       GdkEventPrivate *event = tmp_list->data;
322       event->flags |= GDK_EVENT_FLUSHED;
323     }
324 }
325 
326 /**
327  * gdk_event_handler_set:
328  * @func: the function to call to handle events from GDK.
329  * @data: user data to pass to the function.
330  * @notify: the function to call when the handler function is removed, i.e. when
331  *          gdk_event_handler_set() is called with another event handler.
332  *
333  * Sets the function to call to handle all events from GDK.
334  *
335  * Note that GTK+ uses this to install its own event handler, so it is
336  * usually not useful for GTK+ applications. (Although an application
337  * can call this function then call gtk_main_do_event() to pass
338  * events to GTK+.)
339  **/
340 void
gdk_event_handler_set(GdkEventFunc func,gpointer data,GDestroyNotify notify)341 gdk_event_handler_set (GdkEventFunc   func,
342 		       gpointer       data,
343 		       GDestroyNotify notify)
344 {
345   if (_gdk_event_notify)
346     (*_gdk_event_notify) (_gdk_event_data);
347 
348   _gdk_event_func = func;
349   _gdk_event_data = data;
350   _gdk_event_notify = notify;
351 }
352 
353 /**
354  * gdk_events_pending:
355  *
356  * Checks if any events are ready to be processed for any display.
357  *
358  * Returns: %TRUE if any events are pending.
359  */
360 gboolean
gdk_events_pending(void)361 gdk_events_pending (void)
362 {
363   GSList *list, *l;
364   gboolean pending;
365 
366   pending = FALSE;
367   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
368   for (l = list; l; l = l->next)
369     {
370       if (_gdk_event_queue_find_first (l->data))
371         {
372           pending = TRUE;
373           goto out;
374         }
375     }
376 
377   for (l = list; l; l = l->next)
378     {
379       if (gdk_display_has_pending (l->data))
380         {
381           pending = TRUE;
382           goto out;
383         }
384     }
385 
386  out:
387   g_slist_free (list);
388 
389   return pending;
390 }
391 
392 /**
393  * gdk_event_get:
394  *
395  * Checks all open displays for a #GdkEvent to process,to be processed
396  * on, fetching events from the windowing system if necessary.
397  * See gdk_display_get_event().
398  *
399  * Returns: (nullable): the next #GdkEvent to be processed, or %NULL
400  * if no events are pending. The returned #GdkEvent should be freed
401  * with gdk_event_free().
402  **/
403 GdkEvent*
gdk_event_get(void)404 gdk_event_get (void)
405 {
406   GSList *list, *l;
407   GdkEvent *event;
408 
409   event = NULL;
410   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
411   for (l = list; l; l = l->next)
412     {
413       event = gdk_display_get_event (l->data);
414       if (event)
415         break;
416     }
417 
418   g_slist_free (list);
419 
420   return event;
421 }
422 
423 /**
424  * gdk_event_peek:
425  *
426  * If there is an event waiting in the event queue of some open
427  * display, returns a copy of it. See gdk_display_peek_event().
428  *
429  * Returns: (nullable): a copy of the first #GdkEvent on some event
430  * queue, or %NULL if no events are in any queues. The returned
431  * #GdkEvent should be freed with gdk_event_free().
432  **/
433 GdkEvent*
gdk_event_peek(void)434 gdk_event_peek (void)
435 {
436   GSList *list, *l;
437   GdkEvent *event;
438 
439   event = NULL;
440   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
441   for (l = list; l; l = l->next)
442     {
443       event = gdk_display_peek_event (l->data);
444       if (event)
445         break;
446     }
447 
448   g_slist_free (list);
449 
450   return event;
451 }
452 
453 static GdkDisplay *
event_get_display(const GdkEvent * event)454 event_get_display (const GdkEvent *event)
455 {
456   if (event->any.window)
457     return gdk_window_get_display (event->any.window);
458   else
459     return gdk_display_get_default ();
460 }
461 
462 /**
463  * gdk_event_put:
464  * @event: a #GdkEvent.
465  *
466  * Appends a copy of the given event onto the front of the event
467  * queue for event->any.window’s display, or the default event
468  * queue if event->any.window is %NULL. See gdk_display_put_event().
469  **/
470 void
gdk_event_put(const GdkEvent * event)471 gdk_event_put (const GdkEvent *event)
472 {
473   GdkDisplay *display;
474 
475   g_return_if_fail (event != NULL);
476 
477   display = event_get_display (event);
478 
479   gdk_display_put_event (display, event);
480 }
481 
482 static GHashTable *event_hash = NULL;
483 
484 /**
485  * gdk_event_new:
486  * @type: a #GdkEventType
487  *
488  * Creates a new event of the given type. All fields are set to 0.
489  *
490  * Returns: a newly-allocated #GdkEvent. The returned #GdkEvent
491  * should be freed with gdk_event_free().
492  *
493  * Since: 2.2
494  **/
495 GdkEvent*
gdk_event_new(GdkEventType type)496 gdk_event_new (GdkEventType type)
497 {
498   GdkEventPrivate *new_private;
499   GdkEvent *new_event;
500 
501   if (!event_hash)
502     event_hash = g_hash_table_new (g_direct_hash, NULL);
503 
504   new_private = g_slice_new0 (GdkEventPrivate);
505 
506   new_private->flags = 0;
507   new_private->screen = NULL;
508 
509   g_hash_table_insert (event_hash, new_private, GUINT_TO_POINTER (1));
510 
511   new_event = (GdkEvent *) new_private;
512 
513   new_event->any.type = type;
514 
515   /*
516    * Bytewise 0 initialization is reasonable for most of the
517    * current event types. Explicitely initialize double fields
518    * since I trust bytewise 0 == 0. less than for integers
519    * or pointers.
520    */
521   switch (type)
522     {
523     case GDK_MOTION_NOTIFY:
524       new_event->motion.x = 0.;
525       new_event->motion.y = 0.;
526       new_event->motion.x_root = 0.;
527       new_event->motion.y_root = 0.;
528       break;
529     case GDK_BUTTON_PRESS:
530     case GDK_2BUTTON_PRESS:
531     case GDK_3BUTTON_PRESS:
532     case GDK_BUTTON_RELEASE:
533       new_event->button.x = 0.;
534       new_event->button.y = 0.;
535       new_event->button.x_root = 0.;
536       new_event->button.y_root = 0.;
537       break;
538     case GDK_TOUCH_BEGIN:
539     case GDK_TOUCH_UPDATE:
540     case GDK_TOUCH_END:
541     case GDK_TOUCH_CANCEL:
542       new_event->touch.x = 0.;
543       new_event->touch.y = 0.;
544       new_event->touch.x_root = 0.;
545       new_event->touch.y_root = 0.;
546       break;
547     case GDK_SCROLL:
548       new_event->scroll.x = 0.;
549       new_event->scroll.y = 0.;
550       new_event->scroll.x_root = 0.;
551       new_event->scroll.y_root = 0.;
552       new_event->scroll.delta_x = 0.;
553       new_event->scroll.delta_y = 0.;
554       new_event->scroll.is_stop = FALSE;
555       break;
556     case GDK_ENTER_NOTIFY:
557     case GDK_LEAVE_NOTIFY:
558       new_event->crossing.x = 0.;
559       new_event->crossing.y = 0.;
560       new_event->crossing.x_root = 0.;
561       new_event->crossing.y_root = 0.;
562       break;
563     case GDK_TOUCHPAD_SWIPE:
564       new_event->touchpad_swipe.x = 0;
565       new_event->touchpad_swipe.y = 0;
566       new_event->touchpad_swipe.dx = 0;
567       new_event->touchpad_swipe.dy = 0;
568       new_event->touchpad_swipe.x_root = 0;
569       new_event->touchpad_swipe.y_root = 0;
570       break;
571     case GDK_TOUCHPAD_PINCH:
572       new_event->touchpad_pinch.x = 0;
573       new_event->touchpad_pinch.y = 0;
574       new_event->touchpad_pinch.dx = 0;
575       new_event->touchpad_pinch.dy = 0;
576       new_event->touchpad_pinch.angle_delta = 0;
577       new_event->touchpad_pinch.scale = 0;
578       new_event->touchpad_pinch.x_root = 0;
579       new_event->touchpad_pinch.y_root = 0;
580       break;
581     default:
582       break;
583     }
584 
585   return new_event;
586 }
587 
588 gboolean
gdk_event_is_allocated(const GdkEvent * event)589 gdk_event_is_allocated (const GdkEvent *event)
590 {
591   if (event_hash)
592     return g_hash_table_lookup (event_hash, event) != NULL;
593 
594   return FALSE;
595 }
596 
597 void
gdk_event_set_pointer_emulated(GdkEvent * event,gboolean emulated)598 gdk_event_set_pointer_emulated (GdkEvent *event,
599                                 gboolean  emulated)
600 {
601   if (gdk_event_is_allocated (event))
602     {
603       GdkEventPrivate *private = (GdkEventPrivate *) event;
604 
605       if (emulated)
606         private->flags |= GDK_EVENT_POINTER_EMULATED;
607       else
608         private->flags &= ~(GDK_EVENT_POINTER_EMULATED);
609     }
610 }
611 
612 /**
613  * gdk_event_get_pointer_emulated:
614  * #event: a #GdkEvent
615  *
616  * Returns whether this event is an 'emulated' pointer event (typically
617  * from a touch event), as opposed to a real one.
618  *
619  * Returns: %TRUE if this event is emulated
620  *
621  * Since: 3.22
622  */
623 gboolean
gdk_event_get_pointer_emulated(GdkEvent * event)624 gdk_event_get_pointer_emulated (GdkEvent *event)
625 {
626   if (gdk_event_is_allocated (event))
627     return (((GdkEventPrivate *) event)->flags & GDK_EVENT_POINTER_EMULATED) != 0;
628 
629   return FALSE;
630 }
631 
632 /**
633  * gdk_event_copy:
634  * @event: a #GdkEvent
635  *
636  * Copies a #GdkEvent, copying or incrementing the reference count of the
637  * resources associated with it (e.g. #GdkWindow’s and strings).
638  *
639  * Returns: a copy of @event. The returned #GdkEvent should be freed with
640  * gdk_event_free().
641  **/
642 GdkEvent*
gdk_event_copy(const GdkEvent * event)643 gdk_event_copy (const GdkEvent *event)
644 {
645   GdkEventPrivate *new_private;
646   GdkEvent *new_event;
647 
648   g_return_val_if_fail (event != NULL, NULL);
649 
650   new_event = gdk_event_new (GDK_NOTHING);
651   new_private = (GdkEventPrivate *)new_event;
652 
653   *new_event = *event;
654   if (new_event->any.window)
655     g_object_ref (new_event->any.window);
656 
657   if (gdk_event_is_allocated (event))
658     {
659       GdkEventPrivate *private = (GdkEventPrivate *)event;
660 
661       new_private->screen = private->screen;
662       new_private->device = private->device ? g_object_ref (private->device) : NULL;
663       new_private->source_device = private->source_device ? g_object_ref (private->source_device) : NULL;
664       new_private->seat = private->seat;
665       new_private->tool = private->tool;
666 
667 #ifdef GDK_WINDOWING_WIN32
668       new_private->translation_len = private->translation_len;
669       new_private->translation = g_memdup (private->translation, private->translation_len * sizeof (private->translation[0]));
670 #endif
671     }
672 
673   switch (event->any.type)
674     {
675     case GDK_KEY_PRESS:
676     case GDK_KEY_RELEASE:
677       new_event->key.string = g_strdup (event->key.string);
678       break;
679 
680     case GDK_ENTER_NOTIFY:
681     case GDK_LEAVE_NOTIFY:
682       if (event->crossing.subwindow != NULL)
683         g_object_ref (event->crossing.subwindow);
684       break;
685 
686     case GDK_DRAG_ENTER:
687     case GDK_DRAG_LEAVE:
688     case GDK_DRAG_MOTION:
689     case GDK_DRAG_STATUS:
690     case GDK_DROP_START:
691     case GDK_DROP_FINISHED:
692       g_object_ref (event->dnd.context);
693       break;
694 
695     case GDK_EXPOSE:
696     case GDK_DAMAGE:
697       if (event->expose.region)
698         new_event->expose.region = cairo_region_copy (event->expose.region);
699       break;
700 
701     case GDK_SETTING:
702       new_event->setting.name = g_strdup (new_event->setting.name);
703       break;
704 
705     case GDK_BUTTON_PRESS:
706     case GDK_2BUTTON_PRESS:
707     case GDK_3BUTTON_PRESS:
708     case GDK_BUTTON_RELEASE:
709       if (event->button.axes)
710         new_event->button.axes = g_memdup (event->button.axes,
711                                            sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
712       break;
713 
714     case GDK_TOUCH_BEGIN:
715     case GDK_TOUCH_UPDATE:
716     case GDK_TOUCH_END:
717     case GDK_TOUCH_CANCEL:
718       if (event->touch.axes)
719         new_event->touch.axes = g_memdup (event->touch.axes,
720                                            sizeof (gdouble) * gdk_device_get_n_axes (event->touch.device));
721       break;
722 
723     case GDK_MOTION_NOTIFY:
724       if (event->motion.axes)
725         new_event->motion.axes = g_memdup (event->motion.axes,
726                                            sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
727       break;
728 
729     case GDK_OWNER_CHANGE:
730       new_event->owner_change.owner = event->owner_change.owner;
731       if (new_event->owner_change.owner)
732         g_object_ref (new_event->owner_change.owner);
733       break;
734 
735     case GDK_SELECTION_CLEAR:
736     case GDK_SELECTION_NOTIFY:
737     case GDK_SELECTION_REQUEST:
738       new_event->selection.requestor = event->selection.requestor;
739       if (new_event->selection.requestor)
740         g_object_ref (new_event->selection.requestor);
741       break;
742 
743     default:
744       break;
745     }
746 
747   if (gdk_event_is_allocated (event))
748     _gdk_display_event_data_copy (event_get_display (event), event, new_event);
749 
750   return new_event;
751 }
752 
753 /**
754  * gdk_event_free:
755  * @event:  a #GdkEvent.
756  *
757  * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
758  * Note that this function should only be called with events returned from
759  * functions such as gdk_event_peek(), gdk_event_get(), gdk_event_copy()
760  * and gdk_event_new().
761  **/
762 void
gdk_event_free(GdkEvent * event)763 gdk_event_free (GdkEvent *event)
764 {
765   GdkEventPrivate *private;
766   GdkDisplay *display;
767 
768   g_return_if_fail (event != NULL);
769 
770   if (gdk_event_is_allocated (event))
771     {
772       private = (GdkEventPrivate *) event;
773       g_clear_object (&private->device);
774       g_clear_object (&private->source_device);
775 #ifdef GDK_WINDOWING_WIN32
776       g_free (private->translation);
777 #endif
778     }
779 
780   switch (event->any.type)
781     {
782     case GDK_KEY_PRESS:
783     case GDK_KEY_RELEASE:
784       g_free (event->key.string);
785       break;
786 
787     case GDK_ENTER_NOTIFY:
788     case GDK_LEAVE_NOTIFY:
789       if (event->crossing.subwindow != NULL)
790 	g_object_unref (event->crossing.subwindow);
791       break;
792 
793     case GDK_DRAG_ENTER:
794     case GDK_DRAG_LEAVE:
795     case GDK_DRAG_MOTION:
796     case GDK_DRAG_STATUS:
797     case GDK_DROP_START:
798     case GDK_DROP_FINISHED:
799       if (event->dnd.context != NULL)
800         g_object_unref (event->dnd.context);
801       break;
802 
803     case GDK_BUTTON_PRESS:
804     case GDK_2BUTTON_PRESS:
805     case GDK_3BUTTON_PRESS:
806     case GDK_BUTTON_RELEASE:
807       g_free (event->button.axes);
808       break;
809 
810     case GDK_TOUCH_BEGIN:
811     case GDK_TOUCH_UPDATE:
812     case GDK_TOUCH_END:
813     case GDK_TOUCH_CANCEL:
814       g_free (event->touch.axes);
815       break;
816 
817     case GDK_EXPOSE:
818     case GDK_DAMAGE:
819       if (event->expose.region)
820 	cairo_region_destroy (event->expose.region);
821       break;
822 
823     case GDK_MOTION_NOTIFY:
824       g_free (event->motion.axes);
825       break;
826 
827     case GDK_SETTING:
828       g_free (event->setting.name);
829       break;
830 
831     case GDK_OWNER_CHANGE:
832       if (event->owner_change.owner)
833         g_object_unref (event->owner_change.owner);
834       break;
835 
836     case GDK_SELECTION_CLEAR:
837     case GDK_SELECTION_NOTIFY:
838     case GDK_SELECTION_REQUEST:
839       if (event->selection.requestor)
840         g_object_unref (event->selection.requestor);
841       break;
842 
843     default:
844       break;
845     }
846 
847   display = event_get_display (event);
848   if (display)
849     _gdk_display_event_data_free (display, event);
850 
851   if (event->any.window)
852     g_object_unref (event->any.window);
853 
854   g_hash_table_remove (event_hash, event);
855   g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
856 }
857 
858 /**
859  * gdk_event_get_window:
860  * @event: a #GdkEvent
861  *
862  * Extracts the #GdkWindow associated with an event.
863  *
864  * Returns: (transfer none): The #GdkWindow associated with the event
865  *
866  * Since: 3.10
867  */
868 GdkWindow *
gdk_event_get_window(const GdkEvent * event)869 gdk_event_get_window (const GdkEvent *event)
870 {
871   g_return_val_if_fail (event != NULL, NULL);
872 
873   return event->any.window;
874 }
875 
876 /**
877  * gdk_event_get_time:
878  * @event: a #GdkEvent
879  *
880  * Returns the time stamp from @event, if there is one; otherwise
881  * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
882  *
883  * Returns: time stamp field from @event
884  **/
885 guint32
gdk_event_get_time(const GdkEvent * event)886 gdk_event_get_time (const GdkEvent *event)
887 {
888   if (event)
889     switch (event->type)
890       {
891       case GDK_MOTION_NOTIFY:
892 	return event->motion.time;
893       case GDK_BUTTON_PRESS:
894       case GDK_2BUTTON_PRESS:
895       case GDK_3BUTTON_PRESS:
896       case GDK_BUTTON_RELEASE:
897 	return event->button.time;
898       case GDK_TOUCH_BEGIN:
899       case GDK_TOUCH_UPDATE:
900       case GDK_TOUCH_END:
901       case GDK_TOUCH_CANCEL:
902         return event->touch.time;
903       case GDK_TOUCHPAD_SWIPE:
904         return event->touchpad_swipe.time;
905       case GDK_TOUCHPAD_PINCH:
906         return event->touchpad_pinch.time;
907       case GDK_SCROLL:
908         return event->scroll.time;
909       case GDK_KEY_PRESS:
910       case GDK_KEY_RELEASE:
911 	return event->key.time;
912       case GDK_ENTER_NOTIFY:
913       case GDK_LEAVE_NOTIFY:
914 	return event->crossing.time;
915       case GDK_PROPERTY_NOTIFY:
916 	return event->property.time;
917       case GDK_SELECTION_CLEAR:
918       case GDK_SELECTION_REQUEST:
919       case GDK_SELECTION_NOTIFY:
920 	return event->selection.time;
921       case GDK_PROXIMITY_IN:
922       case GDK_PROXIMITY_OUT:
923 	return event->proximity.time;
924       case GDK_DRAG_ENTER:
925       case GDK_DRAG_LEAVE:
926       case GDK_DRAG_MOTION:
927       case GDK_DRAG_STATUS:
928       case GDK_DROP_START:
929       case GDK_DROP_FINISHED:
930 	return event->dnd.time;
931       case GDK_PAD_BUTTON_PRESS:
932       case GDK_PAD_BUTTON_RELEASE:
933         return event->pad_button.time;
934       case GDK_PAD_RING:
935       case GDK_PAD_STRIP:
936         return event->pad_axis.time;
937       case GDK_PAD_GROUP_MODE:
938         return event->pad_group_mode.time;
939       case GDK_CLIENT_EVENT:
940       case GDK_VISIBILITY_NOTIFY:
941       case GDK_CONFIGURE:
942       case GDK_FOCUS_CHANGE:
943       case GDK_NOTHING:
944       case GDK_DAMAGE:
945       case GDK_DELETE:
946       case GDK_DESTROY:
947       case GDK_EXPOSE:
948       case GDK_MAP:
949       case GDK_UNMAP:
950       case GDK_WINDOW_STATE:
951       case GDK_SETTING:
952       case GDK_OWNER_CHANGE:
953       case GDK_GRAB_BROKEN:
954       case GDK_EVENT_LAST:
955         /* return current time */
956         break;
957       }
958 
959   return GDK_CURRENT_TIME;
960 }
961 
962 /**
963  * gdk_event_get_state:
964  * @event: (allow-none): a #GdkEvent or %NULL
965  * @state: (out): return location for state
966  *
967  * If the event contains a “state” field, puts that field in @state. Otherwise
968  * stores an empty state (0). Returns %TRUE if there was a state field
969  * in the event. @event may be %NULL, in which case it’s treated
970  * as if the event had no state field.
971  *
972  * Returns: %TRUE if there was a state field in the event
973  **/
974 gboolean
gdk_event_get_state(const GdkEvent * event,GdkModifierType * state)975 gdk_event_get_state (const GdkEvent        *event,
976                      GdkModifierType       *state)
977 {
978   g_return_val_if_fail (state != NULL, FALSE);
979 
980   if (event)
981     switch (event->type)
982       {
983       case GDK_MOTION_NOTIFY:
984 	*state = event->motion.state;
985         return TRUE;
986       case GDK_BUTTON_PRESS:
987       case GDK_2BUTTON_PRESS:
988       case GDK_3BUTTON_PRESS:
989       case GDK_BUTTON_RELEASE:
990         *state = event->button.state;
991         return TRUE;
992       case GDK_TOUCH_BEGIN:
993       case GDK_TOUCH_UPDATE:
994       case GDK_TOUCH_END:
995       case GDK_TOUCH_CANCEL:
996         *state = event->touch.state;
997         return TRUE;
998       case GDK_TOUCHPAD_SWIPE:
999         *state = event->touchpad_swipe.state;
1000         return TRUE;
1001       case GDK_TOUCHPAD_PINCH:
1002         *state = event->touchpad_pinch.state;
1003         return TRUE;
1004       case GDK_SCROLL:
1005 	*state =  event->scroll.state;
1006         return TRUE;
1007       case GDK_KEY_PRESS:
1008       case GDK_KEY_RELEASE:
1009 	*state =  event->key.state;
1010         return TRUE;
1011       case GDK_ENTER_NOTIFY:
1012       case GDK_LEAVE_NOTIFY:
1013 	*state =  event->crossing.state;
1014         return TRUE;
1015       case GDK_PROPERTY_NOTIFY:
1016       case GDK_VISIBILITY_NOTIFY:
1017       case GDK_CLIENT_EVENT:
1018       case GDK_CONFIGURE:
1019       case GDK_FOCUS_CHANGE:
1020       case GDK_SELECTION_CLEAR:
1021       case GDK_SELECTION_REQUEST:
1022       case GDK_SELECTION_NOTIFY:
1023       case GDK_PROXIMITY_IN:
1024       case GDK_PROXIMITY_OUT:
1025       case GDK_DAMAGE:
1026       case GDK_DRAG_ENTER:
1027       case GDK_DRAG_LEAVE:
1028       case GDK_DRAG_MOTION:
1029       case GDK_DRAG_STATUS:
1030       case GDK_DROP_START:
1031       case GDK_DROP_FINISHED:
1032       case GDK_NOTHING:
1033       case GDK_DELETE:
1034       case GDK_DESTROY:
1035       case GDK_EXPOSE:
1036       case GDK_MAP:
1037       case GDK_UNMAP:
1038       case GDK_WINDOW_STATE:
1039       case GDK_SETTING:
1040       case GDK_OWNER_CHANGE:
1041       case GDK_GRAB_BROKEN:
1042       case GDK_PAD_BUTTON_PRESS:
1043       case GDK_PAD_BUTTON_RELEASE:
1044       case GDK_PAD_RING:
1045       case GDK_PAD_STRIP:
1046       case GDK_PAD_GROUP_MODE:
1047       case GDK_EVENT_LAST:
1048         /* no state field */
1049         break;
1050       }
1051 
1052   *state = 0;
1053   return FALSE;
1054 }
1055 
1056 /**
1057  * gdk_event_get_coords:
1058  * @event: a #GdkEvent
1059  * @x_win: (out) (optional): location to put event window x coordinate
1060  * @y_win: (out) (optional): location to put event window y coordinate
1061  *
1062  * Extract the event window relative x/y coordinates from an event.
1063  *
1064  * Returns: %TRUE if the event delivered event window coordinates
1065  **/
1066 gboolean
gdk_event_get_coords(const GdkEvent * event,gdouble * x_win,gdouble * y_win)1067 gdk_event_get_coords (const GdkEvent *event,
1068 		      gdouble        *x_win,
1069 		      gdouble        *y_win)
1070 {
1071   gdouble x = 0, y = 0;
1072   gboolean fetched = TRUE;
1073 
1074   g_return_val_if_fail (event != NULL, FALSE);
1075 
1076   switch (event->type)
1077     {
1078     case GDK_CONFIGURE:
1079       x = event->configure.x;
1080       y = event->configure.y;
1081       break;
1082     case GDK_ENTER_NOTIFY:
1083     case GDK_LEAVE_NOTIFY:
1084       x = event->crossing.x;
1085       y = event->crossing.y;
1086       break;
1087     case GDK_SCROLL:
1088       x = event->scroll.x;
1089       y = event->scroll.y;
1090       break;
1091     case GDK_BUTTON_PRESS:
1092     case GDK_2BUTTON_PRESS:
1093     case GDK_3BUTTON_PRESS:
1094     case GDK_BUTTON_RELEASE:
1095       x = event->button.x;
1096       y = event->button.y;
1097       break;
1098     case GDK_TOUCH_BEGIN:
1099     case GDK_TOUCH_UPDATE:
1100     case GDK_TOUCH_END:
1101     case GDK_TOUCH_CANCEL:
1102       x = event->touch.x;
1103       y = event->touch.y;
1104       break;
1105     case GDK_MOTION_NOTIFY:
1106       x = event->motion.x;
1107       y = event->motion.y;
1108       break;
1109     case GDK_TOUCHPAD_SWIPE:
1110       x = event->touchpad_swipe.x;
1111       y = event->touchpad_swipe.y;
1112       break;
1113     case GDK_TOUCHPAD_PINCH:
1114       x = event->touchpad_pinch.x;
1115       y = event->touchpad_pinch.y;
1116       break;
1117     default:
1118       fetched = FALSE;
1119       break;
1120     }
1121 
1122   if (x_win)
1123     *x_win = x;
1124   if (y_win)
1125     *y_win = y;
1126 
1127   return fetched;
1128 }
1129 
1130 /**
1131  * gdk_event_get_root_coords:
1132  * @event: a #GdkEvent
1133  * @x_root: (out) (optional): location to put root window x coordinate
1134  * @y_root: (out) (optional): location to put root window y coordinate
1135  *
1136  * Extract the root window relative x/y coordinates from an event.
1137  *
1138  * Returns: %TRUE if the event delivered root window coordinates
1139  **/
1140 gboolean
gdk_event_get_root_coords(const GdkEvent * event,gdouble * x_root,gdouble * y_root)1141 gdk_event_get_root_coords (const GdkEvent *event,
1142 			   gdouble        *x_root,
1143 			   gdouble        *y_root)
1144 {
1145   gdouble x = 0, y = 0;
1146   gboolean fetched = TRUE;
1147 
1148   g_return_val_if_fail (event != NULL, FALSE);
1149 
1150   switch (event->type)
1151     {
1152     case GDK_MOTION_NOTIFY:
1153       x = event->motion.x_root;
1154       y = event->motion.y_root;
1155       break;
1156     case GDK_SCROLL:
1157       x = event->scroll.x_root;
1158       y = event->scroll.y_root;
1159       break;
1160     case GDK_BUTTON_PRESS:
1161     case GDK_2BUTTON_PRESS:
1162     case GDK_3BUTTON_PRESS:
1163     case GDK_BUTTON_RELEASE:
1164       x = event->button.x_root;
1165       y = event->button.y_root;
1166       break;
1167     case GDK_TOUCH_BEGIN:
1168     case GDK_TOUCH_UPDATE:
1169     case GDK_TOUCH_END:
1170     case GDK_TOUCH_CANCEL:
1171       x = event->touch.x_root;
1172       y = event->touch.y_root;
1173       break;
1174     case GDK_ENTER_NOTIFY:
1175     case GDK_LEAVE_NOTIFY:
1176       x = event->crossing.x_root;
1177       y = event->crossing.y_root;
1178       break;
1179     case GDK_DRAG_ENTER:
1180     case GDK_DRAG_LEAVE:
1181     case GDK_DRAG_MOTION:
1182     case GDK_DRAG_STATUS:
1183     case GDK_DROP_START:
1184     case GDK_DROP_FINISHED:
1185       x = event->dnd.x_root;
1186       y = event->dnd.y_root;
1187       break;
1188     case GDK_TOUCHPAD_SWIPE:
1189       x = event->touchpad_swipe.x_root;
1190       y = event->touchpad_swipe.y_root;
1191       break;
1192     case GDK_TOUCHPAD_PINCH:
1193       x = event->touchpad_pinch.x_root;
1194       y = event->touchpad_pinch.y_root;
1195       break;
1196     default:
1197       fetched = FALSE;
1198       break;
1199     }
1200 
1201   if (x_root)
1202     *x_root = x;
1203   if (y_root)
1204     *y_root = y;
1205 
1206   return fetched;
1207 }
1208 
1209 /**
1210  * gdk_event_get_button:
1211  * @event: a #GdkEvent
1212  * @button: (out): location to store mouse button number
1213  *
1214  * Extract the button number from an event.
1215  *
1216  * Returns: %TRUE if the event delivered a button number
1217  *
1218  * Since: 3.2
1219  **/
1220 gboolean
gdk_event_get_button(const GdkEvent * event,guint * button)1221 gdk_event_get_button (const GdkEvent *event,
1222                       guint *button)
1223 {
1224   gboolean fetched = TRUE;
1225   guint number = 0;
1226 
1227   g_return_val_if_fail (event != NULL, FALSE);
1228 
1229   switch (event->type)
1230     {
1231     case GDK_BUTTON_PRESS:
1232     case GDK_2BUTTON_PRESS:
1233     case GDK_3BUTTON_PRESS:
1234     case GDK_BUTTON_RELEASE:
1235       number = event->button.button;
1236       break;
1237     case GDK_PAD_BUTTON_PRESS:
1238     case GDK_PAD_BUTTON_RELEASE:
1239       number = event->pad_button.button;
1240       break;
1241     default:
1242       fetched = FALSE;
1243       break;
1244     }
1245 
1246   if (button)
1247     *button = number;
1248 
1249   return fetched;
1250 }
1251 
1252 /**
1253  * gdk_event_get_click_count:
1254  * @event: a #GdkEvent
1255  * @click_count: (out): location to store click count
1256  *
1257  * Extracts the click count from an event.
1258  *
1259  * Returns: %TRUE if the event delivered a click count
1260  *
1261  * Since: 3.2
1262  */
1263 gboolean
gdk_event_get_click_count(const GdkEvent * event,guint * click_count)1264 gdk_event_get_click_count (const GdkEvent *event,
1265                            guint *click_count)
1266 {
1267   gboolean fetched = TRUE;
1268   guint number = 0;
1269 
1270   g_return_val_if_fail (event != NULL, FALSE);
1271 
1272   switch (event->type)
1273     {
1274     case GDK_BUTTON_PRESS:
1275     case GDK_BUTTON_RELEASE:
1276       number = 1;
1277       break;
1278     case GDK_2BUTTON_PRESS:
1279       number = 2;
1280       break;
1281     case GDK_3BUTTON_PRESS:
1282       number = 3;
1283       break;
1284     default:
1285       fetched = FALSE;
1286       break;
1287     }
1288 
1289   if (click_count)
1290     *click_count = number;
1291 
1292   return fetched;
1293 }
1294 
1295 /**
1296  * gdk_event_get_keyval:
1297  * @event: a #GdkEvent
1298  * @keyval: (out): location to store the keyval
1299  *
1300  * Extracts the keyval from an event.
1301  *
1302  * Returns: %TRUE if the event delivered a key symbol
1303  *
1304  * Since: 3.2
1305  */
1306 gboolean
gdk_event_get_keyval(const GdkEvent * event,guint * keyval)1307 gdk_event_get_keyval (const GdkEvent *event,
1308                       guint *keyval)
1309 {
1310   gboolean fetched = TRUE;
1311   guint number = 0;
1312 
1313   switch (event->type)
1314     {
1315     case GDK_KEY_PRESS:
1316     case GDK_KEY_RELEASE:
1317       number = event->key.keyval;
1318       break;
1319     default:
1320       fetched = FALSE;
1321       break;
1322     }
1323 
1324   if (keyval)
1325     *keyval = number;
1326 
1327   return fetched;
1328 }
1329 
1330 /**
1331  * gdk_event_get_keycode:
1332  * @event: a #GdkEvent
1333  * @keycode: (out): location to store the keycode
1334  *
1335  * Extracts the hardware keycode from an event.
1336  *
1337  * Also see gdk_event_get_scancode().
1338  *
1339  * Returns: %TRUE if the event delivered a hardware keycode
1340  *
1341  * Since: 3.2
1342  */
1343 gboolean
gdk_event_get_keycode(const GdkEvent * event,guint16 * keycode)1344 gdk_event_get_keycode (const GdkEvent *event,
1345                        guint16 *keycode)
1346 {
1347   gboolean fetched = TRUE;
1348   guint16 number = 0;
1349 
1350   switch (event->type)
1351     {
1352     case GDK_KEY_PRESS:
1353     case GDK_KEY_RELEASE:
1354       number = event->key.hardware_keycode;
1355       break;
1356     default:
1357       fetched = FALSE;
1358       break;
1359     }
1360 
1361   if (keycode)
1362     *keycode = number;
1363 
1364   return fetched;
1365 }
1366 
1367 /**
1368  * gdk_event_get_scroll_direction:
1369  * @event: a #GdkEvent
1370  * @direction: (out): location to store the scroll direction
1371  *
1372  * Extracts the scroll direction from an event.
1373  *
1374  * If @event is not of type %GDK_SCROLL, the contents of @direction
1375  * are undefined.
1376  *
1377  * If you wish to handle both discrete and smooth scrolling, you
1378  * should check the return value of this function, or of
1379  * gdk_event_get_scroll_deltas(); for instance:
1380  *
1381  * |[<!-- language="C" -->
1382  *   GdkScrollDirection direction;
1383  *   double vscroll_factor = 0.0;
1384  *   double x_scroll, y_scroll;
1385  *
1386  *   if (gdk_event_get_scroll_direction (event, &direction))
1387  *     {
1388  *       // Handle discrete scrolling with a known constant delta;
1389  *       const double delta = 12.0;
1390  *
1391  *       switch (direction)
1392  *         {
1393  *         case GDK_SCROLL_UP:
1394  *           vscroll_factor = -delta;
1395  *           break;
1396  *         case GDK_SCROLL_DOWN:
1397  *           vscroll_factor = delta;
1398  *           break;
1399  *         default:
1400  *           // no scrolling
1401  *           break;
1402  *         }
1403  *     }
1404  *   else if (gdk_event_get_scroll_deltas (event, &x_scroll, &y_scroll))
1405  *     {
1406  *       // Handle smooth scrolling directly
1407  *       vscroll_factor = y_scroll;
1408  *     }
1409  * ]|
1410  *
1411  * Returns: %TRUE if the event delivered a scroll direction
1412  *   and %FALSE otherwise
1413  *
1414  * Since: 3.2
1415  */
1416 gboolean
gdk_event_get_scroll_direction(const GdkEvent * event,GdkScrollDirection * direction)1417 gdk_event_get_scroll_direction (const GdkEvent *event,
1418                                 GdkScrollDirection *direction)
1419 {
1420   gboolean fetched = TRUE;
1421   GdkScrollDirection dir = 0;
1422 
1423   switch (event->type)
1424     {
1425     case GDK_SCROLL:
1426       if (event->scroll.direction == GDK_SCROLL_SMOOTH)
1427         fetched = FALSE;
1428       else
1429         dir = event->scroll.direction;
1430       break;
1431     default:
1432       fetched = FALSE;
1433       break;
1434     }
1435 
1436   if (direction)
1437     *direction = dir;
1438 
1439   return fetched;
1440 }
1441 
1442 /**
1443  * gdk_event_get_scroll_deltas:
1444  * @event: a #GdkEvent
1445  * @delta_x: (out): return location for X delta
1446  * @delta_y: (out): return location for Y delta
1447  *
1448  * Retrieves the scroll deltas from a #GdkEvent
1449  *
1450  * See also: gdk_event_get_scroll_direction()
1451  *
1452  * Returns: %TRUE if the event contains smooth scroll information
1453  *   and %FALSE otherwise
1454  *
1455  * Since: 3.4
1456  **/
1457 gboolean
gdk_event_get_scroll_deltas(const GdkEvent * event,gdouble * delta_x,gdouble * delta_y)1458 gdk_event_get_scroll_deltas (const GdkEvent *event,
1459                              gdouble        *delta_x,
1460                              gdouble        *delta_y)
1461 {
1462   gboolean fetched = TRUE;
1463   gdouble dx = 0.0;
1464   gdouble dy = 0.0;
1465 
1466   switch (event->type)
1467     {
1468     case GDK_SCROLL:
1469       if (event->scroll.direction == GDK_SCROLL_SMOOTH)
1470         {
1471           dx = event->scroll.delta_x;
1472           dy = event->scroll.delta_y;
1473         }
1474       else
1475         fetched = FALSE;
1476       break;
1477     default:
1478       fetched = FALSE;
1479       break;
1480     }
1481 
1482   if (delta_x)
1483     *delta_x = dx;
1484 
1485   if (delta_y)
1486     *delta_y = dy;
1487 
1488   return fetched;
1489 }
1490 
1491 /**
1492  * gdk_event_is_scroll_stop_event
1493  * @event: a #GdkEvent
1494  *
1495  * Check whether a scroll event is a stop scroll event. Scroll sequences
1496  * with smooth scroll information may provide a stop scroll event once the
1497  * interaction with the device finishes, e.g. by lifting a finger. This
1498  * stop scroll event is the signal that a widget may trigger kinetic
1499  * scrolling based on the current velocity.
1500  *
1501  * Stop scroll events always have a a delta of 0/0.
1502  *
1503  * Returns: %TRUE if the event is a scroll stop event
1504  *
1505  * Since: 3.20
1506  */
1507 gboolean
gdk_event_is_scroll_stop_event(const GdkEvent * event)1508 gdk_event_is_scroll_stop_event (const GdkEvent *event)
1509 {
1510   return event->scroll.is_stop;
1511 }
1512 
1513 /**
1514  * gdk_event_get_axis:
1515  * @event: a #GdkEvent
1516  * @axis_use: the axis use to look for
1517  * @value: (out): location to store the value found
1518  *
1519  * Extract the axis value for a particular axis use from
1520  * an event structure.
1521  *
1522  * Returns: %TRUE if the specified axis was found, otherwise %FALSE
1523  **/
1524 gboolean
gdk_event_get_axis(const GdkEvent * event,GdkAxisUse axis_use,gdouble * value)1525 gdk_event_get_axis (const GdkEvent *event,
1526 		    GdkAxisUse      axis_use,
1527 		    gdouble        *value)
1528 {
1529   gdouble *axes;
1530   GdkDevice *device;
1531 
1532   g_return_val_if_fail (event != NULL, FALSE);
1533 
1534   if (axis_use == GDK_AXIS_X || axis_use == GDK_AXIS_Y)
1535     {
1536       gdouble x, y;
1537 
1538       switch (event->type)
1539 	{
1540         case GDK_MOTION_NOTIFY:
1541 	  x = event->motion.x;
1542 	  y = event->motion.y;
1543 	  break;
1544 	case GDK_SCROLL:
1545 	  x = event->scroll.x;
1546 	  y = event->scroll.y;
1547 	  break;
1548 	case GDK_BUTTON_PRESS:
1549 	case GDK_BUTTON_RELEASE:
1550 	  x = event->button.x;
1551 	  y = event->button.y;
1552 	  break;
1553         case GDK_TOUCH_BEGIN:
1554         case GDK_TOUCH_UPDATE:
1555         case GDK_TOUCH_END:
1556         case GDK_TOUCH_CANCEL:
1557 	  x = event->touch.x;
1558 	  y = event->touch.y;
1559 	  break;
1560 	case GDK_ENTER_NOTIFY:
1561 	case GDK_LEAVE_NOTIFY:
1562 	  x = event->crossing.x;
1563 	  y = event->crossing.y;
1564 	  break;
1565 
1566 	default:
1567 	  return FALSE;
1568 	}
1569 
1570       if (axis_use == GDK_AXIS_X && value)
1571 	*value = x;
1572       if (axis_use == GDK_AXIS_Y && value)
1573 	*value = y;
1574 
1575       return TRUE;
1576     }
1577   else if (event->type == GDK_BUTTON_PRESS ||
1578 	   event->type == GDK_BUTTON_RELEASE)
1579     {
1580       device = event->button.device;
1581       axes = event->button.axes;
1582     }
1583   else if (event->type == GDK_TOUCH_BEGIN ||
1584            event->type == GDK_TOUCH_UPDATE ||
1585            event->type == GDK_TOUCH_END ||
1586            event->type == GDK_TOUCH_CANCEL)
1587     {
1588       device = event->touch.device;
1589       axes = event->touch.axes;
1590     }
1591   else if (event->type == GDK_MOTION_NOTIFY)
1592     {
1593       device = event->motion.device;
1594       axes = event->motion.axes;
1595     }
1596   else
1597     return FALSE;
1598 
1599   return gdk_device_get_axis (device, axes, axis_use, value);
1600 }
1601 
1602 /**
1603  * gdk_event_set_device:
1604  * @event: a #GdkEvent
1605  * @device: a #GdkDevice
1606  *
1607  * Sets the device for @event to @device. The event must
1608  * have been allocated by GTK+, for instance, by
1609  * gdk_event_copy().
1610  *
1611  * Since: 3.0
1612  **/
1613 void
gdk_event_set_device(GdkEvent * event,GdkDevice * device)1614 gdk_event_set_device (GdkEvent  *event,
1615                       GdkDevice *device)
1616 {
1617   GdkEventPrivate *private;
1618 
1619   g_return_if_fail (gdk_event_is_allocated (event));
1620 
1621   private = (GdkEventPrivate *) event;
1622 
1623   g_set_object (&private->device, device);
1624 
1625   switch (event->type)
1626     {
1627     case GDK_MOTION_NOTIFY:
1628       event->motion.device = device;
1629       break;
1630     case GDK_BUTTON_PRESS:
1631     case GDK_2BUTTON_PRESS:
1632     case GDK_3BUTTON_PRESS:
1633     case GDK_BUTTON_RELEASE:
1634       event->button.device = device;
1635       break;
1636     case GDK_TOUCH_BEGIN:
1637     case GDK_TOUCH_UPDATE:
1638     case GDK_TOUCH_END:
1639     case GDK_TOUCH_CANCEL:
1640       event->touch.device = device;
1641       break;
1642     case GDK_SCROLL:
1643       event->scroll.device = device;
1644       break;
1645     case GDK_PROXIMITY_IN:
1646     case GDK_PROXIMITY_OUT:
1647       event->proximity.device = device;
1648       break;
1649     default:
1650       break;
1651     }
1652 }
1653 
1654 /**
1655  * gdk_event_get_device:
1656  * @event: a #GdkEvent.
1657  *
1658  * If the event contains a “device” field, this function will return
1659  * it, else it will return %NULL.
1660  *
1661  * Returns: (nullable) (transfer none): a #GdkDevice, or %NULL.
1662  *
1663  * Since: 3.0
1664  **/
1665 GdkDevice *
gdk_event_get_device(const GdkEvent * event)1666 gdk_event_get_device (const GdkEvent *event)
1667 {
1668   g_return_val_if_fail (event != NULL, NULL);
1669 
1670   if (gdk_event_is_allocated (event))
1671     {
1672       GdkEventPrivate *private = (GdkEventPrivate *) event;
1673 
1674       if (private->device)
1675         return private->device;
1676     }
1677 
1678   switch (event->type)
1679     {
1680     case GDK_MOTION_NOTIFY:
1681       return event->motion.device;
1682     case GDK_BUTTON_PRESS:
1683     case GDK_2BUTTON_PRESS:
1684     case GDK_3BUTTON_PRESS:
1685     case GDK_BUTTON_RELEASE:
1686       return event->button.device;
1687     case GDK_TOUCH_BEGIN:
1688     case GDK_TOUCH_UPDATE:
1689     case GDK_TOUCH_END:
1690     case GDK_TOUCH_CANCEL:
1691       return event->touch.device;
1692     case GDK_SCROLL:
1693       return event->scroll.device;
1694     case GDK_PROXIMITY_IN:
1695     case GDK_PROXIMITY_OUT:
1696       return event->proximity.device;
1697     default:
1698       break;
1699     }
1700 
1701   /* Fallback if event has no device set */
1702   switch (event->type)
1703     {
1704     case GDK_MOTION_NOTIFY:
1705     case GDK_BUTTON_PRESS:
1706     case GDK_2BUTTON_PRESS:
1707     case GDK_3BUTTON_PRESS:
1708     case GDK_BUTTON_RELEASE:
1709     case GDK_TOUCH_BEGIN:
1710     case GDK_TOUCH_UPDATE:
1711     case GDK_TOUCH_END:
1712     case GDK_TOUCH_CANCEL:
1713     case GDK_ENTER_NOTIFY:
1714     case GDK_LEAVE_NOTIFY:
1715     case GDK_FOCUS_CHANGE:
1716     case GDK_PROXIMITY_IN:
1717     case GDK_PROXIMITY_OUT:
1718     case GDK_DRAG_ENTER:
1719     case GDK_DRAG_LEAVE:
1720     case GDK_DRAG_MOTION:
1721     case GDK_DRAG_STATUS:
1722     case GDK_DROP_START:
1723     case GDK_DROP_FINISHED:
1724     case GDK_SCROLL:
1725     case GDK_GRAB_BROKEN:
1726     case GDK_KEY_PRESS:
1727     case GDK_KEY_RELEASE:
1728       {
1729         GdkDisplay *display;
1730         GdkSeat *seat;
1731 
1732         g_warning ("Event with type %d not holding a GdkDevice. "
1733                    "It is most likely synthesized outside Gdk/GTK+",
1734                    event->type);
1735 
1736         display = gdk_window_get_display (event->any.window);
1737         seat = gdk_display_get_default_seat (display);
1738 
1739         if (event->type == GDK_KEY_PRESS ||
1740             event->type == GDK_KEY_RELEASE)
1741           return gdk_seat_get_keyboard (seat);
1742         else
1743           return gdk_seat_get_pointer (seat);
1744       }
1745       break;
1746     default:
1747       return NULL;
1748     }
1749 }
1750 
1751 /**
1752  * gdk_event_set_source_device:
1753  * @event: a #GdkEvent
1754  * @device: a #GdkDevice
1755  *
1756  * Sets the slave device for @event to @device.
1757  *
1758  * The event must have been allocated by GTK+,
1759  * for instance by gdk_event_copy().
1760  *
1761  * Since: 3.0
1762  **/
1763 void
gdk_event_set_source_device(GdkEvent * event,GdkDevice * device)1764 gdk_event_set_source_device (GdkEvent  *event,
1765                              GdkDevice *device)
1766 {
1767   GdkEventPrivate *private;
1768 
1769   g_return_if_fail (gdk_event_is_allocated (event));
1770   g_return_if_fail (GDK_IS_DEVICE (device));
1771 
1772   private = (GdkEventPrivate *) event;
1773 
1774   g_set_object (&private->source_device, device);
1775 }
1776 
1777 /**
1778  * gdk_event_get_source_device:
1779  * @event: a #GdkEvent
1780  *
1781  * This function returns the hardware (slave) #GdkDevice that has
1782  * triggered the event, falling back to the virtual (master) device
1783  * (as in gdk_event_get_device()) if the event wasn’t caused by
1784  * interaction with a hardware device. This may happen for example
1785  * in synthesized crossing events after a #GdkWindow updates its
1786  * geometry or a grab is acquired/released.
1787  *
1788  * If the event does not contain a device field, this function will
1789  * return %NULL.
1790  *
1791  * Returns: (nullable) (transfer none): a #GdkDevice, or %NULL.
1792  *
1793  * Since: 3.0
1794  **/
1795 GdkDevice *
gdk_event_get_source_device(const GdkEvent * event)1796 gdk_event_get_source_device (const GdkEvent *event)
1797 {
1798   GdkEventPrivate *private;
1799 
1800   g_return_val_if_fail (event != NULL, NULL);
1801 
1802   if (!gdk_event_is_allocated (event))
1803     return NULL;
1804 
1805   private = (GdkEventPrivate *) event;
1806 
1807   if (private->source_device)
1808     return private->source_device;
1809 
1810   /* Fallback to event device */
1811   return gdk_event_get_device (event);
1812 }
1813 
1814 /**
1815  * gdk_event_request_motions:
1816  * @event: a valid #GdkEvent
1817  *
1818  * Request more motion notifies if @event is a motion notify hint event.
1819  *
1820  * This function should be used instead of gdk_window_get_pointer() to
1821  * request further motion notifies, because it also works for extension
1822  * events where motion notifies are provided for devices other than the
1823  * core pointer. Coordinate extraction, processing and requesting more
1824  * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
1825  *
1826  * |[<!-- language="C" -->
1827  * {
1828  *   // motion_event handler
1829  *   x = motion_event->x;
1830  *   y = motion_event->y;
1831  *   // handle (x,y) motion
1832  *   gdk_event_request_motions (motion_event); // handles is_hint events
1833  * }
1834  * ]|
1835  *
1836  * Since: 2.12
1837  **/
1838 void
gdk_event_request_motions(const GdkEventMotion * event)1839 gdk_event_request_motions (const GdkEventMotion *event)
1840 {
1841   GdkDisplay *display;
1842 
1843   g_return_if_fail (event != NULL);
1844 
1845   if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
1846     {
1847       gdk_device_get_state (event->device, event->window, NULL, NULL);
1848 
1849       display = gdk_window_get_display (event->window);
1850       _gdk_display_enable_motion_hints (display, event->device);
1851     }
1852 }
1853 
1854 /**
1855  * gdk_event_triggers_context_menu:
1856  * @event: a #GdkEvent, currently only button events are meaningful values
1857  *
1858  * This function returns whether a #GdkEventButton should trigger a
1859  * context menu, according to platform conventions. The right mouse
1860  * button always triggers context menus. Additionally, if
1861  * gdk_keymap_get_modifier_mask() returns a non-0 mask for
1862  * %GDK_MODIFIER_INTENT_CONTEXT_MENU, then the left mouse button will
1863  * also trigger a context menu if this modifier is pressed.
1864  *
1865  * This function should always be used instead of simply checking for
1866  * event->button == %GDK_BUTTON_SECONDARY.
1867  *
1868  * Returns: %TRUE if the event should trigger a context menu.
1869  *
1870  * Since: 3.4
1871  **/
1872 gboolean
gdk_event_triggers_context_menu(const GdkEvent * event)1873 gdk_event_triggers_context_menu (const GdkEvent *event)
1874 {
1875   g_return_val_if_fail (event != NULL, FALSE);
1876 
1877   if (event->type == GDK_BUTTON_PRESS)
1878     {
1879       const GdkEventButton *bevent = (const GdkEventButton *) event;
1880       GdkDisplay *display;
1881       GdkModifierType modifier;
1882 
1883       g_return_val_if_fail (GDK_IS_WINDOW (bevent->window), FALSE);
1884 
1885       if (bevent->button == GDK_BUTTON_SECONDARY &&
1886           ! (bevent->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))
1887         return TRUE;
1888 
1889       display = gdk_window_get_display (bevent->window);
1890 
1891       modifier = gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
1892                                                GDK_MODIFIER_INTENT_CONTEXT_MENU);
1893 
1894       if (modifier != 0 &&
1895           bevent->button == GDK_BUTTON_PRIMARY &&
1896           ! (bevent->state & (GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) &&
1897           (bevent->state & modifier))
1898         return TRUE;
1899     }
1900 
1901   return FALSE;
1902 }
1903 
1904 static gboolean
gdk_events_get_axis_distances(GdkEvent * event1,GdkEvent * event2,gdouble * x_distance,gdouble * y_distance,gdouble * distance)1905 gdk_events_get_axis_distances (GdkEvent *event1,
1906                                GdkEvent *event2,
1907                                gdouble  *x_distance,
1908                                gdouble  *y_distance,
1909                                gdouble  *distance)
1910 {
1911   gdouble x1, x2, y1, y2;
1912   gdouble xd, yd;
1913 
1914   if (!gdk_event_get_coords (event1, &x1, &y1) ||
1915       !gdk_event_get_coords (event2, &x2, &y2))
1916     return FALSE;
1917 
1918   xd = x2 - x1;
1919   yd = y2 - y1;
1920 
1921   if (x_distance)
1922     *x_distance = xd;
1923 
1924   if (y_distance)
1925     *y_distance = yd;
1926 
1927   if (distance)
1928     *distance = sqrt ((xd * xd) + (yd * yd));
1929 
1930   return TRUE;
1931 }
1932 
1933 /**
1934  * gdk_events_get_distance:
1935  * @event1: first #GdkEvent
1936  * @event2: second #GdkEvent
1937  * @distance: (out): return location for the distance
1938  *
1939  * If both events have X/Y information, the distance between both coordinates
1940  * (as in a straight line going from @event1 to @event2) will be returned.
1941  *
1942  * Returns: %TRUE if the distance could be calculated.
1943  *
1944  * Since: 3.0
1945  **/
1946 gboolean
gdk_events_get_distance(GdkEvent * event1,GdkEvent * event2,gdouble * distance)1947 gdk_events_get_distance (GdkEvent *event1,
1948                          GdkEvent *event2,
1949                          gdouble  *distance)
1950 {
1951   return gdk_events_get_axis_distances (event1, event2,
1952                                         NULL, NULL,
1953                                         distance);
1954 }
1955 
1956 /**
1957  * gdk_events_get_angle:
1958  * @event1: first #GdkEvent
1959  * @event2: second #GdkEvent
1960  * @angle: (out): return location for the relative angle between both events
1961  *
1962  * If both events contain X/Y information, this function will return %TRUE
1963  * and return in @angle the relative angle from @event1 to @event2. The rotation
1964  * direction for positive angles is from the positive X axis towards the positive
1965  * Y axis.
1966  *
1967  * Returns: %TRUE if the angle could be calculated.
1968  *
1969  * Since: 3.0
1970  **/
1971 gboolean
gdk_events_get_angle(GdkEvent * event1,GdkEvent * event2,gdouble * angle)1972 gdk_events_get_angle (GdkEvent *event1,
1973                       GdkEvent *event2,
1974                       gdouble  *angle)
1975 {
1976   gdouble x_distance, y_distance, distance;
1977 
1978   if (!gdk_events_get_axis_distances (event1, event2,
1979                                       &x_distance, &y_distance,
1980                                       &distance))
1981     return FALSE;
1982 
1983   if (angle)
1984     {
1985       *angle = atan2 (x_distance, y_distance);
1986 
1987       /* Invert angle */
1988       *angle = (2 * G_PI) - *angle;
1989 
1990       /* Shift it 90° */
1991       *angle += G_PI / 2;
1992 
1993       /* And constraint it to 0°-360° */
1994       *angle = fmod (*angle, 2 * G_PI);
1995     }
1996 
1997   return TRUE;
1998 }
1999 
2000 /**
2001  * gdk_events_get_center:
2002  * @event1: first #GdkEvent
2003  * @event2: second #GdkEvent
2004  * @x: (out): return location for the X coordinate of the center
2005  * @y: (out): return location for the Y coordinate of the center
2006  *
2007  * If both events contain X/Y information, the center of both coordinates
2008  * will be returned in @x and @y.
2009  *
2010  * Returns: %TRUE if the center could be calculated.
2011  *
2012  * Since: 3.0
2013  **/
2014 gboolean
gdk_events_get_center(GdkEvent * event1,GdkEvent * event2,gdouble * x,gdouble * y)2015 gdk_events_get_center (GdkEvent *event1,
2016                        GdkEvent *event2,
2017                        gdouble  *x,
2018                        gdouble  *y)
2019 {
2020   gdouble x1, x2, y1, y2;
2021 
2022   if (!gdk_event_get_coords (event1, &x1, &y1) ||
2023       !gdk_event_get_coords (event2, &x2, &y2))
2024     return FALSE;
2025 
2026   if (x)
2027     *x = (x2 + x1) / 2;
2028 
2029   if (y)
2030     *y = (y2 + y1) / 2;
2031 
2032   return TRUE;
2033 }
2034 
2035 /**
2036  * gdk_event_set_screen:
2037  * @event: a #GdkEvent
2038  * @screen: a #GdkScreen
2039  *
2040  * Sets the screen for @event to @screen. The event must
2041  * have been allocated by GTK+, for instance, by
2042  * gdk_event_copy().
2043  *
2044  * Since: 2.2
2045  **/
2046 void
gdk_event_set_screen(GdkEvent * event,GdkScreen * screen)2047 gdk_event_set_screen (GdkEvent  *event,
2048 		      GdkScreen *screen)
2049 {
2050   GdkEventPrivate *private;
2051 
2052   g_return_if_fail (gdk_event_is_allocated (event));
2053 
2054   private = (GdkEventPrivate *)event;
2055 
2056   private->screen = screen;
2057 }
2058 
2059 /**
2060  * gdk_event_get_screen:
2061  * @event: a #GdkEvent
2062  *
2063  * Returns the screen for the event. The screen is
2064  * typically the screen for `event->any.window`, but
2065  * for events such as mouse events, it is the screen
2066  * where the pointer was when the event occurs -
2067  * that is, the screen which has the root window
2068  * to which `event->motion.x_root` and
2069  * `event->motion.y_root` are relative.
2070  *
2071  * Returns: (transfer none): the screen for the event
2072  *
2073  * Since: 2.2
2074  **/
2075 GdkScreen *
gdk_event_get_screen(const GdkEvent * event)2076 gdk_event_get_screen (const GdkEvent *event)
2077 {
2078   if (gdk_event_is_allocated (event))
2079     {
2080       GdkEventPrivate *private = (GdkEventPrivate *)event;
2081 
2082       if (private->screen)
2083 	return private->screen;
2084     }
2085 
2086   if (event->any.window)
2087     return gdk_window_get_screen (event->any.window);
2088 
2089   return NULL;
2090 }
2091 
2092 /**
2093  * gdk_event_get_event_sequence:
2094  * @event: a #GdkEvent
2095  *
2096  * If @event if of type %GDK_TOUCH_BEGIN, %GDK_TOUCH_UPDATE,
2097  * %GDK_TOUCH_END or %GDK_TOUCH_CANCEL, returns the #GdkEventSequence
2098  * to which the event belongs. Otherwise, return %NULL.
2099  *
2100  * Returns: (transfer none): the event sequence that the event belongs to
2101  *
2102  * Since: 3.4
2103  */
2104 GdkEventSequence *
gdk_event_get_event_sequence(const GdkEvent * event)2105 gdk_event_get_event_sequence (const GdkEvent *event)
2106 {
2107   if (!event)
2108     return NULL;
2109 
2110   if (event->type == GDK_TOUCH_BEGIN ||
2111       event->type == GDK_TOUCH_UPDATE ||
2112       event->type == GDK_TOUCH_END ||
2113       event->type == GDK_TOUCH_CANCEL)
2114     return event->touch.sequence;
2115 
2116   return NULL;
2117 }
2118 
2119 /**
2120  * gdk_set_show_events:
2121  * @show_events:  %TRUE to output event debugging information.
2122  *
2123  * Sets whether a trace of received events is output.
2124  * Note that GTK+ must be compiled with debugging (that is,
2125  * configured using the `--enable-debug` option)
2126  * to use this option.
2127  **/
2128 void
gdk_set_show_events(gboolean show_events)2129 gdk_set_show_events (gboolean show_events)
2130 {
2131   if (show_events)
2132     _gdk_debug_flags |= GDK_DEBUG_EVENTS;
2133   else
2134     _gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
2135 }
2136 
2137 /**
2138  * gdk_get_show_events:
2139  *
2140  * Gets whether event debugging output is enabled.
2141  *
2142  * Returns: %TRUE if event debugging output is enabled.
2143  **/
2144 gboolean
gdk_get_show_events(void)2145 gdk_get_show_events (void)
2146 {
2147   return (_gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
2148 }
2149 
2150 static void
gdk_synthesize_click(GdkDisplay * display,GdkEvent * event,gint nclicks)2151 gdk_synthesize_click (GdkDisplay *display,
2152                       GdkEvent   *event,
2153                       gint        nclicks)
2154 {
2155   GdkEvent *event_copy;
2156 
2157   event_copy = gdk_event_copy (event);
2158   event_copy->type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2159 
2160   _gdk_event_queue_append (display, event_copy);
2161 }
2162 
2163 void
_gdk_event_button_generate(GdkDisplay * display,GdkEvent * event)2164 _gdk_event_button_generate (GdkDisplay *display,
2165 			    GdkEvent   *event)
2166 {
2167   GdkMultipleClickInfo *info;
2168   GdkDevice *source_device;
2169 
2170   g_return_if_fail (event->type == GDK_BUTTON_PRESS);
2171 
2172   source_device = gdk_event_get_source_device (event);
2173   info = g_hash_table_lookup (display->multiple_click_info, event->button.device);
2174 
2175   if (G_UNLIKELY (!info))
2176     {
2177       info = g_new0 (GdkMultipleClickInfo, 1);
2178       info->button_number[0] = info->button_number[1] = -1;
2179 
2180       g_hash_table_insert (display->multiple_click_info,
2181                            event->button.device, info);
2182     }
2183 
2184   if ((event->button.time < (info->button_click_time[1] + 2 * display->double_click_time)) &&
2185       (event->button.window == info->button_window[1]) &&
2186       (event->button.button == info->button_number[1]) &&
2187       (source_device == info->last_slave) &&
2188       (ABS (event->button.x - info->button_x[1]) <= display->double_click_distance) &&
2189       (ABS (event->button.y - info->button_y[1]) <= display->double_click_distance))
2190     {
2191       gdk_synthesize_click (display, event, 3);
2192 
2193       info->button_click_time[1] = 0;
2194       info->button_click_time[0] = 0;
2195       info->button_window[1] = NULL;
2196       info->button_window[0] = NULL;
2197       info->button_number[1] = -1;
2198       info->button_number[0] = -1;
2199       info->button_x[0] = info->button_x[1] = 0;
2200       info->button_y[0] = info->button_y[1] = 0;
2201       info->last_slave = NULL;
2202     }
2203   else if ((event->button.time < (info->button_click_time[0] + display->double_click_time)) &&
2204 	   (event->button.window == info->button_window[0]) &&
2205 	   (event->button.button == info->button_number[0]) &&
2206            (source_device == info->last_slave) &&
2207 	   (ABS (event->button.x - info->button_x[0]) <= display->double_click_distance) &&
2208 	   (ABS (event->button.y - info->button_y[0]) <= display->double_click_distance))
2209     {
2210       gdk_synthesize_click (display, event, 2);
2211 
2212       info->button_click_time[1] = info->button_click_time[0];
2213       info->button_click_time[0] = event->button.time;
2214       info->button_window[1] = info->button_window[0];
2215       info->button_window[0] = event->button.window;
2216       info->button_number[1] = info->button_number[0];
2217       info->button_number[0] = event->button.button;
2218       info->button_x[1] = info->button_x[0];
2219       info->button_x[0] = event->button.x;
2220       info->button_y[1] = info->button_y[0];
2221       info->button_y[0] = event->button.y;
2222       info->last_slave = source_device;
2223     }
2224   else
2225     {
2226       info->button_click_time[1] = 0;
2227       info->button_click_time[0] = event->button.time;
2228       info->button_window[1] = NULL;
2229       info->button_window[0] = event->button.window;
2230       info->button_number[1] = -1;
2231       info->button_number[0] = event->button.button;
2232       info->button_x[1] = 0;
2233       info->button_x[0] = event->button.x;
2234       info->button_y[1] = 0;
2235       info->button_y[0] = event->button.y;
2236       info->last_slave = source_device;
2237     }
2238 }
2239 
2240 static GList *
gdk_get_pending_window_state_event_link(GdkWindow * window)2241 gdk_get_pending_window_state_event_link (GdkWindow *window)
2242 {
2243   GdkDisplay *display = gdk_window_get_display (window);
2244   GList *tmp_list;
2245 
2246   for (tmp_list = display->queued_events; tmp_list; tmp_list = tmp_list->next)
2247     {
2248       GdkEventPrivate *event = tmp_list->data;
2249 
2250       if (event->event.type == GDK_WINDOW_STATE &&
2251           event->event.window_state.window == window)
2252         return tmp_list;
2253     }
2254 
2255   return NULL;
2256 }
2257 
2258 void
_gdk_set_window_state(GdkWindow * window,GdkWindowState new_state)2259 _gdk_set_window_state (GdkWindow      *window,
2260                        GdkWindowState  new_state)
2261 {
2262   GdkDisplay *display = gdk_window_get_display (window);
2263   GdkEvent temp_event;
2264   GdkWindowState old;
2265   GList *pending_event_link;
2266 
2267   g_return_if_fail (window != NULL);
2268 
2269   temp_event.window_state.window = window;
2270   temp_event.window_state.type = GDK_WINDOW_STATE;
2271   temp_event.window_state.send_event = FALSE;
2272   temp_event.window_state.new_window_state = new_state;
2273 
2274   if (temp_event.window_state.new_window_state == window->state)
2275     return; /* No actual work to do, nothing changed. */
2276 
2277   pending_event_link = gdk_get_pending_window_state_event_link (window);
2278   if (pending_event_link)
2279     {
2280       old = window->old_state;
2281       _gdk_event_queue_remove_link (display, pending_event_link);
2282       gdk_event_free (pending_event_link->data);
2283       g_list_free_1 (pending_event_link);
2284     }
2285   else
2286     {
2287       old = window->state;
2288       window->old_state = old;
2289     }
2290 
2291   temp_event.window_state.changed_mask = new_state ^ old;
2292 
2293   /* Actually update the field in GdkWindow, this is sort of an odd
2294    * place to do it, but seems like the safest since it ensures we expose no
2295    * inconsistent state to the user.
2296    */
2297 
2298   window->state = new_state;
2299 
2300   if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN)
2301     _gdk_window_update_viewable (window);
2302 
2303   /* We only really send the event to toplevels, since
2304    * all the window states don't apply to non-toplevels.
2305    * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
2306    * internally so we needed to update window->state.
2307    */
2308   switch (window->window_type)
2309     {
2310     case GDK_WINDOW_TOPLEVEL:
2311     case GDK_WINDOW_TEMP: /* ? */
2312       gdk_display_put_event (display, &temp_event);
2313       break;
2314     case GDK_WINDOW_FOREIGN:
2315     case GDK_WINDOW_ROOT:
2316     case GDK_WINDOW_CHILD:
2317       break;
2318     }
2319 }
2320 
2321 void
gdk_synthesize_window_state(GdkWindow * window,GdkWindowState unset_flags,GdkWindowState set_flags)2322 gdk_synthesize_window_state (GdkWindow     *window,
2323                              GdkWindowState unset_flags,
2324                              GdkWindowState set_flags)
2325 {
2326   g_return_if_fail (window != NULL);
2327 
2328   _gdk_set_window_state (window, (window->state | set_flags) & ~unset_flags);
2329 }
2330 
2331 /**
2332  * gdk_display_set_double_click_time:
2333  * @display: a #GdkDisplay
2334  * @msec: double click time in milliseconds (thousandths of a second)
2335  *
2336  * Sets the double click time (two clicks within this time interval
2337  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
2338  * Applications should not set this, it is a global
2339  * user-configured setting.
2340  *
2341  * Since: 2.2
2342  **/
2343 void
gdk_display_set_double_click_time(GdkDisplay * display,guint msec)2344 gdk_display_set_double_click_time (GdkDisplay *display,
2345 				   guint       msec)
2346 {
2347   display->double_click_time = msec;
2348 }
2349 
2350 /**
2351  * gdk_set_double_click_time:
2352  * @msec: double click time in milliseconds (thousandths of a second)
2353  *
2354  * Set the double click time for the default display. See
2355  * gdk_display_set_double_click_time().
2356  * See also gdk_display_set_double_click_distance().
2357  * Applications should not set this, it is a
2358  * global user-configured setting.
2359  **/
2360 void
gdk_set_double_click_time(guint msec)2361 gdk_set_double_click_time (guint msec)
2362 {
2363   gdk_display_set_double_click_time (gdk_display_get_default (), msec);
2364 }
2365 
2366 /**
2367  * gdk_display_set_double_click_distance:
2368  * @display: a #GdkDisplay
2369  * @distance: distance in pixels
2370  *
2371  * Sets the double click distance (two clicks within this distance
2372  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
2373  * See also gdk_display_set_double_click_time().
2374  * Applications should not set this, it is a global
2375  * user-configured setting.
2376  *
2377  * Since: 2.4
2378  **/
2379 void
gdk_display_set_double_click_distance(GdkDisplay * display,guint distance)2380 gdk_display_set_double_click_distance (GdkDisplay *display,
2381 				       guint       distance)
2382 {
2383   display->double_click_distance = distance;
2384 }
2385 
G_DEFINE_BOXED_TYPE(GdkEvent,gdk_event,gdk_event_copy,gdk_event_free)2386 G_DEFINE_BOXED_TYPE (GdkEvent, gdk_event,
2387                      gdk_event_copy,
2388                      gdk_event_free)
2389 
2390 static GdkEventSequence *
2391 gdk_event_sequence_copy (GdkEventSequence *sequence)
2392 {
2393   return sequence;
2394 }
2395 
2396 static void
gdk_event_sequence_free(GdkEventSequence * sequence)2397 gdk_event_sequence_free (GdkEventSequence *sequence)
2398 {
2399   /* Nothing to free here */
2400 }
2401 
G_DEFINE_BOXED_TYPE(GdkEventSequence,gdk_event_sequence,gdk_event_sequence_copy,gdk_event_sequence_free)2402 G_DEFINE_BOXED_TYPE (GdkEventSequence, gdk_event_sequence,
2403                      gdk_event_sequence_copy,
2404                      gdk_event_sequence_free)
2405 
2406 /**
2407  * gdk_setting_get:
2408  * @name: the name of the setting.
2409  * @value: location to store the value of the setting.
2410  *
2411  * Obtains a desktop-wide setting, such as the double-click time,
2412  * for the default screen. See gdk_screen_get_setting().
2413  *
2414  * Returns: %TRUE if the setting existed and a value was stored
2415  *   in @value, %FALSE otherwise.
2416  **/
2417 gboolean
2418 gdk_setting_get (const gchar *name,
2419 		 GValue      *value)
2420 {
2421   return gdk_screen_get_setting (gdk_screen_get_default (), name, value);
2422 }
2423 
2424 /**
2425  * gdk_event_get_event_type:
2426  * @event: a #GdkEvent
2427  *
2428  * Retrieves the type of the event.
2429  *
2430  * Returns: a #GdkEventType
2431  *
2432  * Since: 3.10
2433  */
2434 GdkEventType
gdk_event_get_event_type(const GdkEvent * event)2435 gdk_event_get_event_type (const GdkEvent *event)
2436 {
2437   g_return_val_if_fail (event != NULL, GDK_NOTHING);
2438 
2439   return event->type;
2440 }
2441 
2442 /**
2443  * gdk_event_get_seat:
2444  * @event: a #GdkEvent
2445  *
2446  * Returns the #GdkSeat this event was generated for.
2447  *
2448  * Returns: (transfer none): The #GdkSeat of this event
2449  *
2450  * Since: 3.20
2451  **/
2452 GdkSeat *
gdk_event_get_seat(const GdkEvent * event)2453 gdk_event_get_seat (const GdkEvent *event)
2454 {
2455   const GdkEventPrivate *priv;
2456 
2457   if (!gdk_event_is_allocated (event))
2458     return NULL;
2459 
2460   priv = (const GdkEventPrivate *) event;
2461 
2462   if (!priv->seat)
2463     {
2464       GdkDevice *device;
2465 
2466       g_warning ("Event with type %d not holding a GdkSeat. "
2467                  "It is most likely synthesized outside Gdk/GTK+",
2468                  event->type);
2469 
2470       device = gdk_event_get_device (event);
2471 
2472       return device ? gdk_device_get_seat (device) : NULL;
2473     }
2474 
2475   return priv->seat;
2476 }
2477 
2478 void
gdk_event_set_seat(GdkEvent * event,GdkSeat * seat)2479 gdk_event_set_seat (GdkEvent *event,
2480                     GdkSeat  *seat)
2481 {
2482   GdkEventPrivate *priv;
2483 
2484   if (gdk_event_is_allocated (event))
2485     {
2486       priv = (GdkEventPrivate *) event;
2487       priv->seat = seat;
2488     }
2489 }
2490 
2491 /**
2492  * gdk_event_get_device_tool:
2493  * @event: a #GdkEvent
2494  *
2495  * If the event was generated by a device that supports
2496  * different tools (eg. a tablet), this function will
2497  * return a #GdkDeviceTool representing the tool that
2498  * caused the event. Otherwise, %NULL will be returned.
2499  *
2500  * Note: the #GdkDeviceTool<!-- -->s will be constant during
2501  * the application lifetime, if settings must be stored
2502  * persistently across runs, see gdk_device_tool_get_serial()
2503  *
2504  * Returns: (transfer none): The current device tool, or %NULL
2505  *
2506  * Since: 3.22
2507  **/
2508 GdkDeviceTool *
gdk_event_get_device_tool(const GdkEvent * event)2509 gdk_event_get_device_tool (const GdkEvent *event)
2510 {
2511   GdkEventPrivate *private;
2512 
2513   if (!gdk_event_is_allocated (event))
2514     return NULL;
2515 
2516   private = (GdkEventPrivate *) event;
2517   return private->tool;
2518 }
2519 
2520 /**
2521  * gdk_event_set_device_tool:
2522  * @event: a #GdkEvent
2523  * @tool: (nullable): tool to set on the event, or %NULL
2524  *
2525  * Sets the device tool for this event, should be rarely used.
2526  *
2527  * Since: 3.22
2528  **/
2529 void
gdk_event_set_device_tool(GdkEvent * event,GdkDeviceTool * tool)2530 gdk_event_set_device_tool (GdkEvent      *event,
2531                            GdkDeviceTool *tool)
2532 {
2533   GdkEventPrivate *private;
2534 
2535   if (!gdk_event_is_allocated (event))
2536     return;
2537 
2538   private = (GdkEventPrivate *) event;
2539   private->tool = tool;
2540 }
2541 
2542 void
gdk_event_set_scancode(GdkEvent * event,guint16 scancode)2543 gdk_event_set_scancode (GdkEvent *event,
2544                         guint16 scancode)
2545 {
2546   GdkEventPrivate *private = (GdkEventPrivate *) event;
2547 
2548   private->key_scancode = scancode;
2549 }
2550 
2551 /**
2552  * gdk_event_get_scancode:
2553  * @event: a #GdkEvent
2554  *
2555  * Gets the keyboard low-level scancode of a key event.
2556  *
2557  * This is usually hardware_keycode. On Windows this is the high
2558  * word of WM_KEY{DOWN,UP} lParam which contains the scancode and
2559  * some extended flags.
2560  *
2561  * Returns: The associated keyboard scancode or 0
2562  *
2563  * Since: 3.22
2564  **/
2565 int
gdk_event_get_scancode(GdkEvent * event)2566 gdk_event_get_scancode (GdkEvent *event)
2567 {
2568   GdkEventPrivate *private;
2569 
2570   if (!gdk_event_is_allocated (event))
2571     return 0;
2572 
2573   private = (GdkEventPrivate *) event;
2574   return private->key_scancode;
2575 }