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