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