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