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