]> Pileus Git - ~andy/gtk/blob - gdk/gdkevents.c
gdk/gdkdisplay.h gdk/gdkdrawable.h gdk/gdkevents.h gdk/gdkpango.h
[~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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28 #include <string.h>             /* For memset() */
29
30 #include "gdk.h"
31 #include "gdkinternals.h"
32 #include "gdkalias.h"
33
34 typedef struct _GdkIOClosure GdkIOClosure;
35
36 struct _GdkIOClosure
37 {
38   GdkInputFunction function;
39   GdkInputCondition condition;
40   GdkDestroyNotify notify;
41   gpointer data;
42 };
43
44 /* Private variable declarations
45  */
46
47 GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
48 gpointer       _gdk_event_data = NULL;
49 GDestroyNotify _gdk_event_notify = NULL;
50
51 /*********************************************
52  * Functions for maintaining the event queue *
53  *********************************************/
54
55 /**
56  * _gdk_event_queue_find_first:
57  * @display: a #GdkDisplay
58  * 
59  * Find the first event on the queue that is not still
60  * being filled in.
61  * 
62  * Return value: Pointer to the list node for that event, or NULL.
63  **/
64 GList*
65 _gdk_event_queue_find_first (GdkDisplay *display)
66 {
67   GList *tmp_list = display->queued_events;
68
69   while (tmp_list)
70     {
71       GdkEventPrivate *event = tmp_list->data;
72       if (!(event->flags & GDK_EVENT_PENDING))
73         return tmp_list;
74
75       tmp_list = g_list_next (tmp_list);
76     }
77
78   return NULL;
79 }
80
81 /**
82  * _gdk_event_queue_append:
83  * @display: a #GdkDisplay
84  * @event: Event to append.
85  * 
86  * Appends an event onto the tail of the event queue.
87  *
88  * Returns: the newly appended list node.
89  **/
90 GList *
91 _gdk_event_queue_append (GdkDisplay *display,
92                          GdkEvent   *event)
93 {
94   display->queued_tail = g_list_append (display->queued_tail, event);
95   
96   if (!display->queued_events)
97     display->queued_events = display->queued_tail;
98   else
99     display->queued_tail = display->queued_tail->next;
100
101   return display->queued_tail;
102 }
103
104 /**
105  * _gdk_event_queue_remove_link:
106  * @display: a #GdkDisplay
107  * @node: node to remove
108  * 
109  * Removes a specified list node from the event queue.
110  **/
111 void
112 _gdk_event_queue_remove_link (GdkDisplay *display,
113                               GList      *node)
114 {
115   if (node->prev)
116     node->prev->next = node->next;
117   else
118     display->queued_events = node->next;
119   
120   if (node->next)
121     node->next->prev = node->prev;
122   else
123     display->queued_tail = node->prev;
124 }
125
126 /**
127  * _gdk_event_unqueue:
128  * @display: a #GdkDisplay
129  * 
130  * Removes and returns the first event from the event
131  * queue that is not still being filled in.
132  * 
133  * Return value: the event, or %NULL. Ownership is transferred
134  * to the caller.
135  **/
136 GdkEvent*
137 _gdk_event_unqueue (GdkDisplay *display)
138 {
139   GdkEvent *event = NULL;
140   GList *tmp_list;
141
142   tmp_list = _gdk_event_queue_find_first (display);
143
144   if (tmp_list)
145     {
146       event = tmp_list->data;
147       _gdk_event_queue_remove_link (display, tmp_list);
148       g_list_free_1 (tmp_list);
149     }
150
151   return event;
152 }
153
154 /**
155  * gdk_event_handler_set:
156  * @func: the function to call to handle events from GDK.
157  * @data: user data to pass to the function. 
158  * @notify: the function to call when the handler function is removed, i.e. when
159  *          gdk_event_handler_set() is called with another event handler.
160  * 
161  * Sets the function to call to handle all events from GDK.
162  *
163  * Note that GTK+ uses this to install its own event handler, so it is
164  * usually not useful for GTK+ applications. (Although an application
165  * can call this function then call gtk_main_do_event() to pass
166  * events to GTK+.)
167  **/
168 void 
169 gdk_event_handler_set (GdkEventFunc   func,
170                        gpointer       data,
171                        GDestroyNotify notify)
172 {
173   if (_gdk_event_notify)
174     (*_gdk_event_notify) (_gdk_event_data);
175
176   _gdk_event_func = func;
177   _gdk_event_data = data;
178   _gdk_event_notify = notify;
179 }
180
181 /**
182  * gdk_event_get:
183  * 
184  * Checks all open displays for a #GdkEvent to process,to be processed
185  * on, fetching events from the windowing system if necessary.
186  * See gdk_display_get_event().
187  * 
188  * Return value: the next #GdkEvent to be processed, or %NULL if no events
189  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
190  **/
191 GdkEvent*
192 gdk_event_get (void)
193 {
194   GSList *tmp_list;
195
196   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
197     {
198       GdkEvent *event = gdk_display_get_event (tmp_list->data);
199       if (event)
200         return event;
201     }
202
203   return NULL;
204 }
205
206 /**
207  * gdk_event_peek:
208  *
209  * If there is an event waiting in the event queue of some open
210  * display, returns a copy of it. See gdk_display_peek_event().
211  * 
212  * Return value: a copy of the first #GdkEvent on some event queue, or %NULL if no
213  * events are in any queues. The returned #GdkEvent should be freed with
214  * gdk_event_free().
215  **/
216 GdkEvent*
217 gdk_event_peek (void)
218 {
219   GSList *tmp_list;
220
221   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
222     {
223       GdkEvent *event = gdk_display_peek_event (tmp_list->data);
224       if (event)
225         return event;
226     }
227
228   return NULL;
229 }
230
231 /**
232  * gdk_event_put:
233  * @event: a #GdkEvent.
234  *
235  * Appends a copy of the given event onto the front of the event
236  * queue for event->any.window's display, or the default event
237  * queue if event->any.window is %NULL. See gdk_display_put_event().
238  **/
239 void
240 gdk_event_put (const GdkEvent *event)
241 {
242   GdkDisplay *display;
243   
244   g_return_if_fail (event != NULL);
245
246   if (event->any.window)
247     display = gdk_drawable_get_display (event->any.window);
248   else
249     {
250       GDK_NOTE (MULTIHEAD,
251                 g_message ("Falling back to default display for gdk_event_put()"));
252       display = gdk_display_get_default ();
253     }
254
255   gdk_display_put_event (display, event);
256 }
257
258 static GHashTable *event_hash = NULL;
259
260 /**
261  * gdk_event_new:
262  * @type: a #GdkEventType 
263  * 
264  * Creates a new event of the given type. All fields are set to 0.
265  * 
266  * Return value: a newly-allocated #GdkEvent. The returned #GdkEvent 
267  * should be freed with gdk_event_free().
268  *
269  * Since: 2.2
270  **/
271 GdkEvent*
272 gdk_event_new (GdkEventType type)
273 {
274   GdkEventPrivate *new_private;
275   GdkEvent *new_event;
276   
277   if (!event_hash)
278     event_hash = g_hash_table_new (g_direct_hash, NULL);
279
280   new_private = g_slice_new0 (GdkEventPrivate);
281   
282   new_private->flags = 0;
283   new_private->screen = NULL;
284
285   g_hash_table_insert (event_hash, new_private, GUINT_TO_POINTER (1));
286
287   new_event = (GdkEvent *) new_private;
288
289   new_event->any.type = type;
290
291   /*
292    * Bytewise 0 initialization is reasonable for most of the 
293    * current event types. Explicitely initialize double fields
294    * since I trust bytewise 0 == 0. less than for integers
295    * or pointers.
296    */
297   switch (type)
298     {
299     case GDK_MOTION_NOTIFY:
300       new_event->motion.x = 0.;
301       new_event->motion.y = 0.;
302       new_event->motion.x_root = 0.;
303       new_event->motion.y_root = 0.;
304       break;
305     case GDK_BUTTON_PRESS:
306     case GDK_2BUTTON_PRESS:
307     case GDK_3BUTTON_PRESS:
308     case GDK_BUTTON_RELEASE:
309       new_event->button.x = 0.;
310       new_event->button.y = 0.;
311       new_event->button.x_root = 0.;
312       new_event->button.y_root = 0.;
313       break;
314     case GDK_SCROLL:
315       new_event->scroll.x = 0.;
316       new_event->scroll.y = 0.;
317       new_event->scroll.x_root = 0.;
318       new_event->scroll.y_root = 0.;
319       break;
320     case GDK_ENTER_NOTIFY:
321     case GDK_LEAVE_NOTIFY:
322       new_event->crossing.x = 0.;
323       new_event->crossing.y = 0.;
324       new_event->crossing.x_root = 0.;
325       new_event->crossing.y_root = 0.;
326       break;
327     default:
328       break;
329     }
330   
331   return new_event;
332 }
333
334 static gboolean
335 gdk_event_is_allocated (const GdkEvent *event)
336 {
337   if (event_hash)
338     return g_hash_table_lookup (event_hash, event) != NULL;
339
340   return FALSE;
341 }
342  
343 /**
344  * gdk_event_copy:
345  * @event: a #GdkEvent
346  * 
347  * Copies a #GdkEvent, copying or incrementing the reference count of the
348  * resources associated with it (e.g. #GdkWindow's and strings).
349  * 
350  * Return value: a copy of @event. The returned #GdkEvent should be freed with
351  * gdk_event_free().
352  **/
353 GdkEvent*
354 gdk_event_copy (const GdkEvent *event)
355 {
356   GdkEventPrivate *new_private;
357   GdkEvent *new_event;
358   
359   g_return_val_if_fail (event != NULL, NULL);
360   
361   new_event = gdk_event_new (GDK_NOTHING);
362   new_private = (GdkEventPrivate *)new_event;
363
364   *new_event = *event;
365   if (new_event->any.window)
366     g_object_ref (new_event->any.window);
367
368   if (gdk_event_is_allocated (event))
369     {
370       GdkEventPrivate *private = (GdkEventPrivate *)event;
371
372       new_private->screen = private->screen;
373     }
374   
375   switch (event->any.type)
376     {
377     case GDK_KEY_PRESS:
378     case GDK_KEY_RELEASE:
379       new_event->key.string = g_strdup (event->key.string);
380       break;
381       
382     case GDK_ENTER_NOTIFY:
383     case GDK_LEAVE_NOTIFY:
384       if (event->crossing.subwindow != NULL)
385         g_object_ref (event->crossing.subwindow);
386       break;
387       
388     case GDK_DRAG_ENTER:
389     case GDK_DRAG_LEAVE:
390     case GDK_DRAG_MOTION:
391     case GDK_DRAG_STATUS:
392     case GDK_DROP_START:
393     case GDK_DROP_FINISHED:
394       g_object_ref (event->dnd.context);
395       break;
396       
397     case GDK_EXPOSE:
398       if (event->expose.region)
399         new_event->expose.region = gdk_region_copy (event->expose.region);
400       break;
401       
402     case GDK_SETTING:
403       new_event->setting.name = g_strdup (new_event->setting.name);
404       break;
405
406     case GDK_BUTTON_PRESS:
407     case GDK_BUTTON_RELEASE:
408       if (event->button.axes) 
409         new_event->button.axes = g_memdup (event->button.axes, 
410                                              sizeof (gdouble) * event->button.device->num_axes);
411       break;
412
413     case GDK_MOTION_NOTIFY:
414       if (event->motion.axes) 
415         new_event->motion.axes = g_memdup (event->motion.axes, 
416                                            sizeof (gdouble) * event->motion.device->num_axes);
417       
418       break;
419       
420     default:
421       break;
422     }
423   
424   return new_event;
425 }
426
427 /**
428  * gdk_event_free:
429  * @event:  a #GdkEvent.
430  * 
431  * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
432  * Note that this function should only be called with events returned from
433  * functions such as gdk_event_peek(), gdk_event_get(),
434  * gdk_event_get_graphics_expose() and gdk_event_copy().
435  **/
436 void
437 gdk_event_free (GdkEvent *event)
438 {
439   g_return_if_fail (event != NULL);
440
441   if (event->any.window)
442     g_object_unref (event->any.window);
443   
444   switch (event->any.type)
445     {
446     case GDK_KEY_PRESS:
447     case GDK_KEY_RELEASE:
448       g_free (event->key.string);
449       break;
450       
451     case GDK_ENTER_NOTIFY:
452     case GDK_LEAVE_NOTIFY:
453       if (event->crossing.subwindow != NULL)
454         g_object_unref (event->crossing.subwindow);
455       break;
456       
457     case GDK_DRAG_ENTER:
458     case GDK_DRAG_LEAVE:
459     case GDK_DRAG_MOTION:
460     case GDK_DRAG_STATUS:
461     case GDK_DROP_START:
462     case GDK_DROP_FINISHED:
463       g_object_unref (event->dnd.context);
464       break;
465
466     case GDK_BUTTON_PRESS:
467     case GDK_BUTTON_RELEASE:
468       g_free (event->button.axes);
469       break;
470       
471     case GDK_EXPOSE:
472       if (event->expose.region)
473         gdk_region_destroy (event->expose.region);
474       break;
475       
476     case GDK_MOTION_NOTIFY:
477       g_free (event->motion.axes);
478       break;
479       
480     case GDK_SETTING:
481       g_free (event->setting.name);
482       break;
483       
484     default:
485       break;
486     }
487
488   g_hash_table_remove (event_hash, event);
489   g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
490 }
491
492 /**
493  * gdk_event_get_time:
494  * @event: a #GdkEvent
495  * 
496  * Returns the time stamp from @event, if there is one; otherwise
497  * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
498  * 
499  * Return value: time stamp field from @event
500  **/
501 guint32
502 gdk_event_get_time (const GdkEvent *event)
503 {
504   if (event)
505     switch (event->type)
506       {
507       case GDK_MOTION_NOTIFY:
508         return event->motion.time;
509       case GDK_BUTTON_PRESS:
510       case GDK_2BUTTON_PRESS:
511       case GDK_3BUTTON_PRESS:
512       case GDK_BUTTON_RELEASE:
513         return event->button.time;
514       case GDK_SCROLL:
515         return event->scroll.time;
516       case GDK_KEY_PRESS:
517       case GDK_KEY_RELEASE:
518         return event->key.time;
519       case GDK_ENTER_NOTIFY:
520       case GDK_LEAVE_NOTIFY:
521         return event->crossing.time;
522       case GDK_PROPERTY_NOTIFY:
523         return event->property.time;
524       case GDK_SELECTION_CLEAR:
525       case GDK_SELECTION_REQUEST:
526       case GDK_SELECTION_NOTIFY:
527         return event->selection.time;
528       case GDK_PROXIMITY_IN:
529       case GDK_PROXIMITY_OUT:
530         return event->proximity.time;
531       case GDK_DRAG_ENTER:
532       case GDK_DRAG_LEAVE:
533       case GDK_DRAG_MOTION:
534       case GDK_DRAG_STATUS:
535       case GDK_DROP_START:
536       case GDK_DROP_FINISHED:
537         return event->dnd.time;
538       case GDK_CLIENT_EVENT:
539       case GDK_VISIBILITY_NOTIFY:
540       case GDK_NO_EXPOSE:
541       case GDK_CONFIGURE:
542       case GDK_FOCUS_CHANGE:
543       case GDK_NOTHING:
544       case GDK_DELETE:
545       case GDK_DESTROY:
546       case GDK_EXPOSE:
547       case GDK_MAP:
548       case GDK_UNMAP:
549       case GDK_WINDOW_STATE:
550       case GDK_SETTING:
551       case GDK_OWNER_CHANGE:
552       case GDK_GRAB_BROKEN:
553         /* return current time */
554         break;
555       }
556   
557   return GDK_CURRENT_TIME;
558 }
559
560 /**
561  * gdk_event_get_state:
562  * @event: a #GdkEvent or NULL
563  * @state: return location for state
564  * 
565  * If the event contains a "state" field, puts that field in @state. Otherwise
566  * stores an empty state (0). Returns %TRUE if there was a state field
567  * in the event. @event may be %NULL, in which case it's treated
568  * as if the event had no state field.
569  * 
570  * Return value: %TRUE if there was a state field in the event 
571  **/
572 gboolean
573 gdk_event_get_state (const GdkEvent        *event,
574                      GdkModifierType       *state)
575 {
576   g_return_val_if_fail (state != NULL, FALSE);
577   
578   if (event)
579     switch (event->type)
580       {
581       case GDK_MOTION_NOTIFY:
582         *state = event->motion.state;
583         return TRUE;
584       case GDK_BUTTON_PRESS:
585       case GDK_2BUTTON_PRESS:
586       case GDK_3BUTTON_PRESS:
587       case GDK_BUTTON_RELEASE:
588         *state =  event->button.state;
589         return TRUE;
590       case GDK_SCROLL:
591         *state =  event->scroll.state;
592         return TRUE;
593       case GDK_KEY_PRESS:
594       case GDK_KEY_RELEASE:
595         *state =  event->key.state;
596         return TRUE;
597       case GDK_ENTER_NOTIFY:
598       case GDK_LEAVE_NOTIFY:
599         *state =  event->crossing.state;
600         return TRUE;
601       case GDK_PROPERTY_NOTIFY:
602         *state =  event->property.state;
603         return TRUE;
604       case GDK_VISIBILITY_NOTIFY:
605       case GDK_CLIENT_EVENT:
606       case GDK_NO_EXPOSE:
607       case GDK_CONFIGURE:
608       case GDK_FOCUS_CHANGE:
609       case GDK_SELECTION_CLEAR:
610       case GDK_SELECTION_REQUEST:
611       case GDK_SELECTION_NOTIFY:
612       case GDK_PROXIMITY_IN:
613       case GDK_PROXIMITY_OUT:
614       case GDK_DRAG_ENTER:
615       case GDK_DRAG_LEAVE:
616       case GDK_DRAG_MOTION:
617       case GDK_DRAG_STATUS:
618       case GDK_DROP_START:
619       case GDK_DROP_FINISHED:
620       case GDK_NOTHING:
621       case GDK_DELETE:
622       case GDK_DESTROY:
623       case GDK_EXPOSE:
624       case GDK_MAP:
625       case GDK_UNMAP:
626       case GDK_WINDOW_STATE:
627       case GDK_SETTING:
628       case GDK_OWNER_CHANGE:
629       case GDK_GRAB_BROKEN:
630         /* no state field */
631         break;
632       }
633
634   *state = 0;
635   return FALSE;
636 }
637
638 /**
639  * gdk_event_get_coords:
640  * @event: a #GdkEvent
641  * @x_win: location to put event window x coordinate
642  * @y_win: location to put event window y coordinate
643  * 
644  * Extract the event window relative x/y coordinates from an event.
645  * 
646  * Return value: %TRUE if the event delivered event window coordinates
647  **/
648 gboolean
649 gdk_event_get_coords (const GdkEvent *event,
650                       gdouble        *x_win,
651                       gdouble        *y_win)
652 {
653   gdouble x = 0, y = 0;
654   gboolean fetched = TRUE;
655   
656   g_return_val_if_fail (event != NULL, FALSE);
657
658   switch (event->type)
659     {
660     case GDK_CONFIGURE:
661       x = event->configure.x;
662       y = event->configure.y;
663       break;
664     case GDK_ENTER_NOTIFY:
665     case GDK_LEAVE_NOTIFY:
666       x = event->crossing.x;
667       y = event->crossing.y;
668       break;
669     case GDK_SCROLL:
670       x = event->scroll.x;
671       y = event->scroll.y;
672       break;
673     case GDK_BUTTON_PRESS:
674     case GDK_2BUTTON_PRESS:
675     case GDK_3BUTTON_PRESS:
676     case GDK_BUTTON_RELEASE:
677       x = event->button.x;
678       y = event->button.y;
679       break;
680     case GDK_MOTION_NOTIFY:
681       x = event->motion.x;
682       y = event->motion.y;
683       break;
684     default:
685       fetched = FALSE;
686       break;
687     }
688
689   if (x_win)
690     *x_win = x;
691   if (y_win)
692     *y_win = y;
693
694   return fetched;
695 }
696
697 /**
698  * gdk_event_get_root_coords:
699  * @event: a #GdkEvent
700  * @x_root: location to put root window x coordinate
701  * @y_root: location to put root window y coordinate
702  * 
703  * Extract the root window relative x/y coordinates from an event.
704  * 
705  * Return value: %TRUE if the event delivered root window coordinates
706  **/
707 gboolean
708 gdk_event_get_root_coords (const GdkEvent *event,
709                            gdouble        *x_root,
710                            gdouble        *y_root)
711 {
712   gdouble x = 0, y = 0;
713   gboolean fetched = TRUE;
714   
715   g_return_val_if_fail (event != NULL, FALSE);
716
717   switch (event->type)
718     {
719     case GDK_MOTION_NOTIFY:
720       x = event->motion.x_root;
721       y = event->motion.y_root;
722       break;
723     case GDK_SCROLL:
724       x = event->scroll.x_root;
725       y = event->scroll.y_root;
726       break;
727     case GDK_BUTTON_PRESS:
728     case GDK_2BUTTON_PRESS:
729     case GDK_3BUTTON_PRESS:
730     case GDK_BUTTON_RELEASE:
731       x = event->button.x_root;
732       y = event->button.y_root;
733       break;
734     case GDK_ENTER_NOTIFY:
735     case GDK_LEAVE_NOTIFY:
736       x = event->crossing.x_root;
737       y = event->crossing.y_root;
738       break;
739     case GDK_DRAG_ENTER:
740     case GDK_DRAG_LEAVE:
741     case GDK_DRAG_MOTION:
742     case GDK_DRAG_STATUS:
743     case GDK_DROP_START:
744     case GDK_DROP_FINISHED:
745       x = event->dnd.x_root;
746       y = event->dnd.y_root;
747       break;
748     default:
749       fetched = FALSE;
750       break;
751     }
752
753   if (x_root)
754     *x_root = x;
755   if (y_root)
756     *y_root = y;
757
758   return fetched;
759 }
760
761 /**
762  * gdk_event_get_axis:
763  * @event: a #GdkEvent
764  * @axis_use: the axis use to look for
765  * @value: location to store the value found
766  * 
767  * Extract the axis value for a particular axis use from
768  * an event structure.
769  * 
770  * Return value: %TRUE if the specified axis was found, otherwise %FALSE
771  **/
772 gboolean
773 gdk_event_get_axis (const GdkEvent *event,
774                     GdkAxisUse      axis_use,
775                     gdouble        *value)
776 {
777   gdouble *axes;
778   GdkDevice *device;
779   
780   g_return_val_if_fail (event != NULL, FALSE);
781   
782   if (axis_use == GDK_AXIS_X || axis_use == GDK_AXIS_Y)
783     {
784       gdouble x, y;
785       
786       switch (event->type)
787         {
788         case GDK_MOTION_NOTIFY:
789           x = event->motion.x;
790           y = event->motion.y;
791           break;
792         case GDK_SCROLL:
793           x = event->scroll.x;
794           y = event->scroll.y;
795           break;
796         case GDK_BUTTON_PRESS:
797         case GDK_BUTTON_RELEASE:
798           x = event->button.x;
799           y = event->button.y;
800           break;
801         case GDK_ENTER_NOTIFY:
802         case GDK_LEAVE_NOTIFY:
803           x = event->crossing.x;
804           y = event->crossing.y;
805           break;
806           
807         default:
808           return FALSE;
809         }
810
811       if (axis_use == GDK_AXIS_X && value)
812         *value = x;
813       if (axis_use == GDK_AXIS_Y && value)
814         *value = y;
815
816       return TRUE;
817     }
818   else if (event->type == GDK_BUTTON_PRESS ||
819            event->type == GDK_BUTTON_RELEASE)
820     {
821       device = event->button.device;
822       axes = event->button.axes;
823     }
824   else if (event->type == GDK_MOTION_NOTIFY)
825     {
826       device = event->motion.device;
827       axes = event->motion.axes;
828     }
829   else
830     return FALSE;
831
832   return gdk_device_get_axis (device, axes, axis_use, value);
833 }
834
835 /**
836  * gdk_event_request_motions:
837  * @event: a valid #GdkEvent
838  *
839  * Request more motion notifies if @event is a motion notify hint event.
840  * This function should be used instead of gdk_window_get_pointer() to
841  * request further motion notifies, because it also works for extension
842  * events where motion notifies are provided for devices other than the
843  * core pointer. Coordinate extraction, processing and requesting more
844  * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
845  *
846  * |[
847  * { 
848  *   /&ast; motion_event handler &ast;/
849  *   x = motion_event->x;
850  *   y = motion_event->y;
851  *   /&ast; handle (x,y) motion &ast;/
852  *   gdk_event_request_motions (motion_event); /&ast; handles is_hint events &ast;/
853  * }
854  * ]|
855  *
856  * Since: 2.12
857  **/
858 void
859 gdk_event_request_motions (const GdkEventMotion *event)
860 {
861   g_return_if_fail (event != NULL);
862   if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
863     gdk_device_get_state (event->device, event->window, NULL, NULL);
864 }
865
866 /**
867  * gdk_event_set_screen:
868  * @event: a #GdkEvent
869  * @screen: a #GdkScreen
870  * 
871  * Sets the screen for @event to @screen. The event must
872  * have been allocated by GTK+, for instance, by
873  * gdk_event_copy().
874  *
875  * Since: 2.2
876  **/
877 void
878 gdk_event_set_screen (GdkEvent  *event,
879                       GdkScreen *screen)
880 {
881   GdkEventPrivate *private;
882   
883   g_return_if_fail (gdk_event_is_allocated (event));
884
885   private = (GdkEventPrivate *)event;
886   
887   private->screen = screen;
888 }
889
890 /**
891  * gdk_event_get_screen:
892  * @event: a #GdkEvent
893  * 
894  * Returns the screen for the event. The screen is
895  * typically the screen for <literal>event->any.window</literal>, but
896  * for events such as mouse events, it is the screen
897  * where the pointer was when the event occurs -
898  * that is, the screen which has the root window 
899  * to which <literal>event->motion.x_root</literal> and
900  * <literal>event->motion.y_root</literal> are relative.
901  * 
902  * Return value: the screen for the event
903  *
904  * Since: 2.2
905  **/
906 GdkScreen *
907 gdk_event_get_screen (const GdkEvent *event)
908 {
909   if (gdk_event_is_allocated (event))
910     {
911       GdkEventPrivate *private = (GdkEventPrivate *)event;
912
913       if (private->screen)
914         return private->screen;
915     }
916
917   if (event->any.window)
918     return gdk_drawable_get_screen (event->any.window);
919
920   return NULL;
921 }
922
923 /**
924  * gdk_set_show_events:
925  * @show_events:  %TRUE to output event debugging information.
926  * 
927  * Sets whether a trace of received events is output.
928  * Note that GTK+ must be compiled with debugging (that is,
929  * configured using the <option>--enable-debug</option> option)
930  * to use this option.
931  **/
932 void
933 gdk_set_show_events (gboolean show_events)
934 {
935   if (show_events)
936     _gdk_debug_flags |= GDK_DEBUG_EVENTS;
937   else
938     _gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
939 }
940
941 /**
942  * gdk_get_show_events:
943  * 
944  * Gets whether event debugging output is enabled.
945  * 
946  * Return value: %TRUE if event debugging output is enabled.
947  **/
948 gboolean
949 gdk_get_show_events (void)
950 {
951   return (_gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
952 }
953
954 static void
955 gdk_io_destroy (gpointer data)
956 {
957   GdkIOClosure *closure = data;
958
959   if (closure->notify)
960     closure->notify (closure->data);
961
962   g_free (closure);
963 }
964
965 /* What do we do with G_IO_NVAL?
966  */
967 #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
968 #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
969 #define EXCEPTION_CONDITION (G_IO_PRI)
970
971 static gboolean  
972 gdk_io_invoke (GIOChannel   *source,
973                GIOCondition  condition,
974                gpointer      data)
975 {
976   GdkIOClosure *closure = data;
977   GdkInputCondition gdk_cond = 0;
978
979   if (condition & READ_CONDITION)
980     gdk_cond |= GDK_INPUT_READ;
981   if (condition & WRITE_CONDITION)
982     gdk_cond |= GDK_INPUT_WRITE;
983   if (condition & EXCEPTION_CONDITION)
984     gdk_cond |= GDK_INPUT_EXCEPTION;
985
986   if (closure->condition & gdk_cond)
987     closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond);
988
989   return TRUE;
990 }
991
992 gint
993 gdk_input_add_full (gint              source,
994                     GdkInputCondition condition,
995                     GdkInputFunction  function,
996                     gpointer          data,
997                     GdkDestroyNotify  destroy)
998 {
999   guint result;
1000   GdkIOClosure *closure = g_new (GdkIOClosure, 1);
1001   GIOChannel *channel;
1002   GIOCondition cond = 0;
1003
1004   closure->function = function;
1005   closure->condition = condition;
1006   closure->notify = destroy;
1007   closure->data = data;
1008
1009   if (condition & GDK_INPUT_READ)
1010     cond |= READ_CONDITION;
1011   if (condition & GDK_INPUT_WRITE)
1012     cond |= WRITE_CONDITION;
1013   if (condition & GDK_INPUT_EXCEPTION)
1014     cond |= EXCEPTION_CONDITION;
1015
1016   channel = g_io_channel_unix_new (source);
1017   result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond, 
1018                                 gdk_io_invoke,
1019                                 closure, gdk_io_destroy);
1020   g_io_channel_unref (channel);
1021
1022   return result;
1023 }
1024
1025 gint
1026 gdk_input_add (gint              source,
1027                GdkInputCondition condition,
1028                GdkInputFunction  function,
1029                gpointer          data)
1030 {
1031   return gdk_input_add_full (source, condition, function, data, NULL);
1032 }
1033
1034 void
1035 gdk_input_remove (gint tag)
1036 {
1037   g_source_remove (tag);
1038 }
1039
1040 static void
1041 gdk_synthesize_click (GdkDisplay *display,
1042                       GdkEvent   *event,
1043                       gint        nclicks)
1044 {
1045   GdkEvent temp_event;
1046   
1047   g_return_if_fail (event != NULL);
1048   
1049   temp_event = *event;
1050   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
1051   
1052   gdk_display_put_event (display, &temp_event);
1053 }
1054
1055 void
1056 _gdk_event_button_generate (GdkDisplay *display,
1057                             GdkEvent   *event)
1058 {
1059   if ((event->button.time < (display->button_click_time[1] + 2*display->double_click_time)) &&
1060       (event->button.window == display->button_window[1]) &&
1061       (event->button.button == display->button_number[1]) &&
1062       (ABS (event->button.x - display->button_x[1]) <= display->double_click_distance) &&
1063       (ABS (event->button.y - display->button_y[1]) <= display->double_click_distance))
1064 {
1065       gdk_synthesize_click (display, event, 3);
1066             
1067       display->button_click_time[1] = 0;
1068       display->button_click_time[0] = 0;
1069       display->button_window[1] = NULL;
1070       display->button_window[0] = NULL;
1071       display->button_number[1] = -1;
1072       display->button_number[0] = -1;
1073       display->button_x[0] = display->button_x[1] = 0;
1074       display->button_y[0] = display->button_y[1] = 0;
1075     }
1076   else if ((event->button.time < (display->button_click_time[0] + display->double_click_time)) &&
1077            (event->button.window == display->button_window[0]) &&
1078            (event->button.button == display->button_number[0]) &&
1079            (ABS (event->button.x - display->button_x[0]) <= display->double_click_distance) &&
1080            (ABS (event->button.y - display->button_y[0]) <= display->double_click_distance))
1081     {
1082       gdk_synthesize_click (display, event, 2);
1083       
1084       display->button_click_time[1] = display->button_click_time[0];
1085       display->button_click_time[0] = event->button.time;
1086       display->button_window[1] = display->button_window[0];
1087       display->button_window[0] = event->button.window;
1088       display->button_number[1] = display->button_number[0];
1089       display->button_number[0] = event->button.button;
1090       display->button_x[1] = display->button_x[0];
1091       display->button_x[0] = event->button.x;
1092       display->button_y[1] = display->button_y[0];
1093       display->button_y[0] = event->button.y;
1094     }
1095   else
1096     {
1097       display->button_click_time[1] = 0;
1098       display->button_click_time[0] = event->button.time;
1099       display->button_window[1] = NULL;
1100       display->button_window[0] = event->button.window;
1101       display->button_number[1] = -1;
1102       display->button_number[0] = event->button.button;
1103       display->button_x[1] = 0;
1104       display->button_x[0] = event->button.x;
1105       display->button_y[1] = 0;
1106       display->button_y[0] = event->button.y;
1107     }
1108 }
1109
1110 void
1111 gdk_synthesize_window_state (GdkWindow     *window,
1112                              GdkWindowState unset_flags,
1113                              GdkWindowState set_flags)
1114 {
1115   GdkEvent temp_event;
1116   GdkWindowState old;
1117   
1118   g_return_if_fail (window != NULL);
1119   
1120   temp_event.window_state.window = window;
1121   temp_event.window_state.type = GDK_WINDOW_STATE;
1122   temp_event.window_state.send_event = FALSE;
1123   
1124   old = ((GdkWindowObject*) temp_event.window_state.window)->state;
1125   
1126   temp_event.window_state.new_window_state = old;
1127   temp_event.window_state.new_window_state |= set_flags;
1128   temp_event.window_state.new_window_state &= ~unset_flags;
1129   temp_event.window_state.changed_mask = temp_event.window_state.new_window_state ^ old;
1130
1131   if (temp_event.window_state.new_window_state == old)
1132     return; /* No actual work to do, nothing changed. */
1133
1134   /* Actually update the field in GdkWindow, this is sort of an odd
1135    * place to do it, but seems like the safest since it ensures we expose no
1136    * inconsistent state to the user.
1137    */
1138   
1139   ((GdkWindowObject*) window)->state = temp_event.window_state.new_window_state;
1140
1141   /* We only really send the event to toplevels, since
1142    * all the window states don't apply to non-toplevels.
1143    * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
1144    * internally so we needed to update window->state.
1145    */
1146   switch (((GdkWindowObject*) window)->window_type)
1147     {
1148     case GDK_WINDOW_TOPLEVEL:
1149     case GDK_WINDOW_DIALOG:
1150     case GDK_WINDOW_TEMP: /* ? */
1151       gdk_display_put_event (gdk_drawable_get_display (window), &temp_event);
1152       break;
1153       
1154     case GDK_WINDOW_FOREIGN:
1155     case GDK_WINDOW_ROOT:
1156     case GDK_WINDOW_CHILD:
1157       break;
1158     }
1159 }
1160
1161 /**
1162  * gdk_display_set_double_click_time:
1163  * @display: a #GdkDisplay
1164  * @msec: double click time in milliseconds (thousandths of a second) 
1165  * 
1166  * Sets the double click time (two clicks within this time interval
1167  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1168  * Applications should <emphasis>not</emphasis> set this, it is a global 
1169  * user-configured setting.
1170  *
1171  * Since: 2.2
1172  **/
1173 void
1174 gdk_display_set_double_click_time (GdkDisplay *display,
1175                                    guint       msec)
1176 {
1177   display->double_click_time = msec;
1178 }
1179
1180 /**
1181  * gdk_set_double_click_time:
1182  * @msec: double click time in milliseconds (thousandths of a second)
1183  *
1184  * Set the double click time for the default display. See
1185  * gdk_display_set_double_click_time(). 
1186  * See also gdk_display_set_double_click_distance().
1187  * Applications should <emphasis>not</emphasis> set this, it is a 
1188  * global user-configured setting.
1189  **/
1190 void
1191 gdk_set_double_click_time (guint msec)
1192 {
1193   gdk_display_set_double_click_time (gdk_display_get_default (), msec);
1194 }
1195
1196 /**
1197  * gdk_display_set_double_click_distance:
1198  * @display: a #GdkDisplay
1199  * @distance: distance in pixels
1200  * 
1201  * Sets the double click distance (two clicks within this distance
1202  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1203  * See also gdk_display_set_double_click_time().
1204  * Applications should <emphasis>not</emphasis> set this, it is a global 
1205  * user-configured setting.
1206  *
1207  * Since: 2.4
1208  **/
1209 void
1210 gdk_display_set_double_click_distance (GdkDisplay *display,
1211                                        guint       distance)
1212 {
1213   display->double_click_distance = distance;
1214 }
1215
1216 GType
1217 gdk_event_get_type (void)
1218 {
1219   static GType our_type = 0;
1220   
1221   if (our_type == 0)
1222     our_type = g_boxed_type_register_static (g_intern_static_string ("GdkEvent"),
1223                                              (GBoxedCopyFunc)gdk_event_copy,
1224                                              (GBoxedFreeFunc)gdk_event_free);
1225   return our_type;
1226 }
1227
1228 /**
1229  * gdk_setting_get:
1230  * @name: the name of the setting.
1231  * @value: location to store the value of the setting.
1232  *
1233  * Obtains a desktop-wide setting, such as the double-click time,
1234  * for the default screen. See gdk_screen_get_setting().
1235  *
1236  * Returns : %TRUE if the setting existed and a value was stored
1237  *   in @value, %FALSE otherwise.
1238  **/
1239 gboolean
1240 gdk_setting_get (const gchar *name,
1241                  GValue      *value)
1242 {
1243   return gdk_screen_get_setting (gdk_screen_get_default (), name, value);
1244 }
1245
1246 #define __GDK_EVENTS_C__
1247 #include "gdkaliasdef.c"