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 }