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