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
51typedef struct _GdkIOClosure GdkIOClosure;
52
53struct _GdkIOClosure
54{
55 GDestroyNotify notify;
56 gpointer data;
57};
58
59/* Private variable declarations
60 */
61
62static GdkEventFunc _gdk_event_func = NULL; /* Callback for events */
63static gpointer _gdk_event_data = NULL;
64static GDestroyNotify _gdk_event_notify = NULL;
65
66void
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 **/
93GList*
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 **/
133GList *
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 */
160GList*
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 */
188GList*
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 **/
211void
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 **/
236GdkEvent*
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
254void
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
314void
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 **/
340void
341gdk_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 */
360gboolean
361gdk_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 **/
403GdkEvent*
404gdk_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 **/
433GdkEvent*
434gdk_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
453static GdkDisplay *
454event_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 **/
470void
471gdk_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
482static 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 **/
495GdkEvent*
496gdk_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
588static gboolean
589gdk_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
597void
598gdk_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 */
623gboolean
624gdk_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 **/
642GdkEvent*
643gdk_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
668 switch (event->any.type)
669 {
670 case GDK_KEY_PRESS:
671 case GDK_KEY_RELEASE:
672 new_event->key.string = g_strdup (event->key.string);
673 break;
674
675 case GDK_ENTER_NOTIFY:
676 case GDK_LEAVE_NOTIFY:
677 if (event->crossing.subwindow != NULL)
678 g_object_ref (event->crossing.subwindow);
679 break;
680
681 case GDK_DRAG_ENTER:
682 case GDK_DRAG_LEAVE:
683 case GDK_DRAG_MOTION:
684 case GDK_DRAG_STATUS:
685 case GDK_DROP_START:
686 case GDK_DROP_FINISHED:
687 g_object_ref (event->dnd.context);
688 break;
689
690 case GDK_EXPOSE:
691 case GDK_DAMAGE:
692 if (event->expose.region)
693 new_event->expose.region = cairo_region_copy (event->expose.region);
694 break;
695
696 case GDK_SETTING:
697 new_event->setting.name = g_strdup (new_event->setting.name);
698 break;
699
700 case GDK_BUTTON_PRESS:
701 case GDK_2BUTTON_PRESS:
702 case GDK_3BUTTON_PRESS:
703 case GDK_BUTTON_RELEASE:
704 if (event->button.axes)
705 new_event->button.axes = g_memdup (event->button.axes,
706 sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
707 break;
708
709 case GDK_TOUCH_BEGIN:
710 case GDK_TOUCH_UPDATE:
711 case GDK_TOUCH_END:
712 case GDK_TOUCH_CANCEL:
713 if (event->touch.axes)
714 new_event->touch.axes = g_memdup (event->touch.axes,
715 sizeof (gdouble) * gdk_device_get_n_axes (event->touch.device));
716 break;
717
718 case GDK_MOTION_NOTIFY:
719 if (event->motion.axes)
720 new_event->motion.axes = g_memdup (event->motion.axes,
721 sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
722 break;
723
724 case GDK_OWNER_CHANGE:
725 new_event->owner_change.owner = event->owner_change.owner;
726 if (new_event->owner_change.owner)
727 g_object_ref (new_event->owner_change.owner);
728 break;
729
730 case GDK_SELECTION_CLEAR:
731 case GDK_SELECTION_NOTIFY:
732 case GDK_SELECTION_REQUEST:
733 new_event->selection.requestor = event->selection.requestor;
734 if (new_event->selection.requestor)
735 g_object_ref (new_event->selection.requestor);
736 break;
737
738 default:
739 break;
740 }
741
742 if (gdk_event_is_allocated (event))
743 _gdk_display_event_data_copy (event_get_display (event), event, new_event);
744
745 return new_event;
746}
747
748/**
749 * gdk_event_free:
750 * @event: a #GdkEvent.
751 *
752 * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
753 * Note that this function should only be called with events returned from
754 * functions such as gdk_event_peek(), gdk_event_get(), gdk_event_copy()
755 * and gdk_event_new().
756 **/
757void
758gdk_event_free (GdkEvent *event)
759{
760 GdkEventPrivate *private;
761 GdkDisplay *display;
762
763 g_return_if_fail (event != NULL);
764
765 if (gdk_event_is_allocated (event))
766 {
767 private = (GdkEventPrivate *) event;
768 g_clear_object (&private->device);
769 g_clear_object (&private->source_device);
770 }
771
772 switch (event->any.type)
773 {
774 case GDK_KEY_PRESS:
775 case GDK_KEY_RELEASE:
776 g_free (event->key.string);
777 break;
778
779 case GDK_ENTER_NOTIFY:
780 case GDK_LEAVE_NOTIFY:
781 if (event->crossing.subwindow != NULL)
782 g_object_unref (event->crossing.subwindow);
783 break;
784
785 case GDK_DRAG_ENTER:
786 case GDK_DRAG_LEAVE:
787 case GDK_DRAG_MOTION:
788 case GDK_DRAG_STATUS:
789 case GDK_DROP_START:
790 case GDK_DROP_FINISHED:
791 if (event->dnd.context != NULL)
792 g_object_unref (event->dnd.context);
793 break;
794
795 case GDK_BUTTON_PRESS:
796 case GDK_2BUTTON_PRESS:
797 case GDK_3BUTTON_PRESS:
798 case GDK_BUTTON_RELEASE:
799 g_free (event->button.axes);
800 break;
801
802 case GDK_TOUCH_BEGIN:
803 case GDK_TOUCH_UPDATE:
804 case GDK_TOUCH_END:
805 case GDK_TOUCH_CANCEL:
806 g_free (event->touch.axes);
807 break;
808
809 case GDK_EXPOSE:
810 case GDK_DAMAGE:
811 if (event->expose.region)
812 cairo_region_destroy (event->expose.region);
813 break;
814
815 case GDK_MOTION_NOTIFY:
816 g_free (event->motion.axes);
817 break;
818
819 case GDK_SETTING:
820 g_free (event->setting.name);
821 break;
822
823 case GDK_OWNER_CHANGE:
824 if (event->owner_change.owner)
825 g_object_unref (event->owner_change.owner);
826 break;
827
828 case GDK_SELECTION_CLEAR:
829 case GDK_SELECTION_NOTIFY:
830 case GDK_SELECTION_REQUEST:
831 if (event->selection.requestor)
832 g_object_unref (event->selection.requestor);
833 break;
834
835 default:
836 break;
837 }
838
839 display = event_get_display (event);
840 if (display)
841 _gdk_display_event_data_free (display, event);
842
843 if (event->any.window)
844 g_object_unref (event->any.window);
845
846 g_hash_table_remove (event_hash, event);
847 g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
848}
849
850/**
851 * gdk_event_get_window:
852 * @event: a #GdkEvent
853 *
854 * Extracts the #GdkWindow associated with an event.
855 *
856 * Returns: (transfer none): The #GdkWindow associated with the event
857 *
858 * Since: 3.10
859 */
860GdkWindow *
861gdk_event_get_window (const GdkEvent *event)
862{
863 g_return_val_if_fail (event != NULL, NULL);
864
865 return event->any.window;
866}
867
868/**
869 * gdk_event_get_time:
870 * @event: a #GdkEvent
871 *
872 * Returns the time stamp from @event, if there is one; otherwise
873 * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
874 *
875 * Returns: time stamp field from @event
876 **/
877guint32
878gdk_event_get_time (const GdkEvent *event)
879{
880 if (event)
881 switch (event->type)
882 {
883 case GDK_MOTION_NOTIFY:
884 return event->motion.time;
885 case GDK_BUTTON_PRESS:
886 case GDK_2BUTTON_PRESS:
887 case GDK_3BUTTON_PRESS:
888 case GDK_BUTTON_RELEASE:
889 return event->button.time;
890 case GDK_TOUCH_BEGIN:
891 case GDK_TOUCH_UPDATE:
892 case GDK_TOUCH_END:
893 case GDK_TOUCH_CANCEL:
894 return event->touch.time;
895 case GDK_TOUCHPAD_SWIPE:
896 return event->touchpad_swipe.time;
897 case GDK_TOUCHPAD_PINCH:
898 return event->touchpad_pinch.time;
899 case GDK_SCROLL:
900 return event->scroll.time;
901 case GDK_KEY_PRESS:
902 case GDK_KEY_RELEASE:
903 return event->key.time;
904 case GDK_ENTER_NOTIFY:
905 case GDK_LEAVE_NOTIFY:
906 return event->crossing.time;
907 case GDK_PROPERTY_NOTIFY:
908 return event->property.time;
909 case GDK_SELECTION_CLEAR:
910 case GDK_SELECTION_REQUEST:
911 case GDK_SELECTION_NOTIFY:
912 return event->selection.time;
913 case GDK_PROXIMITY_IN:
914 case GDK_PROXIMITY_OUT:
915 return event->proximity.time;
916 case GDK_DRAG_ENTER:
917 case GDK_DRAG_LEAVE:
918 case GDK_DRAG_MOTION:
919 case GDK_DRAG_STATUS:
920 case GDK_DROP_START:
921 case GDK_DROP_FINISHED:
922 return event->dnd.time;
923 case GDK_CLIENT_EVENT:
924 case GDK_VISIBILITY_NOTIFY:
925 case GDK_CONFIGURE:
926 case GDK_FOCUS_CHANGE:
927 case GDK_NOTHING:
928 case GDK_DAMAGE:
929 case GDK_DELETE:
930 case GDK_DESTROY:
931 case GDK_EXPOSE:
932 case GDK_MAP:
933 case GDK_UNMAP:
934 case GDK_WINDOW_STATE:
935 case GDK_SETTING:
936 case GDK_OWNER_CHANGE:
937 case GDK_GRAB_BROKEN:
938 case GDK_EVENT_LAST:
939 /* return current time */
940 break;
941 }
942
943 return GDK_CURRENT_TIME;
944}
945
946/**
947 * gdk_event_get_state:
948 * @event: (allow-none): a #GdkEvent or %NULL
949 * @state: (out): return location for state
950 *
951 * If the event contains a “state” field, puts that field in @state. Otherwise
952 * stores an empty state (0). Returns %TRUE if there was a state field
953 * in the event. @event may be %NULL, in which case it’s treated
954 * as if the event had no state field.
955 *
956 * Returns: %TRUE if there was a state field in the event
957 **/
958gboolean
959gdk_event_get_state (const GdkEvent *event,
960 GdkModifierType *state)
961{
962 g_return_val_if_fail (state != NULL, FALSE);
963
964 if (event)
965 switch (event->type)
966 {
967 case GDK_MOTION_NOTIFY:
968 *state = event->motion.state;
969 return TRUE;
970 case GDK_BUTTON_PRESS:
971 case GDK_2BUTTON_PRESS:
972 case GDK_3BUTTON_PRESS:
973 case GDK_BUTTON_RELEASE:
974 *state = event->button.state;
975 return TRUE;
976 case GDK_TOUCH_BEGIN:
977 case GDK_TOUCH_UPDATE:
978 case GDK_TOUCH_END:
979 case GDK_TOUCH_CANCEL:
980 *state = event->touch.state;
981 return TRUE;
982 case GDK_TOUCHPAD_SWIPE:
983 *state = event->touchpad_swipe.state;
984 return TRUE;
985 case GDK_TOUCHPAD_PINCH:
986 *state = event->touchpad_pinch.state;
987 return TRUE;
988 case GDK_SCROLL:
989 *state = event->scroll.state;
990 return TRUE;
991 case GDK_KEY_PRESS:
992 case GDK_KEY_RELEASE:
993 *state = event->key.state;
994 return TRUE;
995 case GDK_ENTER_NOTIFY:
996 case GDK_LEAVE_NOTIFY:
997 *state = event->crossing.state;
998 return TRUE;
999 case GDK_PROPERTY_NOTIFY:
1000 case GDK_VISIBILITY_NOTIFY:
1001 case GDK_CLIENT_EVENT:
1002 case GDK_CONFIGURE:
1003 case GDK_FOCUS_CHANGE:
1004 case GDK_SELECTION_CLEAR:
1005 case GDK_SELECTION_REQUEST:
1006 case GDK_SELECTION_NOTIFY:
1007 case GDK_PROXIMITY_IN:
1008 case GDK_PROXIMITY_OUT:
1009 case GDK_DAMAGE:
1010 case GDK_DRAG_ENTER:
1011 case GDK_DRAG_LEAVE:
1012 case GDK_DRAG_MOTION:
1013 case GDK_DRAG_STATUS:
1014 case GDK_DROP_START:
1015 case GDK_DROP_FINISHED:
1016 case GDK_NOTHING:
1017 case GDK_DELETE:
1018 case GDK_DESTROY:
1019 case GDK_EXPOSE:
1020 case GDK_MAP:
1021 case GDK_UNMAP:
1022 case GDK_WINDOW_STATE:
1023 case GDK_SETTING:
1024 case GDK_OWNER_CHANGE:
1025 case GDK_GRAB_BROKEN:
1026 case GDK_EVENT_LAST:
1027 /* no state field */
1028 break;
1029 }
1030
1031 *state = 0;
1032 return FALSE;
1033}
1034
1035/**
1036 * gdk_event_get_coords:
1037 * @event: a #GdkEvent
1038 * @x_win: (out) (optional): location to put event window x coordinate
1039 * @y_win: (out) (optional): location to put event window y coordinate
1040 *
1041 * Extract the event window relative x/y coordinates from an event.
1042 *
1043 * Returns: %TRUE if the event delivered event window coordinates
1044 **/
1045gboolean
1046gdk_event_get_coords (const GdkEvent *event,
1047 gdouble *x_win,
1048 gdouble *y_win)
1049{
1050 gdouble x = 0, y = 0;
1051 gboolean fetched = TRUE;
1052
1053 g_return_val_if_fail (event != NULL, FALSE);
1054
1055 switch (event->type)
1056 {
1057 case GDK_CONFIGURE:
1058 x = event->configure.x;
1059 y = event->configure.y;
1060 break;
1061 case GDK_ENTER_NOTIFY:
1062 case GDK_LEAVE_NOTIFY:
1063 x = event->crossing.x;
1064 y = event->crossing.y;
1065 break;
1066 case GDK_SCROLL:
1067 x = event->scroll.x;
1068 y = event->scroll.y;
1069 break;
1070 case GDK_BUTTON_PRESS:
1071 case GDK_2BUTTON_PRESS:
1072 case GDK_3BUTTON_PRESS:
1073 case GDK_BUTTON_RELEASE:
1074 x = event->button.x;
1075 y = event->button.y;
1076 break;
1077 case GDK_TOUCH_BEGIN:
1078 case GDK_TOUCH_UPDATE:
1079 case GDK_TOUCH_END:
1080 case GDK_TOUCH_CANCEL:
1081 x = event->touch.x;
1082 y = event->touch.y;
1083 break;
1084 case GDK_MOTION_NOTIFY:
1085 x = event->motion.x;
1086 y = event->motion.y;
1087 break;
1088 case GDK_TOUCHPAD_SWIPE:
1089 x = event->touchpad_swipe.x;
1090 y = event->touchpad_swipe.y;
1091 break;
1092 case GDK_TOUCHPAD_PINCH:
1093 x = event->touchpad_pinch.x;
1094 y = event->touchpad_pinch.y;
1095 break;
1096 default:
1097 fetched = FALSE;
1098 break;
1099 }
1100
1101 if (x_win)
1102 *x_win = x;
1103 if (y_win)
1104 *y_win = y;
1105
1106 return fetched;
1107}
1108
1109/**
1110 * gdk_event_get_root_coords:
1111 * @event: a #GdkEvent
1112 * @x_root: (out) (optional): location to put root window x coordinate
1113 * @y_root: (out) (optional): location to put root window y coordinate
1114 *
1115 * Extract the root window relative x/y coordinates from an event.
1116 *
1117 * Returns: %TRUE if the event delivered root window coordinates
1118 **/
1119gboolean
1120gdk_event_get_root_coords (const GdkEvent *event,
1121 gdouble *x_root,
1122 gdouble *y_root)
1123{
1124 gdouble x = 0, y = 0;
1125 gboolean fetched = TRUE;
1126
1127 g_return_val_if_fail (event != NULL, FALSE);
1128
1129 switch (event->type)
1130 {
1131 case GDK_MOTION_NOTIFY:
1132 x = event->motion.x_root;
1133 y = event->motion.y_root;
1134 break;
1135 case GDK_SCROLL:
1136 x = event->scroll.x_root;
1137 y = event->scroll.y_root;
1138 break;
1139 case GDK_BUTTON_PRESS:
1140 case GDK_2BUTTON_PRESS:
1141 case GDK_3BUTTON_PRESS:
1142 case GDK_BUTTON_RELEASE:
1143 x = event->button.x_root;
1144 y = event->button.y_root;
1145 break;
1146 case GDK_TOUCH_BEGIN:
1147 case GDK_TOUCH_UPDATE:
1148 case GDK_TOUCH_END:
1149 case GDK_TOUCH_CANCEL:
1150 x = event->touch.x_root;
1151 y = event->touch.y_root;
1152 break;
1153 case GDK_ENTER_NOTIFY:
1154 case GDK_LEAVE_NOTIFY:
1155 x = event->crossing.x_root;
1156 y = event->crossing.y_root;
1157 break;
1158 case GDK_DRAG_ENTER:
1159 case GDK_DRAG_LEAVE:
1160 case GDK_DRAG_MOTION:
1161 case GDK_DRAG_STATUS:
1162 case GDK_DROP_START:
1163 case GDK_DROP_FINISHED:
1164 x = event->dnd.x_root;
1165 y = event->dnd.y_root;
1166 break;
1167 case GDK_TOUCHPAD_SWIPE:
1168 x = event->touchpad_swipe.x_root;
1169 y = event->touchpad_swipe.y_root;
1170 break;
1171 case GDK_TOUCHPAD_PINCH:
1172 x = event->touchpad_pinch.x_root;
1173 y = event->touchpad_pinch.y_root;
1174 break;
1175 default:
1176 fetched = FALSE;
1177 break;
1178 }
1179
1180 if (x_root)
1181 *x_root = x;
1182 if (y_root)
1183 *y_root = y;
1184
1185 return fetched;
1186}
1187
1188/**
1189 * gdk_event_get_button:
1190 * @event: a #GdkEvent
1191 * @button: (out): location to store mouse button number
1192 *
1193 * Extract the button number from an event.
1194 *
1195 * Returns: %TRUE if the event delivered a button number
1196 *
1197 * Since: 3.2
1198 **/
1199gboolean
1200gdk_event_get_button (const GdkEvent *event,
1201 guint *button)
1202{
1203 gboolean fetched = TRUE;
1204 guint number = 0;
1205
1206 g_return_val_if_fail (event != NULL, FALSE);
1207
1208 switch (event->type)
1209 {
1210 case GDK_BUTTON_PRESS:
1211 case GDK_2BUTTON_PRESS:
1212 case GDK_3BUTTON_PRESS:
1213 case GDK_BUTTON_RELEASE:
1214 number = event->button.button;
1215 break;
1216 default:
1217 fetched = FALSE;
1218 break;
1219 }
1220
1221 if (button)
1222 *button = number;
1223
1224 return fetched;
1225}
1226
1227/**
1228 * gdk_event_get_click_count:
1229 * @event: a #GdkEvent
1230 * @click_count: (out): location to store click count
1231 *
1232 * Extracts the click count from an event.
1233 *
1234 * Returns: %TRUE if the event delivered a click count
1235 *
1236 * Since: 3.2
1237 */
1238gboolean
1239gdk_event_get_click_count (const GdkEvent *event,
1240 guint *click_count)
1241{
1242 gboolean fetched = TRUE;
1243 guint number = 0;
1244
1245 g_return_val_if_fail (event != NULL, FALSE);
1246
1247 switch (event->type)
1248 {
1249 case GDK_BUTTON_PRESS:
1250 case GDK_BUTTON_RELEASE:
1251 number = 1;
1252 break;
1253 case GDK_2BUTTON_PRESS:
1254 number = 2;
1255 break;
1256 case GDK_3BUTTON_PRESS:
1257 number = 3;
1258 break;
1259 default:
1260 fetched = FALSE;
1261 break;
1262 }
1263
1264 if (click_count)
1265 *click_count = number;
1266
1267 return fetched;
1268}
1269
1270/**
1271 * gdk_event_get_keyval:
1272 * @event: a #GdkEvent
1273 * @keyval: (out): location to store the keyval
1274 *
1275 * Extracts the keyval from an event.
1276 *
1277 * Returns: %TRUE if the event delivered a key symbol
1278 *
1279 * Since: 3.2
1280 */
1281gboolean
1282gdk_event_get_keyval (const GdkEvent *event,
1283 guint *keyval)
1284{
1285 gboolean fetched = TRUE;
1286 guint number = 0;
1287
1288 switch (event->type)
1289 {
1290 case GDK_KEY_PRESS:
1291 case GDK_KEY_RELEASE:
1292 number = event->key.keyval;
1293 break;
1294 default:
1295 fetched = FALSE;
1296 break;
1297 }
1298
1299 if (keyval)
1300 *keyval = number;
1301
1302 return fetched;
1303}
1304
1305/**
1306 * gdk_event_get_keycode:
1307 * @event: a #GdkEvent
1308 * @keycode: (out): location to store the keycode
1309 *
1310 * Extracts the hardware keycode from an event.
1311 *
1312 * Also see gdk_event_get_scancode().
1313 *
1314 * Returns: %TRUE if the event delivered a hardware keycode
1315 *
1316 * Since: 3.2
1317 */
1318gboolean
1319gdk_event_get_keycode (const GdkEvent *event,
1320 guint16 *keycode)
1321{
1322 gboolean fetched = TRUE;
1323 guint16 number = 0;
1324
1325 switch (event->type)
1326 {
1327 case GDK_KEY_PRESS:
1328 case GDK_KEY_RELEASE:
1329 number = event->key.hardware_keycode;
1330 break;
1331 default:
1332 fetched = FALSE;
1333 break;
1334 }
1335
1336 if (keycode)
1337 *keycode = number;
1338
1339 return fetched;
1340}
1341
1342/**
1343 * gdk_event_get_scroll_direction:
1344 * @event: a #GdkEvent
1345 * @direction: (out): location to store the scroll direction
1346 *
1347 * Extracts the scroll direction from an event.
1348 *
1349 * Returns: %TRUE if the event delivered a scroll direction
1350 *
1351 * Since: 3.2
1352 */
1353gboolean
1354gdk_event_get_scroll_direction (const GdkEvent *event,
1355 GdkScrollDirection *direction)
1356{
1357 gboolean fetched = TRUE;
1358 GdkScrollDirection dir = 0;
1359
1360 switch (event->type)
1361 {
1362 case GDK_SCROLL:
1363 if (event->scroll.direction == GDK_SCROLL_SMOOTH)
1364 fetched = FALSE;
1365 else
1366 dir = event->scroll.direction;
1367 break;
1368 default:
1369 fetched = FALSE;
1370 break;
1371 }
1372
1373 if (direction)
1374 *direction = dir;
1375
1376 return fetched;
1377}
1378
1379/**
1380 * gdk_event_get_scroll_deltas:
1381 * @event: a #GdkEvent
1382 * @delta_x: (out): return location for X delta
1383 * @delta_y: (out): return location for Y delta
1384 *
1385 * Retrieves the scroll deltas from a #GdkEvent
1386 *
1387 * Returns: %TRUE if the event contains smooth scroll information
1388 *
1389 * Since: 3.4
1390 **/
1391gboolean
1392gdk_event_get_scroll_deltas (const GdkEvent *event,
1393 gdouble *delta_x,
1394 gdouble *delta_y)
1395{
1396 gboolean fetched = TRUE;
1397 gdouble dx = 0.0;
1398 gdouble dy = 0.0;
1399
1400 switch (event->type)
1401 {
1402 case GDK_SCROLL:
1403 if (event->scroll.direction == GDK_SCROLL_SMOOTH)
1404 {
1405 dx = event->scroll.delta_x;
1406 dy = event->scroll.delta_y;
1407 }
1408 else
1409 fetched = FALSE;
1410 break;
1411 default:
1412 fetched = FALSE;
1413 break;
1414 }
1415
1416 if (delta_x)
1417 *delta_x = dx;
1418
1419 if (delta_y)
1420 *delta_y = dy;
1421
1422 return fetched;
1423}
1424
1425/**
1426 * gdk_event_is_scroll_stop_event
1427 * @event: a #GdkEvent
1428 *
1429 * Check whether a scroll event is a stop scroll event. Scroll sequences
1430 * with smooth scroll information may provide a stop scroll event once the
1431 * interaction with the device finishes, e.g. by lifting a finger. This
1432 * stop scroll event is the signal that a widget may trigger kinetic
1433 * scrolling based on the current velocity.
1434 *
1435 * Stop scroll events always have a a delta of 0/0.
1436 *
1437 * Returns: %TRUE if the event is a scroll stop event
1438 *
1439 * Since: 3.20
1440 */
1441gboolean
1442gdk_event_is_scroll_stop_event (const GdkEvent *event)
1443{
1444 return event->scroll.is_stop;
1445}
1446
1447/**
1448 * gdk_event_get_axis:
1449 * @event: a #GdkEvent
1450 * @axis_use: the axis use to look for
1451 * @value: (out): location to store the value found
1452 *
1453 * Extract the axis value for a particular axis use from
1454 * an event structure.
1455 *
1456 * Returns: %TRUE if the specified axis was found, otherwise %FALSE
1457 **/
1458gboolean
1459gdk_event_get_axis (const GdkEvent *event,
1460 GdkAxisUse axis_use,
1461 gdouble *value)
1462{
1463 gdouble *axes;
1464 GdkDevice *device;
1465
1466 g_return_val_if_fail (event != NULL, FALSE);
1467
1468 if (axis_use == GDK_AXIS_X || axis_use == GDK_AXIS_Y)
1469 {
1470 gdouble x, y;
1471
1472 switch (event->type)
1473 {
1474 case GDK_MOTION_NOTIFY:
1475 x = event->motion.x;
1476 y = event->motion.y;
1477 break;
1478 case GDK_SCROLL:
1479 x = event->scroll.x;
1480 y = event->scroll.y;
1481 break;
1482 case GDK_BUTTON_PRESS:
1483 case GDK_BUTTON_RELEASE:
1484 x = event->button.x;
1485 y = event->button.y;
1486 break;
1487 case GDK_TOUCH_BEGIN:
1488 case GDK_TOUCH_UPDATE:
1489 case GDK_TOUCH_END:
1490 case GDK_TOUCH_CANCEL:
1491 x = event->touch.x;
1492 y = event->touch.y;
1493 break;
1494 case GDK_ENTER_NOTIFY:
1495 case GDK_LEAVE_NOTIFY:
1496 x = event->crossing.x;
1497 y = event->crossing.y;
1498 break;
1499
1500 default:
1501 return FALSE;
1502 }
1503
1504 if (axis_use == GDK_AXIS_X && value)
1505 *value = x;
1506 if (axis_use == GDK_AXIS_Y && value)
1507 *value = y;
1508
1509 return TRUE;
1510 }
1511 else if (event->type == GDK_BUTTON_PRESS ||
1512 event->type == GDK_BUTTON_RELEASE)
1513 {
1514 device = event->button.device;
1515 axes = event->button.axes;
1516 }
1517 else if (event->type == GDK_TOUCH_BEGIN ||
1518 event->type == GDK_TOUCH_UPDATE ||
1519 event->type == GDK_TOUCH_END ||
1520 event->type == GDK_TOUCH_CANCEL)
1521 {
1522 device = event->touch.device;
1523 axes = event->touch.axes;
1524 }
1525 else if (event->type == GDK_MOTION_NOTIFY)
1526 {
1527 device = event->motion.device;
1528 axes = event->motion.axes;
1529 }
1530 else
1531 return FALSE;
1532
1533 return gdk_device_get_axis (device, axes, axis_use, value);
1534}
1535
1536/**
1537 * gdk_event_set_device:
1538 * @event: a #GdkEvent
1539 * @device: a #GdkDevice
1540 *
1541 * Sets the device for @event to @device. The event must
1542 * have been allocated by GTK+, for instance, by
1543 * gdk_event_copy().
1544 *
1545 * Since: 3.0
1546 **/
1547void
1548gdk_event_set_device (GdkEvent *event,
1549 GdkDevice *device)
1550{
1551 GdkEventPrivate *private;
1552
1553 g_return_if_fail (gdk_event_is_allocated (event));
1554
1555 private = (GdkEventPrivate *) event;
1556
1557 g_set_object (&private->device, device);
1558
1559 switch (event->type)
1560 {
1561 case GDK_MOTION_NOTIFY:
1562 event->motion.device = device;
1563 break;
1564 case GDK_BUTTON_PRESS:
1565 case GDK_2BUTTON_PRESS:
1566 case GDK_3BUTTON_PRESS:
1567 case GDK_BUTTON_RELEASE:
1568 event->button.device = device;
1569 break;
1570 case GDK_TOUCH_BEGIN:
1571 case GDK_TOUCH_UPDATE:
1572 case GDK_TOUCH_END:
1573 case GDK_TOUCH_CANCEL:
1574 event->touch.device = device;
1575 break;
1576 case GDK_SCROLL:
1577 event->scroll.device = device;
1578 break;
1579 case GDK_PROXIMITY_IN:
1580 case GDK_PROXIMITY_OUT:
1581 event->proximity.device = device;
1582 break;
1583 default:
1584 break;
1585 }
1586}
1587
1588/**
1589 * gdk_event_get_device:
1590 * @event: a #GdkEvent.
1591 *
1592 * If the event contains a “device” field, this function will return
1593 * it, else it will return %NULL.
1594 *
1595 * Returns: (nullable) (transfer none): a #GdkDevice, or %NULL.
1596 *
1597 * Since: 3.0
1598 **/
1599GdkDevice *
1600gdk_event_get_device (const GdkEvent *event)
1601{
1602 g_return_val_if_fail (event != NULL, NULL);
1603
1604 if (gdk_event_is_allocated (event))
1605 {
1606 GdkEventPrivate *private = (GdkEventPrivate *) event;
1607
1608 if (private->device)
1609 return private->device;
1610 }
1611
1612 switch (event->type)
1613 {
1614 case GDK_MOTION_NOTIFY:
1615 return event->motion.device;
1616 case GDK_BUTTON_PRESS:
1617 case GDK_2BUTTON_PRESS:
1618 case GDK_3BUTTON_PRESS:
1619 case GDK_BUTTON_RELEASE:
1620 return event->button.device;
1621 case GDK_TOUCH_BEGIN:
1622 case GDK_TOUCH_UPDATE:
1623 case GDK_TOUCH_END:
1624 case GDK_TOUCH_CANCEL:
1625 return event->touch.device;
1626 case GDK_SCROLL:
1627 return event->scroll.device;
1628 case GDK_PROXIMITY_IN:
1629 case GDK_PROXIMITY_OUT:
1630 return event->proximity.device;
1631 default:
1632 break;
1633 }
1634
1635 /* Fallback if event has no device set */
1636 switch (event->type)
1637 {
1638 case GDK_MOTION_NOTIFY:
1639 case GDK_BUTTON_PRESS:
1640 case GDK_2BUTTON_PRESS:
1641 case GDK_3BUTTON_PRESS:
1642 case GDK_BUTTON_RELEASE:
1643 case GDK_TOUCH_BEGIN:
1644 case GDK_TOUCH_UPDATE:
1645 case GDK_TOUCH_END:
1646 case GDK_TOUCH_CANCEL:
1647 case GDK_ENTER_NOTIFY:
1648 case GDK_LEAVE_NOTIFY:
1649 case GDK_FOCUS_CHANGE:
1650 case GDK_PROXIMITY_IN:
1651 case GDK_PROXIMITY_OUT:
1652 case GDK_DRAG_ENTER:
1653 case GDK_DRAG_LEAVE:
1654 case GDK_DRAG_MOTION:
1655 case GDK_DRAG_STATUS:
1656 case GDK_DROP_START:
1657 case GDK_DROP_FINISHED:
1658 case GDK_SCROLL:
1659 case GDK_GRAB_BROKEN:
1660 case GDK_KEY_PRESS:
1661 case GDK_KEY_RELEASE:
1662 {
1663 GdkDisplay *display;
1664 GdkSeat *seat;
1665
1666 g_warning ("Event with type %d not holding a GdkDevice. "
1667 "It is most likely synthesized outside Gdk/GTK+",
1668 event->type);
1669
1670 display = gdk_window_get_display (event->any.window);
1671 seat = gdk_display_get_default_seat (display);
1672
1673 if (event->type == GDK_KEY_PRESS ||
1674 event->type == GDK_KEY_RELEASE)
1675 return gdk_seat_get_keyboard (seat);
1676 else
1677 return gdk_seat_get_pointer (seat);
1678 }
1679 break;
1680 default:
1681 return NULL;
1682 }
1683}
1684
1685/**
1686 * gdk_event_set_source_device:
1687 * @event: a #GdkEvent
1688 * @device: a #GdkDevice
1689 *
1690 * Sets the slave device for @event to @device.
1691 *
1692 * The event must have been allocated by GTK+,
1693 * for instance by gdk_event_copy().
1694 *
1695 * Since: 3.0
1696 **/
1697void
1698gdk_event_set_source_device (GdkEvent *event,
1699 GdkDevice *device)
1700{
1701 GdkEventPrivate *private;
1702
1703 g_return_if_fail (gdk_event_is_allocated (event));
1704 g_return_if_fail (GDK_IS_DEVICE (device));
1705
1706 private = (GdkEventPrivate *) event;
1707
1708 g_set_object (&private->source_device, device);
1709}
1710
1711/**
1712 * gdk_event_get_source_device:
1713 * @event: a #GdkEvent
1714 *
1715 * This function returns the hardware (slave) #GdkDevice that has
1716 * triggered the event, falling back to the virtual (master) device
1717 * (as in gdk_event_get_device()) if the event wasn’t caused by
1718 * interaction with a hardware device. This may happen for example
1719 * in synthesized crossing events after a #GdkWindow updates its
1720 * geometry or a grab is acquired/released.
1721 *
1722 * If the event does not contain a device field, this function will
1723 * return %NULL.
1724 *
1725 * Returns: (nullable) (transfer none): a #GdkDevice, or %NULL.
1726 *
1727 * Since: 3.0
1728 **/
1729GdkDevice *
1730gdk_event_get_source_device (const GdkEvent *event)
1731{
1732 GdkEventPrivate *private;
1733
1734 g_return_val_if_fail (event != NULL, NULL);
1735
1736 if (!gdk_event_is_allocated (event))
1737 return NULL;
1738
1739 private = (GdkEventPrivate *) event;
1740
1741 if (private->source_device)
1742 return private->source_device;
1743
1744 /* Fallback to event device */
1745 return gdk_event_get_device (event);
1746}
1747
1748/**
1749 * gdk_event_request_motions:
1750 * @event: a valid #GdkEvent
1751 *
1752 * Request more motion notifies if @event is a motion notify hint event.
1753 *
1754 * This function should be used instead of gdk_window_get_pointer() to
1755 * request further motion notifies, because it also works for extension
1756 * events where motion notifies are provided for devices other than the
1757 * core pointer. Coordinate extraction, processing and requesting more
1758 * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
1759 *
1760 * |[<!-- language="C" -->
1761 * {
1762 * // motion_event handler
1763 * x = motion_event->x;
1764 * y = motion_event->y;
1765 * // handle (x,y) motion
1766 * gdk_event_request_motions (motion_event); // handles is_hint events
1767 * }
1768 * ]|
1769 *
1770 * Since: 2.12
1771 **/
1772void
1773gdk_event_request_motions (const GdkEventMotion *event)
1774{
1775 GdkDisplay *display;
1776
1777 g_return_if_fail (event != NULL);
1778
1779 if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
1780 {
1781 gdk_device_get_state (event->device, event->window, NULL, NULL);
1782
1783 display = gdk_window_get_display (event->window);
1784 _gdk_display_enable_motion_hints (display, event->device);
1785 }
1786}
1787
1788/**
1789 * gdk_event_triggers_context_menu:
1790 * @event: a #GdkEvent, currently only button events are meaningful values
1791 *
1792 * This function returns whether a #GdkEventButton should trigger a
1793 * context menu, according to platform conventions. The right mouse
1794 * button always triggers context menus. Additionally, if
1795 * gdk_keymap_get_modifier_mask() returns a non-0 mask for
1796 * %GDK_MODIFIER_INTENT_CONTEXT_MENU, then the left mouse button will
1797 * also trigger a context menu if this modifier is pressed.
1798 *
1799 * This function should always be used instead of simply checking for
1800 * event->button == %GDK_BUTTON_SECONDARY.
1801 *
1802 * Returns: %TRUE if the event should trigger a context menu.
1803 *
1804 * Since: 3.4
1805 **/
1806gboolean
1807gdk_event_triggers_context_menu (const GdkEvent *event)
1808{
1809 g_return_val_if_fail (event != NULL, FALSE);
1810
1811 if (event->type == GDK_BUTTON_PRESS)
1812 {
1813 const GdkEventButton *bevent = (const GdkEventButton *) event;
1814 GdkDisplay *display;
1815 GdkModifierType modifier;
1816
1817 g_return_val_if_fail (GDK_IS_WINDOW (bevent->window), FALSE);
1818
1819 if (bevent->button == GDK_BUTTON_SECONDARY &&
1820 ! (bevent->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))
1821 return TRUE;
1822
1823 display = gdk_window_get_display (bevent->window);
1824
1825 modifier = gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
1826 GDK_MODIFIER_INTENT_CONTEXT_MENU);
1827
1828 if (modifier != 0 &&
1829 bevent->button == GDK_BUTTON_PRIMARY &&
1830 ! (bevent->state & (GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) &&
1831 (bevent->state & modifier))
1832 return TRUE;
1833 }
1834
1835 return FALSE;
1836}
1837
1838static gboolean
1839gdk_events_get_axis_distances (GdkEvent *event1,
1840 GdkEvent *event2,
1841 gdouble *x_distance,
1842 gdouble *y_distance,
1843 gdouble *distance)
1844{
1845 gdouble x1, x2, y1, y2;
1846 gdouble xd, yd;
1847
1848 if (!gdk_event_get_coords (event1, &x1, &y1) ||
1849 !gdk_event_get_coords (event2, &x2, &y2))
1850 return FALSE;
1851
1852 xd = x2 - x1;
1853 yd = y2 - y1;
1854
1855 if (x_distance)
1856 *x_distance = xd;
1857
1858 if (y_distance)
1859 *y_distance = yd;
1860
1861 if (distance)
1862 *distance = sqrt ((xd * xd) + (yd * yd));
1863
1864 return TRUE;
1865}
1866
1867/**
1868 * gdk_events_get_distance:
1869 * @event1: first #GdkEvent
1870 * @event2: second #GdkEvent
1871 * @distance: (out): return location for the distance
1872 *
1873 * If both events have X/Y information, the distance between both coordinates
1874 * (as in a straight line going from @event1 to @event2) will be returned.
1875 *
1876 * Returns: %TRUE if the distance could be calculated.
1877 *
1878 * Since: 3.0
1879 **/
1880gboolean
1881gdk_events_get_distance (GdkEvent *event1,
1882 GdkEvent *event2,
1883 gdouble *distance)
1884{
1885 return gdk_events_get_axis_distances (event1, event2,
1886 NULL, NULL,
1887 distance);
1888}
1889
1890/**
1891 * gdk_events_get_angle:
1892 * @event1: first #GdkEvent
1893 * @event2: second #GdkEvent
1894 * @angle: (out): return location for the relative angle between both events
1895 *
1896 * If both events contain X/Y information, this function will return %TRUE
1897 * and return in @angle the relative angle from @event1 to @event2. The rotation
1898 * direction for positive angles is from the positive X axis towards the positive
1899 * Y axis.
1900 *
1901 * Returns: %TRUE if the angle could be calculated.
1902 *
1903 * Since: 3.0
1904 **/
1905gboolean
1906gdk_events_get_angle (GdkEvent *event1,
1907 GdkEvent *event2,
1908 gdouble *angle)
1909{
1910 gdouble x_distance, y_distance, distance;
1911
1912 if (!gdk_events_get_axis_distances (event1, event2,
1913 &x_distance, &y_distance,
1914 &distance))
1915 return FALSE;
1916
1917 if (angle)
1918 {
1919 *angle = atan2 (x_distance, y_distance);
1920
1921 /* Invert angle */
1922 *angle = (2 * G_PI) - *angle;
1923
1924 /* Shift it 90° */
1925 *angle += G_PI / 2;
1926
1927 /* And constraint it to 0°-360° */
1928 *angle = fmod (*angle, 2 * G_PI);
1929 }
1930
1931 return TRUE;
1932}
1933
1934/**
1935 * gdk_events_get_center:
1936 * @event1: first #GdkEvent
1937 * @event2: second #GdkEvent
1938 * @x: (out): return location for the X coordinate of the center
1939 * @y: (out): return location for the Y coordinate of the center
1940 *
1941 * If both events contain X/Y information, the center of both coordinates
1942 * will be returned in @x and @y.
1943 *
1944 * Returns: %TRUE if the center could be calculated.
1945 *
1946 * Since: 3.0
1947 **/
1948gboolean
1949gdk_events_get_center (GdkEvent *event1,
1950 GdkEvent *event2,
1951 gdouble *x,
1952 gdouble *y)
1953{
1954 gdouble x1, x2, y1, y2;
1955
1956 if (!gdk_event_get_coords (event1, &x1, &y1) ||
1957 !gdk_event_get_coords (event2, &x2, &y2))
1958 return FALSE;
1959
1960 if (x)
1961 *x = (x2 + x1) / 2;
1962
1963 if (y)
1964 *y = (y2 + y1) / 2;
1965
1966 return TRUE;
1967}
1968
1969/**
1970 * gdk_event_set_screen:
1971 * @event: a #GdkEvent
1972 * @screen: a #GdkScreen
1973 *
1974 * Sets the screen for @event to @screen. The event must
1975 * have been allocated by GTK+, for instance, by
1976 * gdk_event_copy().
1977 *
1978 * Since: 2.2
1979 **/
1980void
1981gdk_event_set_screen (GdkEvent *event,
1982 GdkScreen *screen)
1983{
1984 GdkEventPrivate *private;
1985
1986 g_return_if_fail (gdk_event_is_allocated (event));
1987
1988 private = (GdkEventPrivate *)event;
1989
1990 private->screen = screen;
1991}
1992
1993/**
1994 * gdk_event_get_screen:
1995 * @event: a #GdkEvent
1996 *
1997 * Returns the screen for the event. The screen is
1998 * typically the screen for `event->any.window`, but
1999 * for events such as mouse events, it is the screen
2000 * where the pointer was when the event occurs -
2001 * that is, the screen which has the root window
2002 * to which `event->motion.x_root` and
2003 * `event->motion.y_root` are relative.
2004 *
2005 * Returns: (transfer none): the screen for the event
2006 *
2007 * Since: 2.2
2008 **/
2009GdkScreen *
2010gdk_event_get_screen (const GdkEvent *event)
2011{
2012 if (gdk_event_is_allocated (event))
2013 {
2014 GdkEventPrivate *private = (GdkEventPrivate *)event;
2015
2016 if (private->screen)
2017 return private->screen;
2018 }
2019
2020 if (event->any.window)
2021 return gdk_window_get_screen (event->any.window);
2022
2023 return NULL;
2024}
2025
2026/**
2027 * gdk_event_get_event_sequence:
2028 * @event: a #GdkEvent
2029 *
2030 * If @event if of type %GDK_TOUCH_BEGIN, %GDK_TOUCH_UPDATE,
2031 * %GDK_TOUCH_END or %GDK_TOUCH_CANCEL, returns the #GdkEventSequence
2032 * to which the event belongs. Otherwise, return %NULL.
2033 *
2034 * Returns: (transfer none): the event sequence that the event belongs to
2035 *
2036 * Since: 3.4
2037 */
2038GdkEventSequence *
2039gdk_event_get_event_sequence (const GdkEvent *event)
2040{
2041 if (!event)
2042 return NULL;
2043
2044 if (event->type == GDK_TOUCH_BEGIN ||
2045 event->type == GDK_TOUCH_UPDATE ||
2046 event->type == GDK_TOUCH_END ||
2047 event->type == GDK_TOUCH_CANCEL)
2048 return event->touch.sequence;
2049
2050 return NULL;
2051}
2052
2053/**
2054 * gdk_set_show_events:
2055 * @show_events: %TRUE to output event debugging information.
2056 *
2057 * Sets whether a trace of received events is output.
2058 * Note that GTK+ must be compiled with debugging (that is,
2059 * configured using the `--enable-debug` option)
2060 * to use this option.
2061 **/
2062void
2063gdk_set_show_events (gboolean show_events)
2064{
2065 if (show_events)
2066 _gdk_debug_flags |= GDK_DEBUG_EVENTS;
2067 else
2068 _gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
2069}
2070
2071/**
2072 * gdk_get_show_events:
2073 *
2074 * Gets whether event debugging output is enabled.
2075 *
2076 * Returns: %TRUE if event debugging output is enabled.
2077 **/
2078gboolean
2079gdk_get_show_events (void)
2080{
2081 return (_gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
2082}
2083
2084static void
2085gdk_synthesize_click (GdkDisplay *display,
2086 GdkEvent *event,
2087 gint nclicks)
2088{
2089 GdkEvent *event_copy;
2090
2091 event_copy = gdk_event_copy (event);
2092 event_copy->type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
2093
2094 _gdk_event_queue_append (display, event_copy);
2095}
2096
2097void
2098_gdk_event_button_generate (GdkDisplay *display,
2099 GdkEvent *event)
2100{
2101 GdkMultipleClickInfo *info;
2102 GdkDevice *source_device;
2103
2104 g_return_if_fail (event->type == GDK_BUTTON_PRESS);
2105
2106 source_device = gdk_event_get_source_device (event);
2107 info = g_hash_table_lookup (display->multiple_click_info, event->button.device);
2108
2109 if (G_UNLIKELY (!info))
2110 {
2111 info = g_new0 (GdkMultipleClickInfo, 1);
2112 info->button_number[0] = info->button_number[1] = -1;
2113
2114 g_hash_table_insert (display->multiple_click_info,
2115 event->button.device, info);
2116 }
2117
2118 if ((event->button.time < (info->button_click_time[1] + 2 * display->double_click_time)) &&
2119 (event->button.window == info->button_window[1]) &&
2120 (event->button.button == info->button_number[1]) &&
2121 (source_device == info->last_slave) &&
2122 (ABS (event->button.x - info->button_x[1]) <= display->double_click_distance) &&
2123 (ABS (event->button.y - info->button_y[1]) <= display->double_click_distance))
2124 {
2125 gdk_synthesize_click (display, event, 3);
2126
2127 info->button_click_time[1] = 0;
2128 info->button_click_time[0] = 0;
2129 info->button_window[1] = NULL;
2130 info->button_window[0] = NULL;
2131 info->button_number[1] = -1;
2132 info->button_number[0] = -1;
2133 info->button_x[0] = info->button_x[1] = 0;
2134 info->button_y[0] = info->button_y[1] = 0;
2135 info->last_slave = NULL;
2136 }
2137 else if ((event->button.time < (info->button_click_time[0] + display->double_click_time)) &&
2138 (event->button.window == info->button_window[0]) &&
2139 (event->button.button == info->button_number[0]) &&
2140 (source_device == info->last_slave) &&
2141 (ABS (event->button.x - info->button_x[0]) <= display->double_click_distance) &&
2142 (ABS (event->button.y - info->button_y[0]) <= display->double_click_distance))
2143 {
2144 gdk_synthesize_click (display, event, 2);
2145
2146 info->button_click_time[1] = info->button_click_time[0];
2147 info->button_click_time[0] = event->button.time;
2148 info->button_window[1] = info->button_window[0];
2149 info->button_window[0] = event->button.window;
2150 info->button_number[1] = info->button_number[0];
2151 info->button_number[0] = event->button.button;
2152 info->button_x[1] = info->button_x[0];
2153 info->button_x[0] = event->button.x;
2154 info->button_y[1] = info->button_y[0];
2155 info->button_y[0] = event->button.y;
2156 info->last_slave = source_device;
2157 }
2158 else
2159 {
2160 info->button_click_time[1] = 0;
2161 info->button_click_time[0] = event->button.time;
2162 info->button_window[1] = NULL;
2163 info->button_window[0] = event->button.window;
2164 info->button_number[1] = -1;
2165 info->button_number[0] = event->button.button;
2166 info->button_x[1] = 0;
2167 info->button_x[0] = event->button.x;
2168 info->button_y[1] = 0;
2169 info->button_y[0] = event->button.y;
2170 info->last_slave = source_device;
2171 }
2172}
2173
2174static GList *
2175gdk_get_pending_window_state_event_link (GdkWindow *window)
2176{
2177 GdkDisplay *display = gdk_window_get_display (window);
2178 GList *tmp_list;
2179
2180 for (tmp_list = display->queued_events; tmp_list; tmp_list = tmp_list->next)
2181 {
2182 GdkEventPrivate *event = tmp_list->data;
2183
2184 if (event->event.type == GDK_WINDOW_STATE &&
2185 event->event.window_state.window == window)
2186 return tmp_list;
2187 }
2188
2189 return NULL;
2190}
2191
2192void
2193_gdk_set_window_state (GdkWindow *window,
2194 GdkWindowState new_state)
2195{
2196 GdkDisplay *display = gdk_window_get_display (window);
2197 GdkEvent temp_event;
2198 GdkWindowState old;
2199 GList *pending_event_link;
2200
2201 g_return_if_fail (window != NULL);
2202
2203 temp_event.window_state.window = window;
2204 temp_event.window_state.type = GDK_WINDOW_STATE;
2205 temp_event.window_state.send_event = FALSE;
2206 temp_event.window_state.new_window_state = new_state;
2207
2208 if (temp_event.window_state.new_window_state == window->state)
2209 return; /* No actual work to do, nothing changed. */
2210
2211 pending_event_link = gdk_get_pending_window_state_event_link (window);
2212 if (pending_event_link)
2213 {
2214 old = window->old_state;
2215 _gdk_event_queue_remove_link (display, pending_event_link);
2216 gdk_event_free (pending_event_link->data);
2217 g_list_free_1 (pending_event_link);
2218 }
2219 else
2220 {
2221 old = window->state;
2222 window->old_state = old;
2223 }
2224
2225 temp_event.window_state.changed_mask = new_state ^ old;
2226
2227 /* Actually update the field in GdkWindow, this is sort of an odd
2228 * place to do it, but seems like the safest since it ensures we expose no
2229 * inconsistent state to the user.
2230 */
2231
2232 window->state = new_state;
2233
2234 if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN)
2235 _gdk_window_update_viewable (window);
2236
2237 /* We only really send the event to toplevels, since
2238 * all the window states don't apply to non-toplevels.
2239 * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
2240 * internally so we needed to update window->state.
2241 */
2242 switch (window->window_type)
2243 {
2244 case GDK_WINDOW_TOPLEVEL:
2245 case GDK_WINDOW_TEMP: /* ? */
2246 gdk_display_put_event (display, &temp_event);
2247 break;
2248 case GDK_WINDOW_FOREIGN:
2249 case GDK_WINDOW_ROOT:
2250 case GDK_WINDOW_CHILD:
2251 break;
2252 }
2253}
2254
2255void
2256gdk_synthesize_window_state (GdkWindow *window,
2257 GdkWindowState unset_flags,
2258 GdkWindowState set_flags)
2259{
2260 g_return_if_fail (window != NULL);
2261
2262 _gdk_set_window_state (window, (window->state | set_flags) & ~unset_flags);
2263}
2264
2265/**
2266 * gdk_display_set_double_click_time:
2267 * @display: a #GdkDisplay
2268 * @msec: double click time in milliseconds (thousandths of a second)
2269 *
2270 * Sets the double click time (two clicks within this time interval
2271 * count as a double click and result in a #GDK_2BUTTON_PRESS event).
2272 * Applications should not set this, it is a global
2273 * user-configured setting.
2274 *
2275 * Since: 2.2
2276 **/
2277void
2278gdk_display_set_double_click_time (GdkDisplay *display,
2279 guint msec)
2280{
2281 display->double_click_time = msec;
2282}
2283
2284/**
2285 * gdk_set_double_click_time:
2286 * @msec: double click time in milliseconds (thousandths of a second)
2287 *
2288 * Set the double click time for the default display. See
2289 * gdk_display_set_double_click_time().
2290 * See also gdk_display_set_double_click_distance().
2291 * Applications should not set this, it is a
2292 * global user-configured setting.
2293 **/
2294void
2295gdk_set_double_click_time (guint msec)
2296{
2297 gdk_display_set_double_click_time (gdk_display_get_default (), msec);
2298}
2299
2300/**
2301 * gdk_display_set_double_click_distance:
2302 * @display: a #GdkDisplay
2303 * @distance: distance in pixels
2304 *
2305 * Sets the double click distance (two clicks within this distance
2306 * count as a double click and result in a #GDK_2BUTTON_PRESS event).
2307 * See also gdk_display_set_double_click_time().
2308 * Applications should not set this, it is a global
2309 * user-configured setting.
2310 *
2311 * Since: 2.4
2312 **/
2313void
2314gdk_display_set_double_click_distance (GdkDisplay *display,
2315 guint distance)
2316{
2317 display->double_click_distance = distance;
2318}
2319
2320G_DEFINE_BOXED_TYPE (GdkEvent, gdk_event,
2321 gdk_event_copy,
2322 gdk_event_free)
2323
2324static GdkEventSequence *
2325gdk_event_sequence_copy (GdkEventSequence *sequence)
2326{
2327 return sequence;
2328}
2329
2330static void
2331gdk_event_sequence_free (GdkEventSequence *sequence)
2332{
2333 /* Nothing to free here */
2334}
2335
2336G_DEFINE_BOXED_TYPE (GdkEventSequence, gdk_event_sequence,
2337 gdk_event_sequence_copy,
2338 gdk_event_sequence_free)
2339
2340/**
2341 * gdk_setting_get:
2342 * @name: the name of the setting.
2343 * @value: location to store the value of the setting.
2344 *
2345 * Obtains a desktop-wide setting, such as the double-click time,
2346 * for the default screen. See gdk_screen_get_setting().
2347 *
2348 * Returns: %TRUE if the setting existed and a value was stored
2349 * in @value, %FALSE otherwise.
2350 **/
2351gboolean
2352gdk_setting_get (const gchar *name,
2353 GValue *value)
2354{
2355 return gdk_screen_get_setting (gdk_screen_get_default (), name, value);
2356}
2357
2358/**
2359 * gdk_event_get_event_type:
2360 * @event: a #GdkEvent
2361 *
2362 * Retrieves the type of the event.
2363 *
2364 * Returns: a #GdkEventType
2365 *
2366 * Since: 3.10
2367 */
2368GdkEventType
2369gdk_event_get_event_type (const GdkEvent *event)
2370{
2371 g_return_val_if_fail (event != NULL, GDK_NOTHING);
2372
2373 return event->type;
2374}
2375
2376/**
2377 * gdk_event_get_seat:
2378 * @event: a #GdkEvent
2379 *
2380 * Returns the #GdkSeat this event was generated for.
2381 *
2382 * Returns: (transfer none): The #GdkSeat of this event
2383 *
2384 * Since: 3.20
2385 **/
2386GdkSeat *
2387gdk_event_get_seat (const GdkEvent *event)
2388{
2389 const GdkEventPrivate *priv;
2390
2391 if (!gdk_event_is_allocated (event))
2392 return NULL;
2393
2394 priv = (const GdkEventPrivate *) event;
2395
2396 if (!priv->seat)
2397 {
2398 GdkDevice *device;
2399
2400 g_warning ("Event with type %d not holding a GdkSeat. "
2401 "It is most likely synthesized outside Gdk/GTK+",
2402 event->type);
2403
2404 device = gdk_event_get_device (event);
2405
2406 return device ? gdk_device_get_seat (device) : NULL;
2407 }
2408
2409 return priv->seat;
2410}
2411
2412void
2413gdk_event_set_seat (GdkEvent *event,
2414 GdkSeat *seat)
2415{
2416 GdkEventPrivate *priv;
2417
2418 if (gdk_event_is_allocated (event))
2419 {
2420 priv = (GdkEventPrivate *) event;
2421 priv->seat = seat;
2422 }
2423}
2424
2425/**
2426 * gdk_event_get_device_tool:
2427 * @event: a #GdkEvent
2428 *
2429 * If the event was generated by a device that supports
2430 * different tools (eg. a tablet), this function will
2431 * return a #GdkDeviceTool representing the tool that
2432 * caused the event. Otherwise, %NULL will be returned.
2433 *
2434 * Note: the #GdkDeviceTool<!-- -->s will be constant during
2435 * the application lifetime, if settings must be stored
2436 * persistently across runs, see gdk_device_tool_get_serial()
2437 *
2438 * Returns: (transfer none): The current device tool, or %NULL
2439 *
2440 * Since: 3.22
2441 **/
2442GdkDeviceTool *
2443gdk_event_get_device_tool (const GdkEvent *event)
2444{
2445 GdkEventPrivate *private;
2446
2447 if (!gdk_event_is_allocated (event))
2448 return NULL;
2449
2450 private = (GdkEventPrivate *) event;
2451 return private->tool;
2452}
2453
2454/**
2455 * gdk_event_set_device_tool:
2456 * @event: a #GdkEvent
2457 * @tool: (nullable): tool to set on the event, or %NULL
2458 *
2459 * Sets the device tool for this event, should be rarely used.
2460 *
2461 * Since: 3.22
2462 **/
2463void
2464gdk_event_set_device_tool (GdkEvent *event,
2465 GdkDeviceTool *tool)
2466{
2467 GdkEventPrivate *private;
2468
2469 if (!gdk_event_is_allocated (event))
2470 return;
2471
2472 private = (GdkEventPrivate *) event;
2473 private->tool = tool;
2474}
2475
2476void
2477gdk_event_set_scancode (GdkEvent *event,
2478 guint16 scancode)
2479{
2480 GdkEventPrivate *private = (GdkEventPrivate *) event;
2481
2482 private->key_scancode = scancode;
2483}
2484
2485/**
2486 * gdk_event_get_scancode:
2487 * @event: a #GdkEvent
2488 *
2489 * Gets the keyboard low-level scancode of a key event.
2490 *
2491 * This is usually hardware_keycode. On Windows this is the high
2492 * word of WM_KEY{DOWN,UP} lParam which contains the scancode and
2493 * some extended flags.
2494 *
2495 * Returns: The associated keyboard scancode or 0
2496 *
2497 * Since: 3.22
2498 **/
2499int
2500gdk_event_get_scancode (GdkEvent *event)
2501{
2502 GdkEventPrivate *private;
2503
2504 if (!gdk_event_is_allocated (event))
2505 return 0;
2506
2507 private = (GdkEventPrivate *) event;
2508 return private->key_scancode;
2509}
2510