]> Pileus Git - ~andy/gtk/blob - gdk/gdkevents.c
Merge branch 'master' into broadway
[~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
29 #include "gdkinternals.h"
30
31 #include <string.h>
32 #include <math.h>
33
34
35 /**
36  * SECTION:events
37  * @Short_description: Functions for handling events from the window system
38  * @Title: Events
39  * @See_also: <link linkend="gdk-Event-Structures">Event Structures</link>
40  *
41  * This section describes functions dealing with events from the window
42  * system.
43  *
44  * In GTK+ applications the events are handled automatically in
45  * gtk_main_do_event() and passed on to the appropriate widgets, so these
46  * functions are rarely needed. Though some of the fields in the
47  * <link linkend="gdk-Event-Structures">Event Structures</link> are useful.
48  */
49
50
51 typedef struct _GdkIOClosure GdkIOClosure;
52
53 struct _GdkIOClosure
54 {
55   GDestroyNotify notify;
56   gpointer data;
57 };
58
59 /* Private variable declarations
60  */
61
62 static GdkEventFunc   _gdk_event_func = NULL;    /* Callback for events */
63 static gpointer       _gdk_event_data = NULL;
64 static GDestroyNotify _gdk_event_notify = NULL;
65
66 void
67 _gdk_event_emit (GdkEvent *event)
68 {
69   if (_gdk_event_func)
70     (*_gdk_event_func) (event, _gdk_event_data);
71 }
72
73 /*********************************************
74  * Functions for maintaining the event queue *
75  *********************************************/
76
77 /**
78  * _gdk_event_queue_find_first:
79  * @display: a #GdkDisplay
80  * 
81  * Find the first event on the queue that is not still
82  * being filled in.
83  * 
84  * Return value: Pointer to the list node for that event, or NULL.
85  **/
86 GList*
87 _gdk_event_queue_find_first (GdkDisplay *display)
88 {
89   GList *tmp_list = display->queued_events;
90
91   while (tmp_list)
92     {
93       GdkEventPrivate *event = tmp_list->data;
94       if (!(event->flags & GDK_EVENT_PENDING))
95         return tmp_list;
96
97       tmp_list = g_list_next (tmp_list);
98     }
99
100   return NULL;
101 }
102
103 /**
104  * _gdk_event_queue_prepend:
105  * @display: a #GdkDisplay
106  * @event: Event to prepend.
107  *
108  * Prepends an event before the head of the event queue.
109  *
110  * Returns: the newly prepended list node.
111  **/
112 GList*
113 _gdk_event_queue_prepend (GdkDisplay *display,
114                           GdkEvent   *event)
115 {
116   display->queued_events = g_list_prepend (display->queued_events, event);
117   if (!display->queued_tail)
118     display->queued_tail = display->queued_events;
119   return display->queued_events;
120 }
121
122 /**
123  * _gdk_event_queue_append:
124  * @display: a #GdkDisplay
125  * @event: Event to append.
126  * 
127  * Appends an event onto the tail of the event queue.
128  *
129  * Returns: the newly appended list node.
130  **/
131 GList *
132 _gdk_event_queue_append (GdkDisplay *display,
133                          GdkEvent   *event)
134 {
135   display->queued_tail = g_list_append (display->queued_tail, event);
136   
137   if (!display->queued_events)
138     display->queued_events = display->queued_tail;
139   else
140     display->queued_tail = display->queued_tail->next;
141
142   return display->queued_tail;
143 }
144
145 /**
146  * _gdk_event_queue_insert_after:
147  * @display: a #GdkDisplay
148  * @sibling: Append after this event.
149  * @event: Event to append.
150  *
151  * Appends an event after the specified event, or if it isn't in
152  * the queue, onto the tail of the event queue.
153  *
154  * Returns: the newly appended list node.
155  *
156  * Since: 2.16
157  */
158 GList*
159 _gdk_event_queue_insert_after (GdkDisplay *display,
160                                GdkEvent   *sibling,
161                                GdkEvent   *event)
162 {
163   GList *prev = g_list_find (display->queued_events, sibling);
164   if (prev && prev->next)
165     {
166       display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
167       return prev->next;
168     }
169   else
170     return _gdk_event_queue_append (display, event);
171 }
172
173 /**
174  * _gdk_event_queue_insert_after:
175  * @display: a #GdkDisplay
176  * @sibling: Append after this event.
177  * @event: Event to append.
178  *
179  * Appends an event before the specified event, or if it isn't in
180  * the queue, onto the tail of the event queue.
181  *
182  * Returns: the newly appended list node.
183  *
184  * Since: 2.16
185  */
186 GList*
187 _gdk_event_queue_insert_before (GdkDisplay *display,
188                                 GdkEvent   *sibling,
189                                 GdkEvent   *event)
190 {
191   GList *next = g_list_find (display->queued_events, sibling);
192   if (next)
193     {
194       display->queued_events = g_list_insert_before (display->queued_events, next, event);
195       return next->prev;
196     }
197   else
198     return _gdk_event_queue_append (display, event);
199 }
200
201
202 /**
203  * _gdk_event_queue_remove_link:
204  * @display: a #GdkDisplay
205  * @node: node to remove
206  * 
207  * Removes a specified list node from the event queue.
208  **/
209 void
210 _gdk_event_queue_remove_link (GdkDisplay *display,
211                               GList      *node)
212 {
213   if (node->prev)
214     node->prev->next = node->next;
215   else
216     display->queued_events = node->next;
217   
218   if (node->next)
219     node->next->prev = node->prev;
220   else
221     display->queued_tail = node->prev;
222 }
223
224 /**
225  * _gdk_event_unqueue:
226  * @display: a #GdkDisplay
227  * 
228  * Removes and returns the first event from the event
229  * queue that is not still being filled in.
230  * 
231  * Return value: the event, or %NULL. Ownership is transferred
232  * to the caller.
233  **/
234 GdkEvent*
235 _gdk_event_unqueue (GdkDisplay *display)
236 {
237   GdkEvent *event = NULL;
238   GList *tmp_list;
239
240   tmp_list = _gdk_event_queue_find_first (display);
241
242   if (tmp_list)
243     {
244       event = tmp_list->data;
245       _gdk_event_queue_remove_link (display, tmp_list);
246       g_list_free_1 (tmp_list);
247     }
248
249   return event;
250 }
251
252 /**
253  * gdk_event_handler_set:
254  * @func: the function to call to handle events from GDK.
255  * @data: user data to pass to the function. 
256  * @notify: the function to call when the handler function is removed, i.e. when
257  *          gdk_event_handler_set() is called with another event handler.
258  * 
259  * Sets the function to call to handle all events from GDK.
260  *
261  * Note that GTK+ uses this to install its own event handler, so it is
262  * usually not useful for GTK+ applications. (Although an application
263  * can call this function then call gtk_main_do_event() to pass
264  * events to GTK+.)
265  **/
266 void 
267 gdk_event_handler_set (GdkEventFunc   func,
268                        gpointer       data,
269                        GDestroyNotify notify)
270 {
271   if (_gdk_event_notify)
272     (*_gdk_event_notify) (_gdk_event_data);
273
274   _gdk_event_func = func;
275   _gdk_event_data = data;
276   _gdk_event_notify = notify;
277 }
278
279 /**
280  * gdk_event_get:
281  * 
282  * Checks all open displays for a #GdkEvent to process,to be processed
283  * on, fetching events from the windowing system if necessary.
284  * See gdk_display_get_event().
285  * 
286  * Return value: the next #GdkEvent to be processed, or %NULL if no events
287  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
288  **/
289 GdkEvent*
290 gdk_event_get (void)
291 {
292   GSList *tmp_list;
293
294   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
295     {
296       GdkEvent *event = gdk_display_get_event (tmp_list->data);
297       if (event)
298         return event;
299     }
300
301   return NULL;
302 }
303
304 /**
305  * gdk_event_peek:
306  *
307  * If there is an event waiting in the event queue of some open
308  * display, returns a copy of it. See gdk_display_peek_event().
309  * 
310  * Return value: a copy of the first #GdkEvent on some event queue, or %NULL if no
311  * events are in any queues. The returned #GdkEvent should be freed with
312  * gdk_event_free().
313  **/
314 GdkEvent*
315 gdk_event_peek (void)
316 {
317   GSList *tmp_list;
318
319   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
320     {
321       GdkEvent *event = gdk_display_peek_event (tmp_list->data);
322       if (event)
323         return event;
324     }
325
326   return NULL;
327 }
328
329 /**
330  * gdk_event_put:
331  * @event: a #GdkEvent.
332  *
333  * Appends a copy of the given event onto the front of the event
334  * queue for event->any.window's display, or the default event
335  * queue if event->any.window is %NULL. See gdk_display_put_event().
336  **/
337 void
338 gdk_event_put (const GdkEvent *event)
339 {
340   GdkDisplay *display;
341   
342   g_return_if_fail (event != NULL);
343
344   if (event->any.window)
345     display = gdk_window_get_display (event->any.window);
346   else
347     {
348       GDK_NOTE (MULTIHEAD,
349                 g_message ("Falling back to default display for gdk_event_put()"));
350       display = gdk_display_get_default ();
351     }
352
353   gdk_display_put_event (display, event);
354 }
355
356 static GHashTable *event_hash = NULL;
357
358 /**
359  * gdk_event_new:
360  * @type: a #GdkEventType 
361  * 
362  * Creates a new event of the given type. All fields are set to 0.
363  * 
364  * Return value: a newly-allocated #GdkEvent. The returned #GdkEvent 
365  * should be freed with gdk_event_free().
366  *
367  * Since: 2.2
368  **/
369 GdkEvent*
370 gdk_event_new (GdkEventType type)
371 {
372   GdkEventPrivate *new_private;
373   GdkEvent *new_event;
374   
375   if (!event_hash)
376     event_hash = g_hash_table_new (g_direct_hash, NULL);
377
378   new_private = g_slice_new0 (GdkEventPrivate);
379   
380   new_private->flags = 0;
381   new_private->screen = NULL;
382
383   g_hash_table_insert (event_hash, new_private, GUINT_TO_POINTER (1));
384
385   new_event = (GdkEvent *) new_private;
386
387   new_event->any.type = type;
388
389   /*
390    * Bytewise 0 initialization is reasonable for most of the 
391    * current event types. Explicitely initialize double fields
392    * since I trust bytewise 0 == 0. less than for integers
393    * or pointers.
394    */
395   switch (type)
396     {
397     case GDK_MOTION_NOTIFY:
398       new_event->motion.x = 0.;
399       new_event->motion.y = 0.;
400       new_event->motion.x_root = 0.;
401       new_event->motion.y_root = 0.;
402       break;
403     case GDK_BUTTON_PRESS:
404     case GDK_2BUTTON_PRESS:
405     case GDK_3BUTTON_PRESS:
406     case GDK_BUTTON_RELEASE:
407       new_event->button.x = 0.;
408       new_event->button.y = 0.;
409       new_event->button.x_root = 0.;
410       new_event->button.y_root = 0.;
411       break;
412     case GDK_SCROLL:
413       new_event->scroll.x = 0.;
414       new_event->scroll.y = 0.;
415       new_event->scroll.x_root = 0.;
416       new_event->scroll.y_root = 0.;
417       break;
418     case GDK_ENTER_NOTIFY:
419     case GDK_LEAVE_NOTIFY:
420       new_event->crossing.x = 0.;
421       new_event->crossing.y = 0.;
422       new_event->crossing.x_root = 0.;
423       new_event->crossing.y_root = 0.;
424       break;
425     default:
426       break;
427     }
428   
429   return new_event;
430 }
431
432 static gboolean
433 gdk_event_is_allocated (const GdkEvent *event)
434 {
435   if (event_hash)
436     return g_hash_table_lookup (event_hash, event) != NULL;
437
438   return FALSE;
439 }
440  
441 /**
442  * gdk_event_copy:
443  * @event: a #GdkEvent
444  * 
445  * Copies a #GdkEvent, copying or incrementing the reference count of the
446  * resources associated with it (e.g. #GdkWindow's and strings).
447  * 
448  * Return value: a copy of @event. The returned #GdkEvent should be freed with
449  * gdk_event_free().
450  **/
451 GdkEvent*
452 gdk_event_copy (const GdkEvent *event)
453 {
454   GdkEventPrivate *new_private;
455   GdkEvent *new_event;
456   
457   g_return_val_if_fail (event != NULL, NULL);
458   
459   new_event = gdk_event_new (GDK_NOTHING);
460   new_private = (GdkEventPrivate *)new_event;
461
462   *new_event = *event;
463   if (new_event->any.window)
464     g_object_ref (new_event->any.window);
465
466   if (gdk_event_is_allocated (event))
467     {
468       GdkEventPrivate *private = (GdkEventPrivate *)event;
469
470       new_private->screen = private->screen;
471       new_private->device = private->device;
472     }
473   
474   switch (event->any.type)
475     {
476     case GDK_KEY_PRESS:
477     case GDK_KEY_RELEASE:
478       new_event->key.string = g_strdup (event->key.string);
479       break;
480       
481     case GDK_ENTER_NOTIFY:
482     case GDK_LEAVE_NOTIFY:
483       if (event->crossing.subwindow != NULL)
484         g_object_ref (event->crossing.subwindow);
485       break;
486       
487     case GDK_DRAG_ENTER:
488     case GDK_DRAG_LEAVE:
489     case GDK_DRAG_MOTION:
490     case GDK_DRAG_STATUS:
491     case GDK_DROP_START:
492     case GDK_DROP_FINISHED:
493       g_object_ref (event->dnd.context);
494       break;
495       
496     case GDK_EXPOSE:
497     case GDK_DAMAGE:
498       if (event->expose.region)
499         new_event->expose.region = cairo_region_copy (event->expose.region);
500       break;
501       
502     case GDK_SETTING:
503       new_event->setting.name = g_strdup (new_event->setting.name);
504       break;
505
506     case GDK_BUTTON_PRESS:
507     case GDK_BUTTON_RELEASE:
508       if (event->button.axes) 
509         new_event->button.axes = g_memdup (event->button.axes,
510                                            sizeof (gdouble) * gdk_device_get_n_axes (event->button.device));
511       break;
512
513     case GDK_MOTION_NOTIFY:
514       if (event->motion.axes) 
515         new_event->motion.axes = g_memdup (event->motion.axes,
516                                            sizeof (gdouble) * gdk_device_get_n_axes (event->motion.device));
517       break;
518
519     default:
520       break;
521     }
522
523   if (gdk_event_is_allocated (event))
524     _gdk_windowing_event_data_copy (event, new_event);
525   
526   return new_event;
527 }
528
529 /**
530  * gdk_event_free:
531  * @event:  a #GdkEvent.
532  * 
533  * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
534  * Note that this function should only be called with events returned from
535  * functions such as gdk_event_peek(), gdk_event_get(), gdk_event_copy()
536  * and gdk_event_new().
537  **/
538 void
539 gdk_event_free (GdkEvent *event)
540 {
541   g_return_if_fail (event != NULL);
542
543   if (event->any.window)
544     g_object_unref (event->any.window);
545   
546   switch (event->any.type)
547     {
548     case GDK_KEY_PRESS:
549     case GDK_KEY_RELEASE:
550       g_free (event->key.string);
551       break;
552       
553     case GDK_ENTER_NOTIFY:
554     case GDK_LEAVE_NOTIFY:
555       if (event->crossing.subwindow != NULL)
556         g_object_unref (event->crossing.subwindow);
557       break;
558       
559     case GDK_DRAG_ENTER:
560     case GDK_DRAG_LEAVE:
561     case GDK_DRAG_MOTION:
562     case GDK_DRAG_STATUS:
563     case GDK_DROP_START:
564     case GDK_DROP_FINISHED:
565       if (event->dnd.context != NULL)
566         g_object_unref (event->dnd.context);
567       break;
568
569     case GDK_BUTTON_PRESS:
570     case GDK_BUTTON_RELEASE:
571       g_free (event->button.axes);
572       break;
573       
574     case GDK_EXPOSE:
575     case GDK_DAMAGE:
576       if (event->expose.region)
577         cairo_region_destroy (event->expose.region);
578       break;
579       
580     case GDK_MOTION_NOTIFY:
581       g_free (event->motion.axes);
582       break;
583       
584     case GDK_SETTING:
585       g_free (event->setting.name);
586       break;
587       
588     default:
589       break;
590     }
591
592   _gdk_windowing_event_data_free (event);
593
594   g_hash_table_remove (event_hash, event);
595   g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
596 }
597
598 /**
599  * gdk_event_get_time:
600  * @event: a #GdkEvent
601  * 
602  * Returns the time stamp from @event, if there is one; otherwise
603  * returns #GDK_CURRENT_TIME. If @event is %NULL, returns #GDK_CURRENT_TIME.
604  * 
605  * Return value: time stamp field from @event
606  **/
607 guint32
608 gdk_event_get_time (const GdkEvent *event)
609 {
610   if (event)
611     switch (event->type)
612       {
613       case GDK_MOTION_NOTIFY:
614         return event->motion.time;
615       case GDK_BUTTON_PRESS:
616       case GDK_2BUTTON_PRESS:
617       case GDK_3BUTTON_PRESS:
618       case GDK_BUTTON_RELEASE:
619         return event->button.time;
620       case GDK_SCROLL:
621         return event->scroll.time;
622       case GDK_KEY_PRESS:
623       case GDK_KEY_RELEASE:
624         return event->key.time;
625       case GDK_ENTER_NOTIFY:
626       case GDK_LEAVE_NOTIFY:
627         return event->crossing.time;
628       case GDK_PROPERTY_NOTIFY:
629         return event->property.time;
630       case GDK_SELECTION_CLEAR:
631       case GDK_SELECTION_REQUEST:
632       case GDK_SELECTION_NOTIFY:
633         return event->selection.time;
634       case GDK_PROXIMITY_IN:
635       case GDK_PROXIMITY_OUT:
636         return event->proximity.time;
637       case GDK_DRAG_ENTER:
638       case GDK_DRAG_LEAVE:
639       case GDK_DRAG_MOTION:
640       case GDK_DRAG_STATUS:
641       case GDK_DROP_START:
642       case GDK_DROP_FINISHED:
643         return event->dnd.time;
644       case GDK_CLIENT_EVENT:
645       case GDK_VISIBILITY_NOTIFY:
646       case GDK_CONFIGURE:
647       case GDK_FOCUS_CHANGE:
648       case GDK_NOTHING:
649       case GDK_DAMAGE:
650       case GDK_DELETE:
651       case GDK_DESTROY:
652       case GDK_EXPOSE:
653       case GDK_MAP:
654       case GDK_UNMAP:
655       case GDK_WINDOW_STATE:
656       case GDK_SETTING:
657       case GDK_OWNER_CHANGE:
658       case GDK_GRAB_BROKEN:
659       case GDK_EVENT_LAST:
660         /* return current time */
661         break;
662       }
663   
664   return GDK_CURRENT_TIME;
665 }
666
667 /**
668  * gdk_event_get_state:
669  * @event: a #GdkEvent or NULL
670  * @state: (out): return location for state
671  * 
672  * If the event contains a "state" field, puts that field in @state. Otherwise
673  * stores an empty state (0). Returns %TRUE if there was a state field
674  * in the event. @event may be %NULL, in which case it's treated
675  * as if the event had no state field.
676  * 
677  * Return value: %TRUE if there was a state field in the event 
678  **/
679 gboolean
680 gdk_event_get_state (const GdkEvent        *event,
681                      GdkModifierType       *state)
682 {
683   g_return_val_if_fail (state != NULL, FALSE);
684   
685   if (event)
686     switch (event->type)
687       {
688       case GDK_MOTION_NOTIFY:
689         *state = event->motion.state;
690         return TRUE;
691       case GDK_BUTTON_PRESS:
692       case GDK_2BUTTON_PRESS:
693       case GDK_3BUTTON_PRESS:
694       case GDK_BUTTON_RELEASE:
695         *state =  event->button.state;
696         return TRUE;
697       case GDK_SCROLL:
698         *state =  event->scroll.state;
699         return TRUE;
700       case GDK_KEY_PRESS:
701       case GDK_KEY_RELEASE:
702         *state =  event->key.state;
703         return TRUE;
704       case GDK_ENTER_NOTIFY:
705       case GDK_LEAVE_NOTIFY:
706         *state =  event->crossing.state;
707         return TRUE;
708       case GDK_PROPERTY_NOTIFY:
709         *state =  event->property.state;
710         return TRUE;
711       case GDK_VISIBILITY_NOTIFY:
712       case GDK_CLIENT_EVENT:
713       case GDK_CONFIGURE:
714       case GDK_FOCUS_CHANGE:
715       case GDK_SELECTION_CLEAR:
716       case GDK_SELECTION_REQUEST:
717       case GDK_SELECTION_NOTIFY:
718       case GDK_PROXIMITY_IN:
719       case GDK_PROXIMITY_OUT:
720       case GDK_DAMAGE:
721       case GDK_DRAG_ENTER:
722       case GDK_DRAG_LEAVE:
723       case GDK_DRAG_MOTION:
724       case GDK_DRAG_STATUS:
725       case GDK_DROP_START:
726       case GDK_DROP_FINISHED:
727       case GDK_NOTHING:
728       case GDK_DELETE:
729       case GDK_DESTROY:
730       case GDK_EXPOSE:
731       case GDK_MAP:
732       case GDK_UNMAP:
733       case GDK_WINDOW_STATE:
734       case GDK_SETTING:
735       case GDK_OWNER_CHANGE:
736       case GDK_GRAB_BROKEN:
737       case GDK_EVENT_LAST:
738         /* no state field */
739         break;
740       }
741
742   *state = 0;
743   return FALSE;
744 }
745
746 /**
747  * gdk_event_get_coords:
748  * @event: a #GdkEvent
749  * @x_win: (out): location to put event window x coordinate
750  * @y_win: (out): location to put event window y coordinate
751  * 
752  * Extract the event window relative x/y coordinates from an event.
753  * 
754  * Return value: %TRUE if the event delivered event window coordinates
755  **/
756 gboolean
757 gdk_event_get_coords (const GdkEvent *event,
758                       gdouble        *x_win,
759                       gdouble        *y_win)
760 {
761   gdouble x = 0, y = 0;
762   gboolean fetched = TRUE;
763   
764   g_return_val_if_fail (event != NULL, FALSE);
765
766   switch (event->type)
767     {
768     case GDK_CONFIGURE:
769       x = event->configure.x;
770       y = event->configure.y;
771       break;
772     case GDK_ENTER_NOTIFY:
773     case GDK_LEAVE_NOTIFY:
774       x = event->crossing.x;
775       y = event->crossing.y;
776       break;
777     case GDK_SCROLL:
778       x = event->scroll.x;
779       y = event->scroll.y;
780       break;
781     case GDK_BUTTON_PRESS:
782     case GDK_2BUTTON_PRESS:
783     case GDK_3BUTTON_PRESS:
784     case GDK_BUTTON_RELEASE:
785       x = event->button.x;
786       y = event->button.y;
787       break;
788     case GDK_MOTION_NOTIFY:
789       x = event->motion.x;
790       y = event->motion.y;
791       break;
792     default:
793       fetched = FALSE;
794       break;
795     }
796
797   if (x_win)
798     *x_win = x;
799   if (y_win)
800     *y_win = y;
801
802   return fetched;
803 }
804
805 /**
806  * gdk_event_get_root_coords:
807  * @event: a #GdkEvent
808  * @x_root: (out): location to put root window x coordinate
809  * @y_root: (out): location to put root window y coordinate
810  * 
811  * Extract the root window relative x/y coordinates from an event.
812  * 
813  * Return value: %TRUE if the event delivered root window coordinates
814  **/
815 gboolean
816 gdk_event_get_root_coords (const GdkEvent *event,
817                            gdouble        *x_root,
818                            gdouble        *y_root)
819 {
820   gdouble x = 0, y = 0;
821   gboolean fetched = TRUE;
822   
823   g_return_val_if_fail (event != NULL, FALSE);
824
825   switch (event->type)
826     {
827     case GDK_MOTION_NOTIFY:
828       x = event->motion.x_root;
829       y = event->motion.y_root;
830       break;
831     case GDK_SCROLL:
832       x = event->scroll.x_root;
833       y = event->scroll.y_root;
834       break;
835     case GDK_BUTTON_PRESS:
836     case GDK_2BUTTON_PRESS:
837     case GDK_3BUTTON_PRESS:
838     case GDK_BUTTON_RELEASE:
839       x = event->button.x_root;
840       y = event->button.y_root;
841       break;
842     case GDK_ENTER_NOTIFY:
843     case GDK_LEAVE_NOTIFY:
844       x = event->crossing.x_root;
845       y = event->crossing.y_root;
846       break;
847     case GDK_DRAG_ENTER:
848     case GDK_DRAG_LEAVE:
849     case GDK_DRAG_MOTION:
850     case GDK_DRAG_STATUS:
851     case GDK_DROP_START:
852     case GDK_DROP_FINISHED:
853       x = event->dnd.x_root;
854       y = event->dnd.y_root;
855       break;
856     default:
857       fetched = FALSE;
858       break;
859     }
860
861   if (x_root)
862     *x_root = x;
863   if (y_root)
864     *y_root = y;
865
866   return fetched;
867 }
868
869 /**
870  * gdk_event_get_axis:
871  * @event: a #GdkEvent
872  * @axis_use: (out): the axis use to look for
873  * @value: (out): location to store the value found
874  * 
875  * Extract the axis value for a particular axis use from
876  * an event structure.
877  * 
878  * Return value: %TRUE if the specified axis was found, otherwise %FALSE
879  **/
880 gboolean
881 gdk_event_get_axis (const GdkEvent *event,
882                     GdkAxisUse      axis_use,
883                     gdouble        *value)
884 {
885   gdouble *axes;
886   GdkDevice *device;
887   
888   g_return_val_if_fail (event != NULL, FALSE);
889   
890   if (axis_use == GDK_AXIS_X || axis_use == GDK_AXIS_Y)
891     {
892       gdouble x, y;
893       
894       switch (event->type)
895         {
896         case GDK_MOTION_NOTIFY:
897           x = event->motion.x;
898           y = event->motion.y;
899           break;
900         case GDK_SCROLL:
901           x = event->scroll.x;
902           y = event->scroll.y;
903           break;
904         case GDK_BUTTON_PRESS:
905         case GDK_BUTTON_RELEASE:
906           x = event->button.x;
907           y = event->button.y;
908           break;
909         case GDK_ENTER_NOTIFY:
910         case GDK_LEAVE_NOTIFY:
911           x = event->crossing.x;
912           y = event->crossing.y;
913           break;
914           
915         default:
916           return FALSE;
917         }
918
919       if (axis_use == GDK_AXIS_X && value)
920         *value = x;
921       if (axis_use == GDK_AXIS_Y && value)
922         *value = y;
923
924       return TRUE;
925     }
926   else if (event->type == GDK_BUTTON_PRESS ||
927            event->type == GDK_BUTTON_RELEASE)
928     {
929       device = event->button.device;
930       axes = event->button.axes;
931     }
932   else if (event->type == GDK_MOTION_NOTIFY)
933     {
934       device = event->motion.device;
935       axes = event->motion.axes;
936     }
937   else
938     return FALSE;
939
940   return gdk_device_get_axis (device, axes, axis_use, value);
941 }
942
943 /**
944  * gdk_event_set_device:
945  * @event: a #GdkEvent
946  * @device: a #GdkDevice
947  *
948  * Sets the device for @event to @device. The event must
949  * have been allocated by GTK+, for instance, by
950  * gdk_event_copy().
951  *
952  * Since: 3.0
953  **/
954 void
955 gdk_event_set_device (GdkEvent  *event,
956                       GdkDevice *device)
957 {
958   GdkEventPrivate *private;
959
960   g_return_if_fail (gdk_event_is_allocated (event));
961
962   private = (GdkEventPrivate *) event;
963
964   private->device = device;
965
966   switch (event->type)
967     {
968     case GDK_MOTION_NOTIFY:
969       event->motion.device = device;
970       break;
971     case GDK_BUTTON_PRESS:
972     case GDK_2BUTTON_PRESS:
973     case GDK_3BUTTON_PRESS:
974     case GDK_BUTTON_RELEASE:
975       event->button.device = device;
976       break;
977     case GDK_SCROLL:
978       event->scroll.device = device;
979       break;
980     case GDK_PROXIMITY_IN:
981     case GDK_PROXIMITY_OUT:
982       event->proximity.device = device;
983       break;
984     default:
985       break;
986     }
987 }
988
989 /**
990  * gdk_event_get_device:
991  * @event: a #GdkEvent.
992  *
993  * If the event contains a "device" field, this function will return
994  * it, else it will return %NULL.
995  *
996  * Returns: (transfer none): a #GdkDevice, or %NULL.
997  *
998  * Since: 3.0
999  **/
1000 GdkDevice *
1001 gdk_event_get_device (const GdkEvent *event)
1002 {
1003   g_return_val_if_fail (event != NULL, NULL);
1004
1005   if (gdk_event_is_allocated (event))
1006     {
1007       GdkEventPrivate *private = (GdkEventPrivate *) event;
1008
1009       if (private->device)
1010         return private->device;
1011     }
1012
1013   switch (event->type)
1014     {
1015     case GDK_MOTION_NOTIFY:
1016       return event->motion.device;
1017     case GDK_BUTTON_PRESS:
1018     case GDK_2BUTTON_PRESS:
1019     case GDK_3BUTTON_PRESS:
1020     case GDK_BUTTON_RELEASE:
1021       return event->button.device;
1022     case GDK_SCROLL:
1023       return event->scroll.device;
1024     case GDK_PROXIMITY_IN:
1025     case GDK_PROXIMITY_OUT:
1026       return event->proximity.device;
1027     default:
1028       break;
1029     }
1030
1031   /* Fallback if event has no device set */
1032   switch (event->type)
1033     {
1034     case GDK_MOTION_NOTIFY:
1035     case GDK_BUTTON_PRESS:
1036     case GDK_2BUTTON_PRESS:
1037     case GDK_3BUTTON_PRESS:
1038     case GDK_BUTTON_RELEASE:
1039     case GDK_ENTER_NOTIFY:
1040     case GDK_LEAVE_NOTIFY:
1041     case GDK_FOCUS_CHANGE:
1042     case GDK_PROXIMITY_IN:
1043     case GDK_PROXIMITY_OUT:
1044     case GDK_DRAG_ENTER:
1045     case GDK_DRAG_LEAVE:
1046     case GDK_DRAG_MOTION:
1047     case GDK_DRAG_STATUS:
1048     case GDK_DROP_START:
1049     case GDK_DROP_FINISHED:
1050     case GDK_SCROLL:
1051     case GDK_GRAB_BROKEN:
1052     case GDK_KEY_PRESS:
1053     case GDK_KEY_RELEASE:
1054       {
1055         GdkDisplay *display;
1056         GdkDeviceManager *device_manager;
1057         GdkDevice *client_pointer;
1058
1059         g_warning ("Event with type %d not holding a GdkDevice. "
1060                    "It is most likely synthesized outside Gdk/GTK+\n",
1061                    event->type);
1062
1063         display = gdk_window_get_display (event->any.window);
1064         device_manager = gdk_display_get_device_manager (display);
1065         client_pointer = gdk_device_manager_get_client_pointer (device_manager);
1066
1067         if (event->type == GDK_KEY_PRESS ||
1068             event->type == GDK_KEY_RELEASE)
1069           return gdk_device_get_associated_device (client_pointer);
1070         else
1071           return client_pointer;
1072       }
1073       break;
1074     default:
1075       return NULL;
1076     }
1077 }
1078
1079 /**
1080  * gdk_event_request_motions:
1081  * @event: a valid #GdkEvent
1082  *
1083  * Request more motion notifies if @event is a motion notify hint event.
1084  * This function should be used instead of gdk_window_get_pointer() to
1085  * request further motion notifies, because it also works for extension
1086  * events where motion notifies are provided for devices other than the
1087  * core pointer. Coordinate extraction, processing and requesting more
1088  * motion events from a %GDK_MOTION_NOTIFY event usually works like this:
1089  *
1090  * |[
1091  * { 
1092  *   /&ast; motion_event handler &ast;/
1093  *   x = motion_event->x;
1094  *   y = motion_event->y;
1095  *   /&ast; handle (x,y) motion &ast;/
1096  *   gdk_event_request_motions (motion_event); /&ast; handles is_hint events &ast;/
1097  * }
1098  * ]|
1099  *
1100  * Since: 2.12
1101  **/
1102 void
1103 gdk_event_request_motions (const GdkEventMotion *event)
1104 {
1105   GdkDisplay *display;
1106   
1107   g_return_if_fail (event != NULL);
1108   
1109   if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
1110     {
1111       gdk_device_get_state (event->device, event->window, NULL, NULL);
1112       
1113       display = gdk_window_get_display (event->window);
1114       _gdk_display_enable_motion_hints (display, event->device);
1115     }
1116 }
1117
1118 static gboolean
1119 gdk_events_get_axis_distances (GdkEvent *event1,
1120                                GdkEvent *event2,
1121                                gdouble  *x_distance,
1122                                gdouble  *y_distance,
1123                                gdouble  *distance)
1124 {
1125   gdouble x1, x2, y1, y2;
1126   gdouble xd, yd;
1127
1128   if (!gdk_event_get_coords (event1, &x1, &y1) ||
1129       !gdk_event_get_coords (event2, &x2, &y2))
1130     return FALSE;
1131
1132   xd = x2 - x1;
1133   yd = y2 - y1;
1134
1135   if (x_distance)
1136     *x_distance = xd;
1137
1138   if (y_distance)
1139     *y_distance = yd;
1140
1141   if (distance)
1142     *distance = sqrt ((xd * xd) + (yd * yd));
1143
1144   return TRUE;
1145 }
1146
1147 /**
1148  * gdk_events_get_distance:
1149  * @event1: first #GdkEvent
1150  * @event2: second #GdkEvent
1151  * @distance: return location for the distance
1152  *
1153  * If both events have X/Y information, the distance between both coordinates
1154  * (as in a straight line going from @event1 to @event2) will be returned.
1155  *
1156  * Returns: %TRUE if the distance could be calculated.
1157  *
1158  * Since: 3.0
1159  **/
1160 gboolean
1161 gdk_events_get_distance (GdkEvent *event1,
1162                          GdkEvent *event2,
1163                          gdouble  *distance)
1164 {
1165   return gdk_events_get_axis_distances (event1, event2,
1166                                         NULL, NULL,
1167                                         distance);
1168 }
1169
1170 /**
1171  * gdk_events_get_angle:
1172  * @event1: first #GdkEvent
1173  * @event2: second #GdkEvent
1174  * @angle: return location for the relative angle between both events
1175  *
1176  * If both events contain X/Y information, this function will return %TRUE
1177  * and return in @angle the relative angle from @event1 to @event2. The rotation
1178  * direction for positive angles is from the positive X axis towards the positive
1179  * Y axis.
1180  *
1181  * Returns: %TRUE if the angle could be calculated.
1182  *
1183  * Since: 3.0
1184  **/
1185 gboolean
1186 gdk_events_get_angle (GdkEvent *event1,
1187                       GdkEvent *event2,
1188                       gdouble  *angle)
1189 {
1190   gdouble x_distance, y_distance, distance;
1191
1192   if (!gdk_events_get_axis_distances (event1, event2,
1193                                       &x_distance, &y_distance,
1194                                       &distance))
1195     return FALSE;
1196
1197   if (angle)
1198     {
1199       *angle = atan2 (x_distance, y_distance);
1200
1201       /* Invert angle */
1202       *angle = (2 * G_PI) - *angle;
1203
1204       /* Shift it 90° */
1205       *angle += G_PI / 2;
1206
1207       /* And constraint it to 0°-360° */
1208       *angle = fmod (*angle, 2 * G_PI);
1209     }
1210
1211   return TRUE;
1212 }
1213
1214 /**
1215  * gdk_events_get_center:
1216  * @event1: first #GdkEvent
1217  * @event2: second #GdkEvent
1218  * @x: (out): return location for the X coordinate of the center
1219  * @y: (out): return location for the Y coordinate of the center
1220  *
1221  * If both events contain X/Y information, the center of both coordinates
1222  * will be returned in @x and @y.
1223  *
1224  * Returns: %TRUE if the center could be calculated.
1225  *
1226  * Since: 3.0
1227  **/
1228 gboolean
1229 gdk_events_get_center (GdkEvent *event1,
1230                        GdkEvent *event2,
1231                        gdouble  *x,
1232                        gdouble  *y)
1233 {
1234   gdouble x1, x2, y1, y2;
1235
1236   if (!gdk_event_get_coords (event1, &x1, &y1) ||
1237       !gdk_event_get_coords (event2, &x2, &y2))
1238     return FALSE;
1239
1240   if (x)
1241     *x = (x2 + x1) / 2;
1242
1243   if (y)
1244     *y = (y2 + y1) / 2;
1245
1246   return TRUE;
1247 }
1248
1249 /**
1250  * gdk_event_set_screen:
1251  * @event: a #GdkEvent
1252  * @screen: a #GdkScreen
1253  * 
1254  * Sets the screen for @event to @screen. The event must
1255  * have been allocated by GTK+, for instance, by
1256  * gdk_event_copy().
1257  *
1258  * Since: 2.2
1259  **/
1260 void
1261 gdk_event_set_screen (GdkEvent  *event,
1262                       GdkScreen *screen)
1263 {
1264   GdkEventPrivate *private;
1265   
1266   g_return_if_fail (gdk_event_is_allocated (event));
1267
1268   private = (GdkEventPrivate *)event;
1269   
1270   private->screen = screen;
1271 }
1272
1273 /**
1274  * gdk_event_get_screen:
1275  * @event: a #GdkEvent
1276  * 
1277  * Returns the screen for the event. The screen is
1278  * typically the screen for <literal>event->any.window</literal>, but
1279  * for events such as mouse events, it is the screen
1280  * where the pointer was when the event occurs -
1281  * that is, the screen which has the root window 
1282  * to which <literal>event->motion.x_root</literal> and
1283  * <literal>event->motion.y_root</literal> are relative.
1284  * 
1285  * Return value: (transfer none): the screen for the event
1286  *
1287  * Since: 2.2
1288  **/
1289 GdkScreen *
1290 gdk_event_get_screen (const GdkEvent *event)
1291 {
1292   if (gdk_event_is_allocated (event))
1293     {
1294       GdkEventPrivate *private = (GdkEventPrivate *)event;
1295
1296       if (private->screen)
1297         return private->screen;
1298     }
1299
1300   if (event->any.window)
1301     return gdk_window_get_screen (event->any.window);
1302
1303   return NULL;
1304 }
1305
1306 /**
1307  * gdk_set_show_events:
1308  * @show_events:  %TRUE to output event debugging information.
1309  * 
1310  * Sets whether a trace of received events is output.
1311  * Note that GTK+ must be compiled with debugging (that is,
1312  * configured using the <option>--enable-debug</option> option)
1313  * to use this option.
1314  **/
1315 void
1316 gdk_set_show_events (gboolean show_events)
1317 {
1318   if (show_events)
1319     _gdk_debug_flags |= GDK_DEBUG_EVENTS;
1320   else
1321     _gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
1322 }
1323
1324 /**
1325  * gdk_get_show_events:
1326  * 
1327  * Gets whether event debugging output is enabled.
1328  * 
1329  * Return value: %TRUE if event debugging output is enabled.
1330  **/
1331 gboolean
1332 gdk_get_show_events (void)
1333 {
1334   return (_gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
1335 }
1336
1337 /* What do we do with G_IO_NVAL?
1338  */
1339 #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
1340 #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
1341 #define EXCEPTION_CONDITION (G_IO_PRI)
1342
1343 static void
1344 gdk_synthesize_click (GdkDisplay *display,
1345                       GdkEvent   *event,
1346                       gint        nclicks)
1347 {
1348   GdkEvent temp_event;
1349   GdkEvent *event_copy;
1350   GList *link;
1351   
1352   g_return_if_fail (event != NULL);
1353   
1354   temp_event = *event;
1355   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
1356
1357   event_copy = gdk_event_copy (&temp_event);
1358   link = _gdk_event_queue_append (display, event_copy);
1359 }
1360
1361 void
1362 _gdk_event_button_generate (GdkDisplay *display,
1363                             GdkEvent   *event)
1364 {
1365   GdkMultipleClickInfo *info;
1366
1367   info = g_hash_table_lookup (display->multiple_click_info, event->button.device);
1368
1369   if (G_UNLIKELY (!info))
1370     {
1371       info = g_new0 (GdkMultipleClickInfo, 1);
1372       info->button_number[0] = info->button_number[1] = -1;
1373
1374       g_hash_table_insert (display->multiple_click_info,
1375                            event->button.device, info);
1376     }
1377
1378   if ((event->button.time < (info->button_click_time[1] + 2 * display->double_click_time)) &&
1379       (event->button.window == info->button_window[1]) &&
1380       (event->button.button == info->button_number[1]) &&
1381       (ABS (event->button.x - info->button_x[1]) <= display->double_click_distance) &&
1382       (ABS (event->button.y - info->button_y[1]) <= display->double_click_distance))
1383     {
1384       gdk_synthesize_click (display, event, 3);
1385
1386       info->button_click_time[1] = 0;
1387       info->button_click_time[0] = 0;
1388       info->button_window[1] = NULL;
1389       info->button_window[0] = NULL;
1390       info->button_number[1] = -1;
1391       info->button_number[0] = -1;
1392       info->button_x[0] = info->button_x[1] = 0;
1393       info->button_y[0] = info->button_y[1] = 0;
1394     }
1395   else if ((event->button.time < (info->button_click_time[0] + display->double_click_time)) &&
1396            (event->button.window == info->button_window[0]) &&
1397            (event->button.button == info->button_number[0]) &&
1398            (ABS (event->button.x - info->button_x[0]) <= display->double_click_distance) &&
1399            (ABS (event->button.y - info->button_y[0]) <= display->double_click_distance))
1400     {
1401       gdk_synthesize_click (display, event, 2);
1402       
1403       info->button_click_time[1] = info->button_click_time[0];
1404       info->button_click_time[0] = event->button.time;
1405       info->button_window[1] = info->button_window[0];
1406       info->button_window[0] = event->button.window;
1407       info->button_number[1] = info->button_number[0];
1408       info->button_number[0] = event->button.button;
1409       info->button_x[1] = info->button_x[0];
1410       info->button_x[0] = event->button.x;
1411       info->button_y[1] = info->button_y[0];
1412       info->button_y[0] = event->button.y;
1413     }
1414   else
1415     {
1416       info->button_click_time[1] = 0;
1417       info->button_click_time[0] = event->button.time;
1418       info->button_window[1] = NULL;
1419       info->button_window[0] = event->button.window;
1420       info->button_number[1] = -1;
1421       info->button_number[0] = event->button.button;
1422       info->button_x[1] = 0;
1423       info->button_x[0] = event->button.x;
1424       info->button_y[1] = 0;
1425       info->button_y[0] = event->button.y;
1426     }
1427 }
1428
1429 void
1430 gdk_synthesize_window_state (GdkWindow     *window,
1431                              GdkWindowState unset_flags,
1432                              GdkWindowState set_flags)
1433 {
1434   GdkEvent temp_event;
1435   GdkWindowState old;
1436   
1437   g_return_if_fail (window != NULL);
1438   
1439   temp_event.window_state.window = window;
1440   temp_event.window_state.type = GDK_WINDOW_STATE;
1441   temp_event.window_state.send_event = FALSE;
1442   
1443   old = temp_event.window_state.window->state;
1444   
1445   temp_event.window_state.new_window_state = old;
1446   temp_event.window_state.new_window_state |= set_flags;
1447   temp_event.window_state.new_window_state &= ~unset_flags;
1448   temp_event.window_state.changed_mask = temp_event.window_state.new_window_state ^ old;
1449
1450   if (temp_event.window_state.new_window_state == old)
1451     return; /* No actual work to do, nothing changed. */
1452
1453   /* Actually update the field in GdkWindow, this is sort of an odd
1454    * place to do it, but seems like the safest since it ensures we expose no
1455    * inconsistent state to the user.
1456    */
1457   
1458   window->state = temp_event.window_state.new_window_state;
1459
1460   if (temp_event.window_state.changed_mask & GDK_WINDOW_STATE_WITHDRAWN)
1461     _gdk_window_update_viewable (window);
1462
1463   /* We only really send the event to toplevels, since
1464    * all the window states don't apply to non-toplevels.
1465    * Non-toplevels do use the GDK_WINDOW_STATE_WITHDRAWN flag
1466    * internally so we needed to update window->state.
1467    */
1468   switch (window->window_type)
1469     {
1470     case GDK_WINDOW_TOPLEVEL:
1471     case GDK_WINDOW_TEMP: /* ? */
1472       gdk_display_put_event (gdk_window_get_display (window), &temp_event);
1473       break;
1474       
1475     case GDK_WINDOW_FOREIGN:
1476     case GDK_WINDOW_ROOT:
1477     case GDK_WINDOW_CHILD:
1478       break;
1479     }
1480 }
1481
1482 /**
1483  * gdk_display_set_double_click_time:
1484  * @display: a #GdkDisplay
1485  * @msec: double click time in milliseconds (thousandths of a second) 
1486  * 
1487  * Sets the double click time (two clicks within this time interval
1488  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1489  * Applications should <emphasis>not</emphasis> set this, it is a global 
1490  * user-configured setting.
1491  *
1492  * Since: 2.2
1493  **/
1494 void
1495 gdk_display_set_double_click_time (GdkDisplay *display,
1496                                    guint       msec)
1497 {
1498   display->double_click_time = msec;
1499 }
1500
1501 /**
1502  * gdk_set_double_click_time:
1503  * @msec: double click time in milliseconds (thousandths of a second)
1504  *
1505  * Set the double click time for the default display. See
1506  * gdk_display_set_double_click_time(). 
1507  * See also gdk_display_set_double_click_distance().
1508  * Applications should <emphasis>not</emphasis> set this, it is a 
1509  * global user-configured setting.
1510  **/
1511 void
1512 gdk_set_double_click_time (guint msec)
1513 {
1514   gdk_display_set_double_click_time (gdk_display_get_default (), msec);
1515 }
1516
1517 /**
1518  * gdk_display_set_double_click_distance:
1519  * @display: a #GdkDisplay
1520  * @distance: distance in pixels
1521  * 
1522  * Sets the double click distance (two clicks within this distance
1523  * count as a double click and result in a #GDK_2BUTTON_PRESS event).
1524  * See also gdk_display_set_double_click_time().
1525  * Applications should <emphasis>not</emphasis> set this, it is a global 
1526  * user-configured setting.
1527  *
1528  * Since: 2.4
1529  **/
1530 void
1531 gdk_display_set_double_click_distance (GdkDisplay *display,
1532                                        guint       distance)
1533 {
1534   display->double_click_distance = distance;
1535 }
1536
1537 G_DEFINE_BOXED_TYPE (GdkEvent, gdk_event,
1538                      gdk_event_copy,
1539                      gdk_event_free)
1540
1541 /**
1542  * gdk_setting_get:
1543  * @name: the name of the setting.
1544  * @value: location to store the value of the setting.
1545  *
1546  * Obtains a desktop-wide setting, such as the double-click time,
1547  * for the default screen. See gdk_screen_get_setting().
1548  *
1549  * Returns: %TRUE if the setting existed and a value was stored
1550  *   in @value, %FALSE otherwise.
1551  **/
1552 gboolean
1553 gdk_setting_get (const gchar *name,
1554                  GValue      *value)
1555 {
1556   return gdk_screen_get_setting (gdk_screen_get_default (), name, value);
1557 }