]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
API: gdk: Make gdk_display_get_window_at_device_position() a device API
[~andy/gtk] / gdk / gdkdisplay.c
1 /* GDK - The GIMP Drawing Kit
2  * gdkdisplay.c
3  * 
4  * Copyright 2001 Sun Microsystems Inc. 
5  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25
26 #include "gdkdisplay.h"
27 #include "gdkdisplayprivate.h"
28
29 #include "gdkdeviceprivate.h"
30 #include "gdkevents.h"
31 #include "gdkwindowimpl.h"
32 #include "gdkinternals.h"
33 #include "gdkmarshalers.h"
34 #include "gdkscreen.h"
35
36 #include <glib.h>
37 #include <math.h>
38
39
40 /**
41  * SECTION:gdkdisplay
42  * @Short_description: Controls the keyboard/mouse pointer grabs and a set of <type>GdkScreen</type>s
43  * @Title: GdkDisplay
44  *
45  * #GdkDisplay objects purpose are two fold:
46  * <itemizedlist>
47  * <listitem><para>
48  *   To grab/ungrab keyboard focus and mouse pointer
49  * </para></listitem>
50  * <listitem><para>
51  *   To manage and provide information about the #GdkScreen(s)
52  *   available for this #GdkDisplay
53  * </para></listitem>
54  * </itemizedlist>
55  *
56  * #GdkDisplay objects are the GDK representation of the X Display which can be
57  * described as <emphasis>a workstation consisting of a keyboard a pointing
58  * device (such as a mouse) and one or more screens</emphasis>.
59  * It is used to open and keep track of various #GdkScreen objects currently
60  * instanciated by the application. It is also used to grab and release the keyboard
61  * and the mouse pointer.
62  */
63
64
65 enum {
66   OPENED,
67   CLOSED,
68   LAST_SIGNAL
69 };
70
71 static void gdk_display_dispose     (GObject         *object);
72 static void gdk_display_finalize    (GObject         *object);
73
74 static void        multihead_get_device_state           (GdkDisplay       *display,
75                                                          GdkDevice        *device,
76                                                          GdkScreen       **screen,
77                                                          gint             *x,
78                                                          gint             *y,
79                                                          GdkModifierType  *mask);
80 static GdkWindow * multihead_window_get_device_position (GdkDisplay       *display,
81                                                          GdkDevice        *device,
82                                                          GdkWindow        *window,
83                                                          gint             *x,
84                                                          gint             *y,
85                                                          GdkModifierType  *mask);
86 static GdkWindow * multihead_window_at_device_position  (GdkDisplay       *display,
87                                                          GdkDevice        *device,
88                                                          gint             *win_x,
89                                                          gint             *win_y);
90
91 static void        multihead_default_get_pointer        (GdkDisplay       *display,
92                                                          GdkScreen       **screen,
93                                                          gint             *x,
94                                                          gint             *y,
95                                                          GdkModifierType  *mask);
96 static GdkWindow * multihead_default_window_get_pointer (GdkDisplay      *display,
97                                                          GdkWindow       *window,
98                                                          gint            *x,
99                                                          gint            *y,
100                                                          GdkModifierType *mask);
101 static GdkWindow * multihead_default_window_at_pointer  (GdkDisplay      *display,
102                                                          gint            *win_x,
103                                                          gint            *win_y);
104
105
106 static void       singlehead_get_pointer (GdkDisplay       *display,
107                                           GdkScreen       **screen,
108                                           gint             *x,
109                                           gint             *y,
110                                           GdkModifierType  *mask);
111 static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
112                                                  GdkWindow        *window,
113                                                  gint             *x,
114                                                  gint             *y,
115                                                  GdkModifierType  *mask);
116 static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
117                                                  gint             *win_x,
118                                                  gint             *win_y);
119
120 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
121                                                          gint            *x,
122                                                          gint            *y,
123                                                          GdkModifierType *mask);
124 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
125                                                          gint            *win_x,
126                                                          gint            *win_y);static GdkWindow *gdk_window_real_window_get_device_position     (GdkDisplay       *display,
127                                                                   GdkDevice        *device,
128                                                                   GdkWindow        *window,
129                                                                   gint             *x,
130                                                                   gint             *y,
131                                                                   GdkModifierType  *mask);
132 static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay       *display,
133                                                                   GdkDevice        *device,
134                                                                   gint             *win_x,
135                                                                   gint             *win_y);
136 static void       gdk_display_real_get_device_state              (GdkDisplay       *display,
137                                                                   GdkDevice        *device,
138                                                                   GdkScreen       **screen,
139                                                                   gint             *x,
140                                                                   gint             *y,
141                                                                   GdkModifierType  *mask);
142 static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
143
144 static guint signals[LAST_SIGNAL] = { 0 };
145
146 static const GdkDisplayDeviceHooks default_device_hooks = {
147   gdk_display_real_get_device_state,
148   gdk_window_real_window_get_device_position,
149   gdk_display_real_get_window_at_device_position
150 };
151
152 static const GdkDisplayDeviceHooks multihead_pointer_hooks = {
153   multihead_get_device_state,
154   multihead_window_get_device_position,
155   multihead_window_at_device_position
156 };
157
158 static const GdkDisplayPointerHooks multihead_default_pointer_hooks = {
159   multihead_default_get_pointer,
160   multihead_default_window_get_pointer,
161   multihead_default_window_at_pointer
162 };
163
164 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
165   singlehead_get_pointer,
166   singlehead_window_get_pointer,
167   singlehead_window_at_pointer
168 };
169
170 static const GdkPointerHooks singlehead_default_pointer_hooks = {
171   singlehead_default_window_get_pointer,
172   singlehead_default_window_at_pointer
173 };
174
175 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
176 static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
177
178 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
179
180 static void
181 gdk_display_class_init (GdkDisplayClass *class)
182 {
183   GObjectClass *object_class = G_OBJECT_CLASS (class);
184
185   object_class->finalize = gdk_display_finalize;
186   object_class->dispose = gdk_display_dispose;
187
188   class->get_app_launch_context = gdk_display_real_get_app_launch_context;
189   class->window_type = GDK_TYPE_WINDOW;
190
191   /**
192    * GdkDisplay::opened:
193    * @display: the object on which the signal is emitted
194    *
195    * The ::opened signal is emitted when the connection to the windowing
196    * system for @display is opened.
197    */
198   signals[OPENED] =
199     g_signal_new (g_intern_static_string ("opened"),
200                   G_OBJECT_CLASS_TYPE (object_class),
201                   G_SIGNAL_RUN_LAST,
202                   0, NULL, NULL,
203                   g_cclosure_marshal_VOID__VOID,
204                   G_TYPE_NONE, 0);
205
206   /**
207    * GdkDisplay::closed:
208    * @display: the object on which the signal is emitted
209    * @is_error: %TRUE if the display was closed due to an error
210    *
211    * The ::closed signal is emitted when the connection to the windowing
212    * system for @display is closed.
213    *
214    * Since: 2.2
215    */   
216   signals[CLOSED] =
217     g_signal_new (g_intern_static_string ("closed"),
218                   G_OBJECT_CLASS_TYPE (object_class),
219                   G_SIGNAL_RUN_LAST,
220                   G_STRUCT_OFFSET (GdkDisplayClass, closed),
221                   NULL, NULL,
222                   _gdk_marshal_VOID__BOOLEAN,
223                   G_TYPE_NONE,
224                   1,
225                   G_TYPE_BOOLEAN);
226 }
227
228 static void
229 free_pointer_info (GdkPointerWindowInfo *info)
230 {
231   g_object_unref (info->toplevel_under_pointer);
232   g_slice_free (GdkPointerWindowInfo, info);
233 }
234
235 static void
236 free_device_grab (GdkDeviceGrabInfo *info)
237 {
238   g_object_unref (info->window);
239   g_object_unref (info->native_window);
240   g_free (info);
241 }
242
243 static gboolean
244 free_device_grabs_foreach (gpointer key,
245                            gpointer value,
246                            gpointer user_data)
247 {
248   GList *list = value;
249
250   g_list_foreach (list, (GFunc) free_device_grab, NULL);
251   g_list_free (list);
252
253   return TRUE;
254 }
255
256 static void
257 device_removed_cb (GdkDeviceManager *device_manager,
258                    GdkDevice        *device,
259                    GdkDisplay       *display)
260 {
261   g_hash_table_remove (display->multiple_click_info, device);
262   g_hash_table_remove (display->device_grabs, device);
263   g_hash_table_remove (display->pointers_info, device);
264
265   /* FIXME: change core pointer and remove from device list */
266 }
267
268 static void
269 gdk_display_opened (GdkDisplay *display)
270 {
271   GdkDeviceManager *device_manager;
272
273   device_manager = gdk_display_get_device_manager (display);
274
275   g_signal_connect (device_manager, "device-removed",
276                     G_CALLBACK (device_removed_cb), display);
277 }
278
279 static void
280 gdk_display_init (GdkDisplay *display)
281 {
282   display->double_click_time = 250;
283   display->double_click_distance = 5;
284
285   display->device_hooks = &default_device_hooks;
286
287   display->device_grabs = g_hash_table_new (NULL, NULL);
288   display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
289                                                      (GDestroyNotify) g_free);
290
291   display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
292                                                   (GDestroyNotify) free_pointer_info);
293
294   display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
295                                                         (GDestroyNotify) g_free);
296
297   g_signal_connect (display, "opened",
298                     G_CALLBACK (gdk_display_opened), NULL);
299 }
300
301 static void
302 gdk_display_dispose (GObject *object)
303 {
304   GdkDisplay *display = GDK_DISPLAY (object);
305   GdkDeviceManager *device_manager;
306
307   device_manager = gdk_display_get_device_manager (GDK_DISPLAY (object));
308
309   g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
310   g_list_free (display->queued_events);
311   display->queued_events = NULL;
312   display->queued_tail = NULL;
313
314   if (device_manager)
315     {
316       /* this is to make it drop devices which may require using the X
317        * display and therefore can't be cleaned up in finalize.
318        * It will also disconnect device_removed_cb
319        */
320       g_object_run_dispose (G_OBJECT (display->device_manager));
321     }
322
323   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
324 }
325
326 static void
327 gdk_display_finalize (GObject *object)
328 {
329   GdkDisplay *display = GDK_DISPLAY (object);
330
331   g_hash_table_foreach_remove (display->device_grabs,
332                                free_device_grabs_foreach,
333                                NULL);
334   g_hash_table_destroy (display->device_grabs);
335
336   g_hash_table_destroy (display->pointers_info);
337   g_hash_table_destroy (display->multiple_click_info);
338
339   if (display->device_manager)
340     g_object_unref (display->device_manager);
341
342   G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
343 }
344
345 /**
346  * gdk_display_close:
347  * @display: a #GdkDisplay
348  *
349  * Closes the connection to the windowing system for the given display,
350  * and cleans up associated resources.
351  *
352  * Since: 2.2
353  */
354 void
355 gdk_display_close (GdkDisplay *display)
356 {
357   g_return_if_fail (GDK_IS_DISPLAY (display));
358
359   if (!display->closed)
360     {
361       display->closed = TRUE;
362       
363       g_signal_emit (display, signals[CLOSED], 0, FALSE);
364       g_object_run_dispose (G_OBJECT (display));
365       
366       g_object_unref (display);
367     }
368 }
369
370 /**
371  * gdk_display_is_closed:
372  * @display: a #GdkDisplay
373  *
374  * Finds out if the display has been closed.
375  *
376  * Returns: %TRUE if the display is closed.
377  *
378  * Since: 2.22
379  */
380 gboolean
381 gdk_display_is_closed  (GdkDisplay  *display)
382 {
383   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
384
385   return display->closed;
386 }
387
388 /**
389  * gdk_display_get_event:
390  * @display: a #GdkDisplay
391  * 
392  * Gets the next #GdkEvent to be processed for @display, fetching events from the
393  * windowing system if necessary.
394  * 
395  * Return value: the next #GdkEvent to be processed, or %NULL if no events
396  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
397  *
398  * Since: 2.2
399  **/
400 GdkEvent*
401 gdk_display_get_event (GdkDisplay *display)
402 {
403   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
404
405   GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
406   return _gdk_event_unqueue (display);
407 }
408
409 /**
410  * gdk_display_peek_event:
411  * @display: a #GdkDisplay 
412  * 
413  * Gets a copy of the first #GdkEvent in the @display's event queue, without
414  * removing the event from the queue.  (Note that this function will
415  * not get more events from the windowing system.  It only checks the events
416  * that have already been moved to the GDK event queue.)
417  * 
418  * Return value: a copy of the first #GdkEvent on the event queue, or %NULL 
419  * if no events are in the queue. The returned #GdkEvent should be freed with
420  * gdk_event_free().
421  *
422  * Since: 2.2
423  **/
424 GdkEvent*
425 gdk_display_peek_event (GdkDisplay *display)
426 {
427   GList *tmp_list;
428
429   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
430
431   tmp_list = _gdk_event_queue_find_first (display);
432   
433   if (tmp_list)
434     return gdk_event_copy (tmp_list->data);
435   else
436     return NULL;
437 }
438
439 /**
440  * gdk_display_put_event:
441  * @display: a #GdkDisplay
442  * @event: a #GdkEvent.
443  *
444  * Appends a copy of the given event onto the front of the event
445  * queue for @display.
446  *
447  * Since: 2.2
448  **/
449 void
450 gdk_display_put_event (GdkDisplay     *display,
451                        const GdkEvent *event)
452 {
453   g_return_if_fail (GDK_IS_DISPLAY (display));
454   g_return_if_fail (event != NULL);
455
456   _gdk_event_queue_append (display, gdk_event_copy (event));
457   /* If the main loop is blocking in a different thread, wake it up */
458   g_main_context_wakeup (NULL); 
459 }
460
461 /**
462  * gdk_display_pointer_ungrab:
463  * @display: a #GdkDisplay.
464  * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
465  *
466  * Release any pointer grab.
467  *
468  * Since: 2.2
469  *
470  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
471  *             instead.
472  */
473 void
474 gdk_display_pointer_ungrab (GdkDisplay *display,
475                             guint32     time_)
476 {
477   GdkDeviceManager *device_manager;
478   GList *devices, *dev;
479   GdkDevice *device;
480
481   g_return_if_fail (GDK_IS_DISPLAY (display));
482
483   device_manager = gdk_display_get_device_manager (display);
484   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
485
486   /* FIXME: Should this be generic to all backends? */
487   /* FIXME: What happens with extended devices? */
488   for (dev = devices; dev; dev = dev->next)
489     {
490       device = dev->data;
491
492       if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
493         continue;
494
495       gdk_device_ungrab (device, time_);
496     }
497
498   g_list_free (devices);
499 }
500
501 /**
502  * gdk_pointer_ungrab:
503  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
504  *  timestamp is available.
505  *
506  * Ungrabs the pointer on the default display, if it is grabbed by this 
507  * application.
508  *
509  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
510  *             instead.
511  **/
512 void
513 gdk_pointer_ungrab (guint32 time)
514 {
515   gdk_display_pointer_ungrab (gdk_display_get_default (), time);
516 }
517
518 /**
519  * gdk_pointer_is_grabbed:
520  * 
521  * Returns %TRUE if the pointer on the default display is currently 
522  * grabbed by this application.
523  *
524  * Note that this does not take the inmplicit pointer grab on button
525  * presses into account.
526  *
527  * Return value: %TRUE if the pointer is currently grabbed by this application.
528  *
529  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
530  **/
531 gboolean
532 gdk_pointer_is_grabbed (void)
533 {
534   return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
535 }
536
537 /**
538  * gdk_display_keyboard_ungrab:
539  * @display: a #GdkDisplay.
540  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
541  *
542  * Release any keyboard grab
543  *
544  * Since: 2.2
545  *
546  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
547  *             instead.
548  */
549 void
550 gdk_display_keyboard_ungrab (GdkDisplay *display,
551                              guint32     time)
552 {
553   GdkDeviceManager *device_manager;
554   GList *devices, *dev;
555   GdkDevice *device;
556
557   g_return_if_fail (GDK_IS_DISPLAY (display));
558
559   device_manager = gdk_display_get_device_manager (display);
560   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
561
562   /* FIXME: Should this be generic to all backends? */
563   /* FIXME: What happens with extended devices? */
564   for (dev = devices; dev; dev = dev->next)
565     {
566       device = dev->data;
567
568       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
569         continue;
570
571       gdk_device_ungrab (device, time);
572     }
573
574   g_list_free (devices);
575 }
576
577 /**
578  * gdk_keyboard_ungrab:
579  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
580  *        timestamp is available.
581  * 
582  * Ungrabs the keyboard on the default display, if it is grabbed by this 
583  * application.
584  *
585  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
586  *             instead.
587  **/
588 void
589 gdk_keyboard_ungrab (guint32 time)
590 {
591   gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
592 }
593
594 /**
595  * gdk_beep:
596  * 
597  * Emits a short beep on the default display.
598  **/
599 void
600 gdk_beep (void)
601 {
602   gdk_display_beep (gdk_display_get_default ());
603 }
604
605 /**
606  * gdk_flush:
607  *
608  * Flushes the output buffers of all display connections and waits
609  * until all requests have been processed.
610  * This is rarely needed by applications.
611  */
612 void
613 gdk_flush (void)
614 {
615   GSList *list, *l;
616
617   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
618   for (l = list; l; l = l->next)
619     {
620       GdkDisplay *display = l->data;
621
622       GDK_DISPLAY_GET_CLASS (display)->sync (display);
623     }
624
625   g_slist_free (list);
626 }
627
628 /**
629  * gdk_event_send_client_message:
630  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
631  * @winid:  the window to send the X ClientMessage event to.
632  * 
633  * Sends an X ClientMessage event to a given window (which must be
634  * on the default #GdkDisplay.)
635  * This could be used for communicating between different applications,
636  * though the amount of data is limited to 20 bytes.
637  * 
638  * Return value: non-zero on success.
639  **/
640 gboolean
641 gdk_event_send_client_message (GdkEvent        *event,
642                                GdkNativeWindow  winid)
643 {
644   g_return_val_if_fail (event != NULL, FALSE);
645
646   return gdk_event_send_client_message_for_display (gdk_display_get_default (),
647                                                     event, winid);
648 }
649
650 /**
651  * gdk_event_send_clientmessage_toall:
652  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
653  *
654  * Sends an X ClientMessage event to all toplevel windows on the default
655  * #GdkScreen.
656  *
657  * Toplevel windows are determined by checking for the WM_STATE property, as
658  * described in the Inter-Client Communication Conventions Manual (ICCCM).
659  * If no windows are found with the WM_STATE property set, the message is sent
660  * to all children of the root window.
661  **/
662 void
663 gdk_event_send_clientmessage_toall (GdkEvent *event)
664 {
665   g_return_if_fail (event != NULL);
666
667   gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
668 }
669
670 void
671 _gdk_display_enable_motion_hints (GdkDisplay *display,
672                                   GdkDevice  *device)
673 {
674   gulong *device_serial, serial;
675
676   device_serial = g_hash_table_lookup (display->motion_hint_info, device);
677
678   if (!device_serial)
679     {
680       device_serial = g_new0 (gulong, 1);
681       *device_serial = G_MAXULONG;
682       g_hash_table_insert (display->motion_hint_info, device, device_serial);
683     }
684
685   if (*device_serial != 0)
686     {
687       serial = _gdk_display_get_next_serial (display);
688       /* We might not actually generate the next request, so
689          make sure this triggers always, this may cause it to
690          trigger slightly too early, but this is just a hint
691          anyway. */
692       if (serial > 0)
693         serial--;
694       if (serial < *device_serial)
695         *device_serial = serial;
696     }
697 }
698
699 /**
700  * gdk_display_set_device_hooks:
701  * @display: a #GdkDisplay.
702  * @new_hooks: (allow-none): a table of pointers to functions for getting quantities related
703  *             to all devices position, or %NULL to restore the default table.
704  *
705  * This function allows for hooking into the operation of getting the current location of any
706  * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
707  * an event recorder. Applications should never have any reason to use this facility.
708  *
709  * Returns: (transfer none): The previous device hook table.
710  *
711  * Since: 3.0
712  **/
713 GdkDisplayDeviceHooks *
714 gdk_display_set_device_hooks (GdkDisplay                  *display,
715                               const GdkDisplayDeviceHooks *new_hooks)
716 {
717   const GdkDisplayDeviceHooks *result;
718
719   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
720   result = display->device_hooks;
721
722   if (new_hooks)
723     display->device_hooks = new_hooks;
724   else
725     display->device_hooks = &default_device_hooks;
726
727   return (GdkDisplayDeviceHooks *) result;
728 }
729
730 /**
731  * gdk_display_get_pointer:
732  * @display: a #GdkDisplay
733  * @screen: (allow-none): location to store the screen that the
734  *          cursor is on, or %NULL.
735  * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
736  * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
737  * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
738  *
739  * Gets the current location of the pointer and the current modifier
740  * mask for a given display.
741  *
742  * Since: 2.2
743  *
744  * Deprecated: 3.0: Use gdk_device_get_position() instead.
745  **/
746 void
747 gdk_display_get_pointer (GdkDisplay      *display,
748                          GdkScreen      **screen,
749                          gint            *x,
750                          gint            *y,
751                          GdkModifierType *mask)
752 {
753   GdkScreen *tmp_screen;
754   gint tmp_x, tmp_y;
755   GdkModifierType tmp_mask;
756
757   g_return_if_fail (GDK_IS_DISPLAY (display));
758
759   /* We call get_device_state here manually instead of gdk_device_get_position()
760    * because we also care about the modifier mask */
761
762   display->device_hooks->get_device_state (display,
763                                            display->core_pointer,
764                                            &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
765   if (screen)
766     *screen = tmp_screen;
767   if (x)
768     *x = tmp_x;
769   if (y)
770     *y = tmp_y;
771   if (mask)
772     *mask = tmp_mask;
773 }
774
775 static GdkWindow *
776 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
777                                                 GdkDevice  *device,
778                                                 gint       *win_x,
779                                                 gint       *win_y)
780 {
781   GdkWindow *window;
782   gint x, y;
783
784   window = _gdk_device_window_at_position (device, &x, &y, NULL, FALSE);
785
786   /* This might need corrections, as the native window returned
787      may contain client side children */
788   if (window)
789     {
790       double xx, yy;
791
792       window = _gdk_window_find_descendant_at (window,
793                                                x, y,
794                                                &xx, &yy);
795       x = floor (xx + 0.5);
796       y = floor (yy + 0.5);
797     }
798
799   *win_x = x;
800   *win_y = y;
801
802   return window;
803 }
804
805 static GdkWindow *
806 gdk_window_real_window_get_device_position (GdkDisplay       *display,
807                                             GdkDevice        *device,
808                                             GdkWindow        *window,
809                                             gint             *x,
810                                             gint             *y,
811                                             GdkModifierType  *mask)
812 {
813   gint tmpx, tmpy;
814   GdkModifierType tmp_mask;
815   gboolean normal_child;
816
817   normal_child = GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_device_state (window,
818                                                                               device,
819                                                                               &tmpx, &tmpy,
820                                                                               &tmp_mask);
821   /* We got the coords on the impl, convert to the window */
822   tmpx -= window->abs_x;
823   tmpy -= window->abs_y;
824
825   if (x)
826     *x = tmpx;
827   if (y)
828     *y = tmpy;
829   if (mask)
830     *mask = tmp_mask;
831
832   if (normal_child)
833     return _gdk_window_find_child_at (window, tmpx, tmpy);
834   return NULL;
835 }
836
837 /**
838  * gdk_display_get_window_at_pointer:
839  * @display: a #GdkDisplay
840  * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
841  *    to the window origin, or %NULL
842  * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
843  &    to the window origin, or %NULL
844  *
845  * Obtains the window underneath the mouse pointer, returning the location
846  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
847  * if the window under the mouse pointer is not known to GDK (for example, 
848  * belongs to another application).
849  *
850  * Returns: (transfer none): the window under the mouse pointer, or %NULL
851  *
852  * Since: 2.2
853  *
854  * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead.
855  **/
856 GdkWindow *
857 gdk_display_get_window_at_pointer (GdkDisplay *display,
858                                    gint       *win_x,
859                                    gint       *win_y)
860 {
861   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
862
863   return gdk_device_get_window_at_position (display->core_pointer, win_x, win_y);
864 }
865
866 static void
867 multihead_get_device_state (GdkDisplay       *display,
868                             GdkDevice        *device,
869                             GdkScreen       **screen,
870                             gint             *x,
871                             gint             *y,
872                             GdkModifierType  *mask)
873 {
874   multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
875 }
876
877 static GdkWindow *
878 multihead_window_get_device_position (GdkDisplay      *display,
879                                       GdkDevice       *device,
880                                       GdkWindow       *window,
881                                       gint            *x,
882                                       gint            *y,
883                                       GdkModifierType *mask)
884 {
885   return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
886 }
887
888 static GdkWindow *
889 multihead_window_at_device_position (GdkDisplay *display,
890                                      GdkDevice  *device,
891                                      gint       *win_x,
892                                      gint       *win_y)
893 {
894   return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
895 }
896
897 static void
898 gdk_display_real_get_device_state (GdkDisplay       *display,
899                                    GdkDevice        *device,
900                                    GdkScreen       **screen,
901                                    gint             *x,
902                                    gint             *y,
903                                    GdkModifierType  *mask)
904 {
905   GdkScreen *default_screen;
906   GdkWindow *root;
907
908   if (gdk_display_is_closed (display))
909     return;
910
911   default_screen = gdk_display_get_default_screen (display);
912
913   _gdk_device_query_state (device,
914                            gdk_screen_get_root_window (default_screen),
915                            &root, NULL,
916                            x, y,
917                            NULL, NULL,
918                            mask);
919
920   *screen = gdk_window_get_screen (root);
921 }
922
923 static void
924 multihead_default_get_pointer (GdkDisplay       *display,
925                                GdkScreen       **screen,
926                                gint             *x,
927                                gint             *y,
928                                GdkModifierType  *mask)
929 {
930   gdk_display_real_get_device_state (display, display->core_pointer,
931                                      screen, x, y, mask);
932 }
933
934 static GdkWindow *
935 multihead_default_window_get_pointer (GdkDisplay      *display,
936                                       GdkWindow       *window,
937                                       gint            *x,
938                                       gint            *y,
939                                       GdkModifierType *mask)
940 {
941   return gdk_window_real_window_get_device_position (display,
942                                                      display->core_pointer,
943                                                      window, x, y, mask);
944 }
945
946 static GdkWindow *
947 multihead_default_window_at_pointer (GdkDisplay *display,
948                                      gint       *win_x,
949                                      gint       *win_y)
950 {
951   return gdk_display_real_get_window_at_device_position (display,
952                                                          display->core_pointer,
953                                                          win_x, win_y);
954 }
955
956 /**
957  * gdk_display_set_pointer_hooks:
958  * @display: a #GdkDisplay
959  * @new_hooks: (allow-none): a table of pointers to functions for getting
960  *   quantities related to the current pointer position,
961  *   or %NULL to restore the default table.
962  * 
963  * This function allows for hooking into the operation
964  * of getting the current location of the pointer on a particular
965  * display. This is only useful for such low-level tools as an
966  * event recorder. Applications should never have any
967  * reason to use this facility.
968  *
969  * Return value: (transfer none): the previous pointer hook table
970  *
971  * Since: 2.2
972  *
973  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
974  **/
975 GdkDisplayPointerHooks *
976 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
977                                const GdkDisplayPointerHooks *new_hooks)
978 {
979   const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
980
981   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
982
983   if (new_hooks)
984     multihead_current_pointer_hooks = new_hooks;
985   else
986     multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
987
988   gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
989
990   return (GdkDisplayPointerHooks *)result;
991 }
992
993 static void
994 singlehead_get_pointer (GdkDisplay       *display,
995                         GdkScreen       **screen,
996                         gint             *x,
997                         gint             *y,
998                         GdkModifierType  *mask)
999 {
1000   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1001   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1002
1003   *screen = default_screen;
1004
1005   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1006 }
1007
1008 static GdkWindow*
1009 singlehead_window_get_pointer (GdkDisplay       *display,
1010                                GdkWindow        *window,
1011                                gint             *x,
1012                                gint             *y,
1013                                GdkModifierType  *mask)
1014 {
1015   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1016 }
1017
1018 static GdkWindow*
1019 singlehead_window_at_pointer   (GdkDisplay *display,
1020                                 gint       *win_x,
1021                                 gint       *win_y)
1022 {
1023   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1024
1025   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1026                                                               win_x, win_y);
1027 }
1028
1029 static GdkWindow*
1030 singlehead_default_window_get_pointer (GdkWindow       *window,
1031                                        gint            *x,
1032                                        gint            *y,
1033                                        GdkModifierType *mask)
1034 {
1035   GdkDisplay *display;
1036
1037   display = gdk_window_get_display (window);
1038
1039   return gdk_window_real_window_get_device_position (display,
1040                                                      display->core_pointer,
1041                                                      window, x, y, mask);
1042 }
1043
1044 static GdkWindow*
1045 singlehead_default_window_at_pointer  (GdkScreen       *screen,
1046                                        gint            *win_x,
1047                                        gint            *win_y)
1048 {
1049   GdkDisplay *display;
1050
1051   display = gdk_screen_get_display (screen);
1052
1053   return gdk_display_real_get_window_at_device_position (display,
1054                                                          display->core_pointer,
1055                                                          win_x, win_y);
1056 }
1057
1058 /**
1059  * gdk_set_pointer_hooks:
1060  * @new_hooks: (allow-none): a table of pointers to functions for getting
1061  *   quantities related to the current pointer position,
1062  *   or %NULL to restore the default table.
1063  * 
1064  * This function allows for hooking into the operation
1065  * of getting the current location of the pointer. This
1066  * is only useful for such low-level tools as an
1067  * event recorder. Applications should never have any
1068  * reason to use this facility.
1069  *
1070  * This function is not multihead safe. For multihead operation,
1071  * see gdk_display_set_pointer_hooks().
1072  * 
1073  * Return value: the previous pointer hook table
1074  *
1075  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1076  **/
1077 GdkPointerHooks *
1078 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1079 {
1080   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1081
1082   if (new_hooks)
1083     singlehead_current_pointer_hooks = new_hooks;
1084   else
1085     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1086
1087   gdk_display_set_pointer_hooks (gdk_display_get_default (),
1088                                  &singlehead_pointer_hooks);
1089   
1090   return (GdkPointerHooks *)result;
1091 }
1092
1093 static void
1094 generate_grab_broken_event (GdkWindow *window,
1095                             GdkDevice *device,
1096                             gboolean   implicit,
1097                             GdkWindow *grab_window)
1098 {
1099   g_return_if_fail (window != NULL);
1100
1101   if (!GDK_WINDOW_DESTROYED (window))
1102     {
1103       GdkEvent *event;
1104
1105       event = gdk_event_new (GDK_GRAB_BROKEN);
1106       event->grab_broken.window = g_object_ref (window);
1107       event->grab_broken.send_event = FALSE;
1108       event->grab_broken.implicit = implicit;
1109       event->grab_broken.grab_window = grab_window;
1110       gdk_event_set_device (event, device);
1111       event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1112
1113       gdk_event_put (event);
1114       gdk_event_free (event);
1115     }
1116 }
1117
1118 GdkDeviceGrabInfo *
1119 _gdk_display_get_last_device_grab (GdkDisplay *display,
1120                                    GdkDevice  *device)
1121 {
1122   GList *l;
1123
1124   l = g_hash_table_lookup (display->device_grabs, device);
1125
1126   if (l)
1127     {
1128       l = g_list_last (l);
1129       return l->data;
1130     }
1131
1132   return NULL;
1133 }
1134
1135 GdkDeviceGrabInfo *
1136 _gdk_display_add_device_grab (GdkDisplay       *display,
1137                               GdkDevice        *device,
1138                               GdkWindow        *window,
1139                               GdkWindow        *native_window,
1140                               GdkGrabOwnership  grab_ownership,
1141                               gboolean          owner_events,
1142                               GdkEventMask      event_mask,
1143                               unsigned long     serial_start,
1144                               guint32           time,
1145                               gboolean          implicit)
1146 {
1147   GdkDeviceGrabInfo *info, *other_info;
1148   GList *grabs, *l;
1149
1150   info = g_new0 (GdkDeviceGrabInfo, 1);
1151
1152   info->window = g_object_ref (window);
1153   info->native_window = g_object_ref (native_window);
1154   info->serial_start = serial_start;
1155   info->serial_end = G_MAXULONG;
1156   info->owner_events = owner_events;
1157   info->event_mask = event_mask;
1158   info->time = time;
1159   info->implicit = implicit;
1160   info->ownership = grab_ownership;
1161
1162   grabs = g_hash_table_lookup (display->device_grabs, device);
1163
1164   /* Find the first grab that has a larger start time (if any) and insert
1165    * before that. I.E we insert after already existing grabs with same
1166    * start time */
1167   for (l = grabs; l != NULL; l = l->next)
1168     {
1169       other_info = l->data;
1170
1171       if (info->serial_start < other_info->serial_start)
1172         break;
1173     }
1174
1175   grabs = g_list_insert_before (grabs, l, info);
1176
1177   /* Make sure the new grab end before next grab */
1178   if (l)
1179     {
1180       other_info = l->data;
1181       info->serial_end = other_info->serial_start;
1182     }
1183
1184   /* Find any previous grab and update its end time */
1185   l = g_list_find (grabs, info);
1186   l = l->prev;
1187   if (l)
1188     {
1189       other_info = l->data;
1190       other_info->serial_end = serial_start;
1191     }
1192
1193   g_hash_table_insert (display->device_grabs, device, grabs);
1194
1195   return info;
1196 }
1197
1198 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1199    This function splits things into two calls if needed, converting the
1200    coordinates to the right toplevel */
1201 static void
1202 synthesize_crossing_events (GdkDisplay      *display,
1203                             GdkDevice       *device,
1204                             GdkDevice       *source_device,
1205                             GdkWindow       *src_window,
1206                             GdkWindow       *dest_window,
1207                             GdkCrossingMode  crossing_mode,
1208                             guint32          time,
1209                             gulong           serial)
1210 {
1211   GdkWindow *src_toplevel, *dest_toplevel;
1212   GdkModifierType state;
1213   int x, y;
1214
1215   /* We use the native crossing events if all native */
1216   if (_gdk_native_windows)
1217     return;
1218   
1219   if (src_window)
1220     src_toplevel = gdk_window_get_toplevel (src_window);
1221   else
1222     src_toplevel = NULL;
1223   if (dest_window)
1224     dest_toplevel = gdk_window_get_toplevel (dest_window);
1225   else
1226     dest_toplevel = NULL;
1227
1228   if (src_toplevel == NULL && dest_toplevel == NULL)
1229     return;
1230   
1231   if (src_toplevel == NULL ||
1232       src_toplevel == dest_toplevel)
1233     {
1234       /* Same toplevels */
1235       gdk_window_get_pointer (dest_toplevel,
1236                               &x, &y, &state);
1237       _gdk_synthesize_crossing_events (display,
1238                                        src_window,
1239                                        dest_window,
1240                                        device, source_device,
1241                                        crossing_mode,
1242                                        x, y, state,
1243                                        time,
1244                                        NULL,
1245                                        serial, FALSE);
1246     }
1247   else if (dest_toplevel == NULL)
1248     {
1249       gdk_window_get_pointer (src_toplevel,
1250                               &x, &y, &state);
1251       _gdk_synthesize_crossing_events (display,
1252                                        src_window,
1253                                        NULL,
1254                                        device, source_device,
1255                                        crossing_mode,
1256                                        x, y, state,
1257                                        time,
1258                                        NULL,
1259                                        serial, FALSE);
1260     }
1261   else
1262     {
1263       /* Different toplevels */
1264       gdk_window_get_pointer (src_toplevel,
1265                               &x, &y, &state);
1266       _gdk_synthesize_crossing_events (display,
1267                                        src_window,
1268                                        NULL,
1269                                        device, source_device,
1270                                        crossing_mode,
1271                                        x, y, state,
1272                                        time,
1273                                        NULL,
1274                                        serial, FALSE);
1275       gdk_window_get_pointer (dest_toplevel,
1276                               &x, &y, &state);
1277       _gdk_synthesize_crossing_events (display,
1278                                        NULL,
1279                                        dest_window,
1280                                        device, source_device,
1281                                        crossing_mode,
1282                                        x, y, state,
1283                                        time,
1284                                        NULL,
1285                                        serial, FALSE);
1286     }
1287 }
1288
1289 static GdkWindow *
1290 get_current_toplevel (GdkDisplay      *display,
1291                       GdkDevice       *device,
1292                       int             *x_out,
1293                       int             *y_out,
1294                       GdkModifierType *state_out)
1295 {
1296   GdkWindow *pointer_window;
1297   int x, y;
1298   GdkModifierType state;
1299
1300   pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
1301
1302   if (pointer_window != NULL &&
1303       (GDK_WINDOW_DESTROYED (pointer_window) ||
1304        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1305        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1306     pointer_window = NULL;
1307
1308   *x_out = x;
1309   *y_out = y;
1310   *state_out = state;
1311
1312   return pointer_window;
1313 }
1314
1315 static void
1316 switch_to_pointer_grab (GdkDisplay        *display,
1317                         GdkDevice         *device,
1318                         GdkDevice         *source_device,
1319                         GdkDeviceGrabInfo *grab,
1320                         GdkDeviceGrabInfo *last_grab,
1321                         guint32            time,
1322                         gulong             serial)
1323 {
1324   GdkWindow *src_window, *pointer_window, *new_toplevel;
1325   GdkPointerWindowInfo *info;
1326   GList *old_grabs;
1327   GdkModifierType state;
1328   int x, y;
1329
1330   /* Temporarily unset pointer to make sure we send the crossing events below */
1331   old_grabs = g_hash_table_lookup (display->device_grabs, device);
1332   g_hash_table_steal (display->device_grabs, device);
1333   info = _gdk_display_get_pointer_info (display, device);
1334
1335   if (grab)
1336     {
1337       /* New grab is in effect */
1338
1339       /* We need to generate crossing events for the grab.
1340        * However, there are never any crossing events for implicit grabs
1341        * TODO: ... Actually, this could happen if the pointer window
1342        *           doesn't have button mask so a parent gets the event...
1343        */
1344       if (!grab->implicit)
1345         {
1346           /* We send GRAB crossing events from the window under the pointer to the
1347              grab window. Except if there is an old grab then we start from that */
1348           if (last_grab)
1349             src_window = last_grab->window;
1350           else
1351             src_window = info->window_under_pointer;
1352
1353           if (src_window != grab->window)
1354             synthesize_crossing_events (display, device, source_device,
1355                                         src_window, grab->window,
1356                                         GDK_CROSSING_GRAB, time, serial);
1357
1358           /* !owner_event Grabbing a window that we're not inside, current status is
1359              now NULL (i.e. outside grabbed window) */
1360           if (!grab->owner_events && info->window_under_pointer != grab->window)
1361             _gdk_display_set_window_under_pointer (display, device, NULL);
1362         }
1363
1364       grab->activated = TRUE;
1365     }
1366
1367   if (last_grab)
1368     {
1369       new_toplevel = NULL;
1370
1371       if (grab == NULL /* ungrab */ ||
1372           (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1373         {
1374           /* We force check what window we're in, and update the toplevel_under_pointer info,
1375            * as that won't get told of this change with toplevel enter events.
1376            */
1377           if (info->toplevel_under_pointer)
1378             g_object_unref (info->toplevel_under_pointer);
1379           info->toplevel_under_pointer = NULL;
1380
1381           new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1382           if (new_toplevel)
1383             {
1384               /* w is now toplevel and x,y in toplevel coords */
1385               info->toplevel_under_pointer = g_object_ref (new_toplevel);
1386               info->toplevel_x = x;
1387               info->toplevel_y = y;
1388               info->state = state;
1389             }
1390         }
1391
1392       if (grab == NULL) /* Ungrabbed, send events */
1393         {
1394           pointer_window = NULL;
1395           if (new_toplevel)
1396             {
1397               /* Find (possibly virtual) child window */
1398               pointer_window =
1399                 _gdk_window_find_descendant_at (new_toplevel,
1400                                                 x, y,
1401                                                 NULL, NULL);
1402             }
1403
1404           if (pointer_window != last_grab->window)
1405             synthesize_crossing_events (display, device, source_device,
1406                                         last_grab->window, pointer_window,
1407                                         GDK_CROSSING_UNGRAB, time, serial);
1408
1409           /* We're now ungrabbed, update the window_under_pointer */
1410           _gdk_display_set_window_under_pointer (display, device, pointer_window);
1411         }
1412     }
1413
1414   g_hash_table_insert (display->device_grabs, device, old_grabs);
1415 }
1416
1417 void
1418 _gdk_display_device_grab_update (GdkDisplay *display,
1419                                  GdkDevice  *device,
1420                                  GdkDevice  *source_device,
1421                                  gulong      current_serial)
1422 {
1423   GdkDeviceGrabInfo *current_grab, *next_grab;
1424   GList *grabs;
1425   guint32 time;
1426
1427   time = display->last_event_time;
1428   grabs = g_hash_table_lookup (display->device_grabs, device);
1429
1430   while (grabs != NULL)
1431     {
1432       current_grab = grabs->data;
1433
1434       if (current_grab->serial_start > current_serial)
1435         return; /* Hasn't started yet */
1436
1437       if (current_grab->serial_end > current_serial)
1438         {
1439           /* This one hasn't ended yet.
1440              its the currently active one or scheduled to be active */
1441
1442           if (!current_grab->activated)
1443             {
1444               if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1445                 switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
1446             }
1447
1448           break;
1449         }
1450
1451       next_grab = NULL;
1452       if (grabs->next)
1453         {
1454           /* This is the next active grab */
1455           next_grab = grabs->next->data;
1456
1457           if (next_grab->serial_start > current_serial)
1458             next_grab = NULL; /* Actually its not yet active */
1459         }
1460
1461       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1462           (next_grab != NULL && current_grab->window != next_grab->window))
1463         generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1464                                     device,
1465                                     current_grab->implicit,
1466                                     next_grab? next_grab->window : NULL);
1467
1468       /* Remove old grab */
1469       grabs = g_list_delete_link (grabs, grabs);
1470       g_hash_table_insert (display->device_grabs, device, grabs);
1471
1472       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1473         switch_to_pointer_grab (display, device, source_device,
1474                                 next_grab, current_grab,
1475                                 time, current_serial);
1476
1477       free_device_grab (current_grab);
1478     }
1479 }
1480
1481 static GList *
1482 grab_list_find (GList  *grabs,
1483                 gulong  serial)
1484 {
1485   GdkDeviceGrabInfo *grab;
1486
1487   while (grabs)
1488     {
1489       grab = grabs->data;
1490
1491       if (serial >= grab->serial_start && serial < grab->serial_end)
1492         return grabs;
1493
1494       grabs = grabs->next;
1495     }
1496
1497   return NULL;
1498 }
1499
1500 static GList *
1501 find_device_grab (GdkDisplay *display,
1502                    GdkDevice  *device,
1503                    gulong      serial)
1504 {
1505   GList *l;
1506
1507   l = g_hash_table_lookup (display->device_grabs, device);
1508   return grab_list_find (l, serial);
1509 }
1510
1511 GdkDeviceGrabInfo *
1512 _gdk_display_has_device_grab (GdkDisplay *display,
1513                               GdkDevice  *device,
1514                               gulong      serial)
1515 {
1516   GList *l;
1517
1518   l = find_device_grab (display, device, serial);
1519   if (l)
1520     return l->data;
1521
1522   return NULL;
1523 }
1524
1525 /* Returns true if last grab was ended
1526  * If if_child is non-NULL, end the grab only if the grabbed
1527  * window is the same as if_child or a descendant of it */
1528 gboolean
1529 _gdk_display_end_device_grab (GdkDisplay *display,
1530                               GdkDevice  *device,
1531                               gulong      serial,
1532                               GdkWindow  *if_child,
1533                               gboolean    implicit)
1534 {
1535   GdkDeviceGrabInfo *grab;
1536   GList *l;
1537
1538   l = find_device_grab (display, device, serial);
1539
1540   if (l == NULL)
1541     return FALSE;
1542
1543   grab = l->data;
1544   if (grab &&
1545       (if_child == NULL ||
1546        _gdk_window_event_parent_of (if_child, grab->window)))
1547     {
1548       grab->serial_end = serial;
1549       grab->implicit_ungrab = implicit;
1550       return l->next == NULL;
1551     }
1552   
1553   return FALSE;
1554 }
1555
1556 /* Returns TRUE if device events are not blocked by any grab */
1557 gboolean
1558 _gdk_display_check_grab_ownership (GdkDisplay *display,
1559                                    GdkDevice  *device,
1560                                    gulong      serial)
1561 {
1562   GHashTableIter iter;
1563   gpointer key, value;
1564   GdkGrabOwnership higher_ownership, device_ownership;
1565   gboolean device_is_keyboard;
1566
1567   g_hash_table_iter_init (&iter, display->device_grabs);
1568   higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1569   device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1570
1571   while (g_hash_table_iter_next (&iter, &key, &value))
1572     {
1573       GdkDeviceGrabInfo *grab;
1574       GdkDevice *dev;
1575       GList *grabs;
1576
1577       dev = key;
1578       grabs = value;
1579       grabs = grab_list_find (grabs, serial);
1580
1581       if (!grabs)
1582         continue;
1583
1584       /* Discard device if it's not of the same type */
1585       if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) ||
1586           (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD))
1587         continue;
1588
1589       grab = grabs->data;
1590
1591       if (dev == device)
1592         device_ownership = grab->ownership;
1593       else
1594         {
1595           if (grab->ownership > higher_ownership)
1596             higher_ownership = grab->ownership;
1597         }
1598     }
1599
1600   if (higher_ownership > device_ownership)
1601     {
1602       /* There's a higher priority ownership
1603        * going on for other device(s)
1604        */
1605       return FALSE;
1606     }
1607
1608   return TRUE;
1609 }
1610
1611 GdkPointerWindowInfo *
1612 _gdk_display_get_pointer_info (GdkDisplay *display,
1613                                GdkDevice  *device)
1614 {
1615   GdkPointerWindowInfo *info;
1616
1617   if (G_UNLIKELY (!device))
1618     return NULL;
1619
1620   info = g_hash_table_lookup (display->pointers_info, device);
1621
1622   if (G_UNLIKELY (!info))
1623     {
1624       info = g_slice_new0 (GdkPointerWindowInfo);
1625       g_hash_table_insert (display->pointers_info, device, info);
1626     }
1627
1628   return info;
1629 }
1630
1631 void
1632 _gdk_display_pointer_info_foreach (GdkDisplay                   *display,
1633                                    GdkDisplayPointerInfoForeach  func,
1634                                    gpointer                      user_data)
1635 {
1636   GHashTableIter iter;
1637   gpointer key, value;
1638
1639   g_hash_table_iter_init (&iter, display->pointers_info);
1640
1641   while (g_hash_table_iter_next (&iter, &key, &value))
1642     {
1643       GdkPointerWindowInfo *info = value;
1644       GdkDevice *device = key;
1645
1646       (func) (display, device, info, user_data);
1647     }
1648 }
1649
1650 /**
1651  * gdk_device_grab_info_libgtk_only:
1652  * @display: the display for which to get the grab information
1653  * @device: device to get the grab information from
1654  * @grab_window: (out) (transfer none): location to store current grab window
1655  * @owner_events: (out): location to store boolean indicating whether
1656  *   the @owner_events flag to gdk_keyboard_grab() or
1657  *   gdk_pointer_grab() was %TRUE.
1658  *
1659  * Determines information about the current keyboard grab.
1660  * This is not public API and must not be used by applications.
1661  *
1662  * Return value: %TRUE if this application currently has the
1663  *  keyboard grabbed.
1664  **/
1665 gboolean
1666 gdk_device_grab_info_libgtk_only (GdkDisplay  *display,
1667                                   GdkDevice   *device,
1668                                   GdkWindow  **grab_window,
1669                                   gboolean    *owner_events)
1670 {
1671   GdkDeviceGrabInfo *info;
1672
1673   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1674   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1675
1676   info = _gdk_display_get_last_device_grab (display, device);
1677
1678   if (info)
1679     {
1680       if (grab_window)
1681         *grab_window = info->window;
1682       if (owner_events)
1683         *owner_events = info->owner_events;
1684
1685       return TRUE;
1686     }
1687   else
1688     return FALSE;
1689 }
1690
1691 /**
1692  * gdk_display_pointer_is_grabbed:
1693  * @display: a #GdkDisplay
1694  *
1695  * Test if the pointer is grabbed.
1696  *
1697  * Returns: %TRUE if an active X pointer grab is in effect
1698  *
1699  * Since: 2.2
1700  *
1701  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1702  */
1703 gboolean
1704 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1705 {
1706   GdkDeviceManager *device_manager;
1707   GList *devices, *dev;
1708   GdkDevice *device;
1709
1710   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1711
1712   device_manager = gdk_display_get_device_manager (display);
1713   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1714
1715   for (dev = devices; dev; dev = dev->next)
1716     {
1717       device = dev->data;
1718
1719       if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
1720           gdk_display_device_is_grabbed (display, device))
1721         return TRUE;
1722     }
1723
1724   return FALSE;
1725 }
1726
1727 /**
1728  * gdk_display_device_is_grabbed:
1729  * @display: a #GdkDisplay
1730  * @device: a #GdkDevice
1731  *
1732  * Returns %TRUE if there is an ongoing grab on @device for @display.
1733  *
1734  * Returns: %TRUE if there is a grab in effect for @device.
1735  **/
1736 gboolean
1737 gdk_display_device_is_grabbed (GdkDisplay *display,
1738                                GdkDevice  *device)
1739 {
1740   GdkDeviceGrabInfo *info;
1741
1742   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1743   g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1744
1745   /* What we're interested in is the steady state (ie last grab),
1746      because we're interested e.g. if we grabbed so that we
1747      can ungrab, even if our grab is not active just yet. */
1748   info = _gdk_display_get_last_device_grab (display, device);
1749
1750   return (info && !info->implicit);
1751 }
1752
1753 /**
1754  * gdk_display_get_device_manager:
1755  * @display: a #GdkDisplay.
1756  *
1757  * Returns the #GdkDeviceManager associated to @display.
1758  *
1759  * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is
1760  *          owned by GDK and must not be freed or unreferenced.
1761  *
1762  * Since: 3.0
1763  **/
1764 GdkDeviceManager *
1765 gdk_display_get_device_manager (GdkDisplay *display)
1766 {
1767   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1768
1769   return display->device_manager;
1770 }
1771
1772 /**
1773  * gdk_display_get_name:
1774  * @display: a #GdkDisplay
1775  *
1776  * Gets the name of the display.
1777  *
1778  * Returns: a string representing the display name. This string is owned
1779  * by GDK and should not be modified or freed.
1780  *
1781  * Since: 2.2
1782  */
1783 G_CONST_RETURN gchar *
1784 gdk_display_get_name (GdkDisplay *display)
1785 {
1786   return GDK_DISPLAY_GET_CLASS(display)->get_name (display);
1787 }
1788
1789 gchar *
1790 gdk_get_display (void)
1791 {
1792   return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
1793 }
1794
1795 /**
1796  * gdk_display_get_n_screens:
1797  * @display: a #GdkDisplay
1798  *
1799  * Gets the number of screen managed by the @display.
1800  *
1801  * Returns: number of screens.
1802  *
1803  * Since: 2.2
1804  */
1805 gint
1806 gdk_display_get_n_screens (GdkDisplay *display)
1807 {
1808   return GDK_DISPLAY_GET_CLASS(display)->get_n_screens (display);
1809 }
1810
1811 /**
1812  * gdk_display_get_screen:
1813  * @display: a #GdkDisplay
1814  * @screen_num: the screen number
1815  *
1816  * Returns a screen object for one of the screens of the display.
1817  *
1818  * Returns: (transfer none): the #GdkScreen object
1819  *
1820  * Since: 2.2
1821  */
1822 GdkScreen *
1823 gdk_display_get_screen (GdkDisplay *display,
1824                         gint        screen_num)
1825 {
1826   return GDK_DISPLAY_GET_CLASS(display)->get_screen (display, screen_num);
1827 }
1828
1829 /**
1830  * gdk_display_get_default_screen:
1831  * @display: a #GdkDisplay
1832  *
1833  * Get the default #GdkScreen for @display.
1834  *
1835  * Returns: (transfer none): the default #GdkScreen object for @display
1836  *
1837  * Since: 2.2
1838  */
1839 GdkScreen *
1840 gdk_display_get_default_screen (GdkDisplay *display)
1841 {
1842   return GDK_DISPLAY_GET_CLASS(display)->get_default_screen (display);
1843 }
1844
1845 /**
1846  * gdk_display_beep:
1847  * @display: a #GdkDisplay
1848  *
1849  * Emits a short beep on @display
1850  *
1851  * Since: 2.2
1852  */
1853 void
1854 gdk_display_beep (GdkDisplay *display)
1855 {
1856   GDK_DISPLAY_GET_CLASS(display)->beep (display);
1857 }
1858
1859 /**
1860  * gdk_display_sync:
1861  * @display: a #GdkDisplay
1862  *
1863  * Flushes any requests queued for the windowing system and waits until all
1864  * requests have been handled. This is often used for making sure that the
1865  * display is synchronized with the current state of the program. Calling
1866  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
1867  * generated from earlier requests are handled before the error trap is
1868  * removed.
1869  *
1870  * This is most useful for X11. On windowing systems where requests are
1871  * handled synchronously, this function will do nothing.
1872  *
1873  * Since: 2.2
1874  */
1875 void
1876 gdk_display_sync (GdkDisplay *display)
1877 {
1878   GDK_DISPLAY_GET_CLASS(display)->sync (display);
1879 }
1880
1881 /**
1882  * gdk_display_flush:
1883  * @display: a #GdkDisplay
1884  *
1885  * Flushes any requests queued for the windowing system; this happens automatically
1886  * when the main loop blocks waiting for new events, but if your application
1887  * is drawing without returning control to the main loop, you may need
1888  * to call this function explicitely. A common case where this function
1889  * needs to be called is when an application is executing drawing commands
1890  * from a thread other than the thread where the main loop is running.
1891  *
1892  * This is most useful for X11. On windowing systems where requests are
1893  * handled synchronously, this function will do nothing.
1894  *
1895  * Since: 2.4
1896  */
1897 void
1898 gdk_display_flush (GdkDisplay *display)
1899 {
1900   GDK_DISPLAY_GET_CLASS(display)->flush (display);
1901 }
1902
1903 /**
1904  * gdk_display_get_default_group:
1905  * @display: a #GdkDisplay
1906  *
1907  * Returns the default group leader window for all toplevel windows
1908  * on @display. This window is implicitly created by GDK.
1909  * See gdk_window_set_group().
1910  *
1911  * Return value: (transfer none): The default group leader window
1912  * for @display
1913  *
1914  * Since: 2.4
1915  **/
1916 GdkWindow *
1917 gdk_display_get_default_group (GdkDisplay *display)
1918 {
1919   return GDK_DISPLAY_GET_CLASS(display)->get_default_group (display);
1920 }
1921
1922 /**
1923  * gdk_display_supports_selection_notification:
1924  * @display: a #GdkDisplay
1925  *
1926  * Returns whether #GdkEventOwnerChange events will be
1927  * sent when the owner of a selection changes.
1928  *
1929  * Return value: whether #GdkEventOwnerChange events will
1930  *               be sent.
1931  *
1932  * Since: 2.6
1933  **/
1934 gboolean
1935 gdk_display_supports_selection_notification (GdkDisplay *display)
1936 {
1937   return GDK_DISPLAY_GET_CLASS(display)->supports_selection_notification (display);
1938 }
1939
1940 /**
1941  * gdk_display_request_selection_notification:
1942  * @display: a #GdkDisplay
1943  * @selection: the #GdkAtom naming the selection for which
1944  *             ownership change notification is requested
1945  *
1946  * Request #GdkEventOwnerChange events for ownership changes
1947  * of the selection named by the given atom.
1948  *
1949  * Return value: whether #GdkEventOwnerChange events will
1950  *               be sent.
1951  *
1952  * Since: 2.6
1953  **/
1954 gboolean
1955 gdk_display_request_selection_notification (GdkDisplay *display,
1956                                             GdkAtom     selection)
1957
1958 {
1959   return GDK_DISPLAY_GET_CLASS(display)->request_selection_notification (display, selection);
1960 }
1961
1962 /**
1963  * gdk_display_supports_clipboard_persistence
1964  * @display: a #GdkDisplay
1965  *
1966  * Returns whether the speicifed display supports clipboard
1967  * persistance; i.e. if it's possible to store the clipboard data after an
1968  * application has quit. On X11 this checks if a clipboard daemon is
1969  * running.
1970  *
1971  * Returns: %TRUE if the display supports clipboard persistance.
1972  *
1973  * Since: 2.6
1974  */
1975 gboolean
1976 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1977 {
1978   return GDK_DISPLAY_GET_CLASS(display)->supports_clipboard_persistence (display);
1979 }
1980
1981 /**
1982  * gdk_display_store_clipboard
1983  * @display:          a #GdkDisplay
1984  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1985  * @time_:            a timestamp
1986  * @targets:          an array of targets that should be saved, or %NULL
1987  *                    if all available targets should be saved.
1988  * @n_targets:        length of the @targets array
1989  *
1990  * Issues a request to the clipboard manager to store the
1991  * clipboard data. On X11, this is a special program that works
1992  * according to the freedesktop clipboard specification, available at
1993  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1994  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1995  *
1996  * Since: 2.6
1997  */
1998 void
1999 gdk_display_store_clipboard (GdkDisplay    *display,
2000                              GdkWindow     *clipboard_window,
2001                              guint32        time_,
2002                              const GdkAtom *targets,
2003                              gint           n_targets)
2004 {
2005   GDK_DISPLAY_GET_CLASS(display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
2006 }
2007
2008 /**
2009  * gdk_display_supports_shapes:
2010  * @display: a #GdkDisplay
2011  *
2012  * Returns %TRUE if gdk_window_shape_combine_mask() can
2013  * be used to create shaped windows on @display.
2014  *
2015  * Returns: %TRUE if shaped windows are supported
2016  *
2017  * Since: 2.10
2018  */
2019 gboolean
2020 gdk_display_supports_shapes (GdkDisplay *display)
2021 {
2022   return GDK_DISPLAY_GET_CLASS(display)->supports_shapes (display);
2023 }
2024
2025 /**
2026  * gdk_display_supports_input_shapes:
2027  * @display: a #GdkDisplay
2028  *
2029  * Returns %TRUE if gdk_window_input_shape_combine_mask() can
2030  * be used to modify the input shape of windows on @display.
2031  *
2032  * Returns: %TRUE if windows with modified input shape are supported
2033  *
2034  * Since: 2.10
2035  */
2036 gboolean
2037 gdk_display_supports_input_shapes (GdkDisplay *display)
2038 {
2039   return GDK_DISPLAY_GET_CLASS(display)->supports_input_shapes (display);
2040 }
2041
2042 /**
2043  * gdk_display_supports_composite:
2044  * @display: a #GdkDisplay
2045  *
2046  * Returns %TRUE if gdk_window_set_composited() can be used
2047  * to redirect drawing on the window using compositing.
2048  *
2049  * Currently this only works on X11 with XComposite and
2050  * XDamage extensions available.
2051  *
2052  * Returns: %TRUE if windows may be composited.
2053  *
2054  * Since: 2.12
2055  */
2056 gboolean
2057 gdk_display_supports_composite (GdkDisplay *display)
2058 {
2059   return GDK_DISPLAY_GET_CLASS(display)->supports_composite (display);
2060 }
2061
2062 /**
2063  * gdk_display_list_devices:
2064  * @display: a #GdkDisplay
2065  *
2066  * Returns the list of available input devices attached to @display.
2067  * The list is statically allocated and should not be freed.
2068  *
2069  * Return value: (transfer none) (element-type GdkDevice):
2070  *     a list of #GdkDevice
2071  *
2072  * Since: 2.2
2073  *
2074  * Deprecated: 3.0: Use gdk_device_manager_list_devices() instead.
2075  **/
2076 GList *
2077 gdk_display_list_devices (GdkDisplay *display)
2078 {
2079   return GDK_DISPLAY_GET_CLASS(display)->list_devices (display);
2080 }
2081
2082 /**
2083  * gdk_event_send_client_message_for_display:
2084  * @display: the #GdkDisplay for the window where the message is to be sent.
2085  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
2086  * @winid: the window to send the client message to.
2087  *
2088  * On X11, sends an X ClientMessage event to a given window. On
2089  * Windows, sends a message registered with the name
2090  * GDK_WIN32_CLIENT_MESSAGE.
2091  *
2092  * This could be used for communicating between different
2093  * applications, though the amount of data is limited to 20 bytes on
2094  * X11, and to just four bytes on Windows.
2095  *
2096  * Returns: non-zero on success.
2097  *
2098  * Since: 2.2
2099  */
2100 gboolean
2101 gdk_event_send_client_message_for_display (GdkDisplay     *display,
2102                                            GdkEvent       *event,
2103                                            GdkNativeWindow winid)
2104 {
2105   return GDK_DISPLAY_GET_CLASS(display)->send_client_message (display, event, winid);
2106 }
2107
2108 /**
2109  * gdk_display_add_client_message_filter:
2110  * @display: a #GdkDisplay for which this message filter applies
2111  * @message_type: the type of ClientMessage events to receive.
2112  *   This will be checked against the @message_type field
2113  *   of the XClientMessage event struct.
2114  * @func: the function to call to process the event.
2115  * @data: user data to pass to @func.
2116  *
2117  * Adds a filter to be called when X ClientMessage events are received.
2118  * See gdk_window_add_filter() if you are interested in filtering other
2119  * types of events.
2120  *
2121  * Since: 2.2
2122  **/
2123 void
2124 gdk_display_add_client_message_filter (GdkDisplay   *display,
2125                                        GdkAtom       message_type,
2126                                        GdkFilterFunc func,
2127                                        gpointer      data)
2128 {
2129   GDK_DISPLAY_GET_CLASS(display)->add_client_message_filter (display, message_type, func, data);
2130 }
2131
2132 /**
2133  * gdk_add_client_message_filter:
2134  * @message_type: the type of ClientMessage events to receive. This will be
2135  *     checked against the <structfield>message_type</structfield> field of the
2136  *     XClientMessage event struct.
2137  * @func: the function to call to process the event.
2138  * @data: user data to pass to @func.
2139  *
2140  * Adds a filter to the default display to be called when X ClientMessage events
2141  * are received. See gdk_display_add_client_message_filter().
2142  **/
2143 void
2144 gdk_add_client_message_filter (GdkAtom       message_type,
2145                                GdkFilterFunc func,
2146                                gpointer      data)
2147 {
2148   gdk_display_add_client_message_filter (gdk_display_get_default (),
2149                                          message_type, func, data);
2150 }
2151
2152 static GdkAppLaunchContext *
2153 gdk_display_real_get_app_launch_context (GdkDisplay *display)
2154 {
2155   GdkAppLaunchContext *ctx;
2156
2157   ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT,
2158                       "display", display,
2159                       NULL);
2160
2161   return ctx;
2162 }
2163
2164 /**
2165  * gdk_display_get_app_launch_context:
2166  * @display: a #GdkDisplay
2167  *
2168  * Returns a #GdkAppLaunchContext suitable for launching
2169  * applications on the given display.
2170  *
2171  * Returns: a new #GdkAppLaunchContext for @display.
2172  *     Free with g_object_unref() when done
2173  *
2174  * Since: 3.0
2175  */
2176 GdkAppLaunchContext *
2177 gdk_display_get_app_launch_context (GdkDisplay *display)
2178 {
2179   return GDK_DISPLAY_GET_CLASS(display)->get_app_launch_context (display);
2180 }
2181
2182 /**
2183  * gdk_drag_get_protocol_for_display:
2184  * @display: the #GdkDisplay where the destination window resides
2185  * @xid: the windowing system id of the destination window.
2186  * @protocol: location where the supported DND protocol is returned.
2187  *
2188  * Finds out the DND protocol supported by a window.
2189  *
2190  * Return value: the windowing system id of the window where the drop
2191  *    should happen. This may be @xid or the id of a proxy window,
2192  *    or zero if @xid does not support Drag and Drop.
2193  *
2194  * Since: 2.2
2195  */
2196 GdkNativeWindow
2197 gdk_drag_get_protocol_for_display (GdkDisplay      *display,
2198                                    GdkNativeWindow  xid,
2199                                    GdkDragProtocol *protocol)
2200 {
2201   return GDK_DISPLAY_GET_CLASS (display)->get_drag_protocol (display, xid, protocol, NULL);
2202 }
2203
2204 /**
2205  * gdk_display_open:
2206  * @display_name: the name of the display to open
2207  *
2208  * Opens a display.
2209  *
2210  * Return value: (transfer none): a #GdkDisplay, or %NULL
2211  *     if the display could not be opened
2212  *
2213  * Since: 2.2
2214  */
2215 GdkDisplay *
2216 gdk_display_open (const gchar *display_name)
2217 {
2218   return gdk_display_manager_open_display (gdk_display_manager_get (), display_name);
2219 }
2220
2221 /**
2222  * gdk_display_has_pending:
2223  * @display: a #GdkDisplay
2224  *
2225  * Returns whether the display has events that are waiting
2226  * to be processed.
2227  *
2228  * Returns: %TRUE if there are events ready to be processed.
2229  *
2230  * Since: 3.0
2231  */
2232 gboolean
2233 gdk_display_has_pending (GdkDisplay *display)
2234 {
2235   return GDK_DISPLAY_GET_CLASS (display)->has_pending (display);
2236 }
2237
2238 /**
2239  * gdk_display_supports_cursor_alpha:
2240  * @display: a #GdkDisplay
2241  *
2242  * Returns %TRUE if cursors can use an 8bit alpha channel
2243  * on @display. Otherwise, cursors are restricted to bilevel
2244  * alpha (i.e. a mask).
2245  *
2246  * Returns: whether cursors can have alpha channels.
2247  *
2248  * Since: 2.4
2249  */
2250 gboolean
2251 gdk_display_supports_cursor_alpha (GdkDisplay *display)
2252 {
2253   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2254
2255   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_alpha (display);
2256 }
2257
2258 /**
2259  * gdk_display_supports_cursor_color:
2260  * @display: a #GdkDisplay
2261  *
2262  * Returns %TRUE if multicolored cursors are supported
2263  * on @display. Otherwise, cursors have only a forground
2264  * and a background color.
2265  *
2266  * Returns: whether cursors can have multiple colors.
2267  *
2268  * Since: 2.4
2269  */
2270 gboolean
2271 gdk_display_supports_cursor_color (GdkDisplay *display)
2272 {
2273   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2274
2275   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_color (display);
2276 }
2277
2278 /**
2279  * gdk_display_get_default_cursor_size:
2280  * @display: a #GdkDisplay
2281  *
2282  * Returns the default size to use for cursors on @display.
2283  *
2284  * Returns: the default cursor size.
2285  *
2286  * Since: 2.4
2287  */
2288 guint
2289 gdk_display_get_default_cursor_size (GdkDisplay *display)
2290 {
2291   guint width, height;
2292
2293   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2294
2295   GDK_DISPLAY_GET_CLASS (display)->get_default_cursor_size (display,
2296                                                             &width,
2297                                                             &height);
2298
2299   return MIN (width, height);
2300 }
2301
2302 /**
2303  * gdk_display_get_maximal_cursor_size:
2304  * @display: a #GdkDisplay
2305  * @width: (out): the return location for the maximal cursor width
2306  * @height: (out): the return location for the maximal cursor height
2307  *
2308  * Gets the maximal size to use for cursors on @display.
2309  *
2310  * Since: 2.4
2311  */
2312 void
2313 gdk_display_get_maximal_cursor_size (GdkDisplay *display,
2314                                      guint       *width,
2315                                      guint       *height)
2316 {
2317   g_return_if_fail (GDK_IS_DISPLAY (display));
2318
2319   GDK_DISPLAY_GET_CLASS (display)->get_maximal_cursor_size (display,
2320                                                             width,
2321                                                             height);
2322 }
2323
2324 /**
2325  * gdk_display_warp_pointer:
2326  * @display: a #GdkDisplay
2327  * @screen: the screen of @display to warp the pointer to
2328  * @x: the x coordinate of the destination
2329  * @y: the y coordinate of the destination
2330  *
2331  * Warps the pointer of @display to the point @x,@y on
2332  * the screen @screen, unless the pointer is confined
2333  * to a window by a grab, in which case it will be moved
2334  * as far as allowed by the grab. Warping the pointer
2335  * creates events as if the user had moved the mouse
2336  * instantaneously to the destination.
2337  *
2338  * Note that the pointer should normally be under the
2339  * control of the user. This function was added to cover
2340  * some rare use cases like keyboard navigation support
2341  * for the color picker in the #GtkColorSelectionDialog.
2342  *
2343  * Since: 2.8
2344  *
2345  * Deprecated: 3.0: Use gdk_device_warp() instead.
2346  */
2347 void
2348 gdk_display_warp_pointer (GdkDisplay *display,
2349                           GdkScreen  *screen,
2350                           gint        x,
2351                           gint        y)
2352 {
2353   gdk_device_warp (display->core_pointer,
2354                    screen,
2355                    x, y);
2356 }
2357
2358 gulong
2359 _gdk_display_get_next_serial (GdkDisplay *display)
2360 {
2361   return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display);
2362 }
2363
2364
2365 /**
2366  * gdk_notify_startup_complete:
2367  *
2368  * Indicates to the GUI environment that the application has finished
2369  * loading. If the applications opens windows, this function is
2370  * normally called after opening the application's initial set of
2371  * windows.
2372  *
2373  * GTK+ will call this function automatically after opening the first
2374  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
2375  * to disable that feature.
2376  *
2377  * Since: 2.2
2378  **/
2379 void
2380 gdk_notify_startup_complete (void)
2381 {
2382   gdk_notify_startup_complete_with_id (NULL);
2383 }
2384
2385 /**
2386  * gdk_notify_startup_complete_with_id:
2387  * @startup_id: a startup-notification identifier, for which
2388  *     notification process should be completed
2389  *
2390  * Indicates to the GUI environment that the application has
2391  * finished loading, using a given identifier.
2392  *
2393  * GTK+ will call this function automatically for #GtkWindow
2394  * with custom startup-notification identifier unless
2395  * gtk_window_set_auto_startup_notification() is called to
2396  * disable that feature.
2397  *
2398  * Since: 2.12
2399  */
2400 void
2401 gdk_notify_startup_complete_with_id (const gchar* startup_id)
2402 {
2403   GdkDisplay *display;
2404
2405   display = gdk_display_get_default ();
2406   if (display)
2407     gdk_display_notify_startup_complete (display, startup_id);
2408 }
2409
2410 /**
2411  * gdk_display_notify_startup_complete:
2412  * @display: a #GdkDisplay
2413  * @startup_id: a startup-notification identifier, for which
2414  *     notification process should be completed
2415  *
2416  * Indicates to the GUI environment that the application has
2417  * finished loading, using a given identifier.
2418  *
2419  * GTK+ will call this function automatically for #GtkWindow
2420  * with custom startup-notification identifier unless
2421  * gtk_window_set_auto_startup_notification() is called to
2422  * disable that feature.
2423  *
2424  * Since: 3.0
2425  */
2426 void
2427 gdk_display_notify_startup_complete (GdkDisplay  *display,
2428                                      const gchar *startup_id)
2429 {
2430   GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
2431 }
2432
2433 void
2434 _gdk_display_event_data_copy (GdkDisplay     *display,
2435                               const GdkEvent *event,
2436                               GdkEvent       *new_event)
2437 {
2438   GDK_DISPLAY_GET_CLASS (display)->event_data_copy (display, event, new_event);
2439 }
2440
2441 void
2442 _gdk_display_event_data_free (GdkDisplay *display,
2443                               GdkEvent   *event)
2444 {
2445   GDK_DISPLAY_GET_CLASS (display)->event_data_free (display, event);
2446 }
2447
2448 void
2449 _gdk_display_create_window_impl (GdkDisplay       *display,
2450                                  GdkWindow        *window,
2451                                  GdkWindow        *real_parent,
2452                                  GdkScreen        *screen,
2453                                  GdkEventMask      event_mask,
2454                                  GdkWindowAttr    *attributes,
2455                                  gint              attributes_mask)
2456 {
2457   GDK_DISPLAY_GET_CLASS (display)->create_window_impl (display,
2458                                                        window,
2459                                                        real_parent,
2460                                                        screen,
2461                                                        event_mask,
2462                                                        attributes,
2463                                                        attributes_mask);
2464 }
2465
2466 GdkWindow *
2467 _gdk_display_create_window (GdkDisplay *display)
2468 {
2469   return g_object_new (GDK_DISPLAY_GET_CLASS (display)->window_type, NULL);
2470 }
2471
2472 /**
2473  * gdk_keymap_get_for_display:
2474  * @display: the #GdkDisplay.
2475  *
2476  * Returns the #GdkKeymap attached to @display.
2477  *
2478  * Return value: (transfer none): the #GdkKeymap attached to @display.
2479  *
2480  * Since: 2.2
2481  */
2482 GdkKeymap*
2483 gdk_keymap_get_for_display (GdkDisplay *display)
2484 {
2485   return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
2486 }
2487
2488 typedef struct _GdkGlobalErrorTrap  GdkGlobalErrorTrap;
2489
2490 struct _GdkGlobalErrorTrap
2491 {
2492   GSList *displays;
2493 };
2494
2495 static GQueue gdk_error_traps = G_QUEUE_INIT;
2496
2497 /**
2498  * gdk_error_trap_push:
2499  *
2500  * This function allows X errors to be trapped instead of the normal
2501  * behavior of exiting the application. It should only be used if it
2502  * is not possible to avoid the X error in any other way. Errors are
2503  * ignored on all #GdkDisplay currently known to the
2504  * #GdkDisplayManager. If you don't care which error happens and just
2505  * want to ignore everything, pop with gdk_error_trap_pop_ignored().
2506  * If you need the error code, use gdk_error_trap_pop() which may have
2507  * to block and wait for the error to arrive from the X server.
2508  *
2509  * This API exists on all platforms but only does anything on X.
2510  *
2511  * You can use gdk_x11_display_error_trap_push() to ignore errors
2512  * on only a single display.
2513  *
2514 * <example>
2515  * <title>Trapping an X error</title>
2516  * <programlisting>
2517  * gdk_error_trap_push (<!-- -->);
2518  *
2519  *  // ... Call the X function which may cause an error here ...
2520  *
2521  *
2522  * if (gdk_error_trap_pop (<!-- -->))
2523  *  {
2524  *    // ... Handle the error here ...
2525  *  }
2526  * </programlisting>
2527  * </example>
2528  */
2529 void
2530 gdk_error_trap_push (void)
2531 {
2532   GdkDisplayManager *manager;
2533   GdkDisplayClass *class;
2534   GdkGlobalErrorTrap *trap;
2535   GSList *l;
2536
2537   manager = gdk_display_manager_get ();
2538   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2539
2540   if (class->push_error_trap == NULL)
2541     return;
2542
2543   trap = g_slice_new (GdkGlobalErrorTrap);
2544   trap->displays = gdk_display_manager_list_displays (manager);
2545
2546   g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
2547   for (l = trap->displays; l != NULL; l = l->next)
2548     {
2549       class->push_error_trap (l->data);
2550     }
2551
2552   g_queue_push_head (&gdk_error_traps, trap);
2553 }
2554
2555 static gint
2556 gdk_error_trap_pop_internal (gboolean need_code)
2557 {
2558   GdkDisplayManager *manager;
2559   GdkDisplayClass *class;
2560   GdkGlobalErrorTrap *trap;
2561   gint result;
2562   GSList *l;
2563
2564   manager = gdk_display_manager_get ();
2565   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2566
2567   if (class->pop_error_trap == NULL)
2568     return 0;
2569
2570   trap = g_queue_pop_head (&gdk_error_traps);
2571
2572   g_return_val_if_fail (trap != NULL, 0);
2573
2574   result = 0;
2575   for (l = trap->displays; l != NULL; l = l->next)
2576     {
2577       gint code = 0;
2578
2579       code = class->pop_error_trap (l->data, !need_code);
2580
2581       /* we use the error on the last display listed, why not. */
2582       if (code != 0)
2583         result = code;
2584     }
2585
2586   g_slist_free_full (trap->displays, g_object_unref);
2587   g_slice_free (GdkGlobalErrorTrap, trap);
2588
2589   return result;
2590 }
2591
2592 /**
2593  * gdk_error_trap_pop_ignored:
2594  *
2595  * Removes an error trap pushed with gdk_error_trap_push(), but
2596  * without bothering to wait and see whether an error occurred.  If an
2597  * error arrives later asynchronously that was triggered while the
2598  * trap was pushed, that error will be ignored.
2599  *
2600  * Since: 3.0
2601  */
2602 void
2603 gdk_error_trap_pop_ignored (void)
2604 {
2605   gdk_error_trap_pop_internal (FALSE);
2606 }
2607
2608 /**
2609  * gdk_error_trap_pop:
2610  *
2611  * Removes an error trap pushed with gdk_error_trap_push().
2612  * May block until an error has been definitively received
2613  * or not received from the X server. gdk_error_trap_pop_ignored()
2614  * is preferred if you don't need to know whether an error
2615  * occurred, because it never has to block. If you don't
2616  * need the return value of gdk_error_trap_pop(), use
2617  * gdk_error_trap_pop_ignored().
2618  *
2619  * Prior to GDK 3.0, this function would not automatically
2620  * sync for you, so you had to gdk_flush() if your last
2621  * call to Xlib was not a blocking round trip.
2622  *
2623  * Return value: X error code or 0 on success
2624  */
2625 gint
2626 gdk_error_trap_pop (void)
2627 {
2628   return gdk_error_trap_pop_internal (TRUE);
2629 }