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