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