]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
gdk: Allow display subclasses to override the type used for windows
[~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_get_device_state:
701  * @display: a #GdkDisplay.
702  * @device: pointer device to query status about.
703  * @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
704  *          the @device is on, or %NULL.
705  * @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
706  * @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
707  * @mask: (out) (allow-none): location to store current modifier mask for @device, or %NULL.
708  *
709  * Gets the current location and state of @device for a given display.
710  *
711  * Since: 3.0
712  **/
713 void
714 gdk_display_get_device_state (GdkDisplay       *display,
715                               GdkDevice        *device,
716                               GdkScreen       **screen,
717                               gint             *x,
718                               gint             *y,
719                               GdkModifierType  *mask)
720 {
721   GdkScreen *tmp_screen;
722   gint tmp_x, tmp_y;
723   GdkModifierType tmp_mask;
724
725   g_return_if_fail (GDK_IS_DISPLAY (display));
726   g_return_if_fail (GDK_IS_DEVICE (device));
727   g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
728
729   display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
730
731   if (screen)
732     *screen = tmp_screen;
733   if (x)
734     *x = tmp_x;
735   if (y)
736     *y = tmp_y;
737   if (mask)
738     *mask = tmp_mask;
739 }
740
741 /**
742  * gdk_display_get_window_at_device_position:
743  * @display: a #GdkDisplay.
744  * @device: pointer #GdkDevice to query info to.
745  * @win_x: (out) (allow-none): return location for the X coordinate of the device location,
746  *         relative to the window origin, or %NULL.
747  * @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
748  *         relative to the window origin, or %NULL.
749  *
750  * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
751  * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
752  *
753  * Returns: (transfer none): the #GdkWindow under the device position, or %NULL.
754  *
755  * Since: 3.0
756  **/
757 GdkWindow *
758 gdk_display_get_window_at_device_position (GdkDisplay *display,
759                                            GdkDevice  *device,
760                                            gint       *win_x,
761                                            gint       *win_y)
762 {
763   gint tmp_x, tmp_y;
764   GdkWindow *window;
765
766   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
767   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
768   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
769
770   window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
771
772   if (win_x)
773     *win_x = tmp_x;
774   if (win_y)
775     *win_y = tmp_y;
776
777   return window;
778 }
779
780 /**
781  * gdk_display_set_device_hooks:
782  * @display: a #GdkDisplay.
783  * @new_hooks: (allow-none): a table of pointers to functions for getting quantities related
784  *             to all devices position, or %NULL to restore the default table.
785  *
786  * This function allows for hooking into the operation of getting the current location of any
787  * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
788  * an event recorder. Applications should never have any reason to use this facility.
789  *
790  * Returns: (transfer none): The previous device hook table.
791  *
792  * Since: 3.0
793  **/
794 GdkDisplayDeviceHooks *
795 gdk_display_set_device_hooks (GdkDisplay                  *display,
796                               const GdkDisplayDeviceHooks *new_hooks)
797 {
798   const GdkDisplayDeviceHooks *result;
799
800   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
801   result = display->device_hooks;
802
803   if (new_hooks)
804     display->device_hooks = new_hooks;
805   else
806     display->device_hooks = &default_device_hooks;
807
808   return (GdkDisplayDeviceHooks *) result;
809 }
810
811 /**
812  * gdk_display_get_pointer:
813  * @display: a #GdkDisplay
814  * @screen: (allow-none): location to store the screen that the
815  *          cursor is on, or %NULL.
816  * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
817  * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
818  * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
819  *
820  * Gets the current location of the pointer and the current modifier
821  * mask for a given display.
822  *
823  * Since: 2.2
824  *
825  * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
826  **/
827 void
828 gdk_display_get_pointer (GdkDisplay      *display,
829                          GdkScreen      **screen,
830                          gint            *x,
831                          gint            *y,
832                          GdkModifierType *mask)
833 {
834   g_return_if_fail (GDK_IS_DISPLAY (display));
835
836   gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
837 }
838
839 static GdkWindow *
840 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
841                                                 GdkDevice  *device,
842                                                 gint       *win_x,
843                                                 gint       *win_y)
844 {
845   GdkWindow *window;
846   gint x, y;
847
848   window = _gdk_device_window_at_position (device, &x, &y, NULL, FALSE);
849
850   /* This might need corrections, as the native window returned
851      may contain client side children */
852   if (window)
853     {
854       double xx, yy;
855
856       window = _gdk_window_find_descendant_at (window,
857                                                x, y,
858                                                &xx, &yy);
859       x = floor (xx + 0.5);
860       y = floor (yy + 0.5);
861     }
862
863   *win_x = x;
864   *win_y = y;
865
866   return window;
867 }
868
869 static GdkWindow *
870 gdk_window_real_window_get_device_position (GdkDisplay       *display,
871                                             GdkDevice        *device,
872                                             GdkWindow        *window,
873                                             gint             *x,
874                                             gint             *y,
875                                             GdkModifierType  *mask)
876 {
877   gint tmpx, tmpy;
878   GdkModifierType tmp_mask;
879   gboolean normal_child;
880
881   normal_child = GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_device_state (window,
882                                                                               device,
883                                                                               &tmpx, &tmpy,
884                                                                               &tmp_mask);
885   /* We got the coords on the impl, convert to the window */
886   tmpx -= window->abs_x;
887   tmpy -= window->abs_y;
888
889   if (x)
890     *x = tmpx;
891   if (y)
892     *y = tmpy;
893   if (mask)
894     *mask = tmp_mask;
895
896   if (normal_child)
897     return _gdk_window_find_child_at (window, tmpx, tmpy);
898   return NULL;
899 }
900
901 /**
902  * gdk_display_get_window_at_pointer:
903  * @display: a #GdkDisplay
904  * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
905  *    to the window origin, or %NULL
906  * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
907  &    to the window origin, or %NULL
908  *
909  * Obtains the window underneath the mouse pointer, returning the location
910  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
911  * if the window under the mouse pointer is not known to GDK (for example, 
912  * belongs to another application).
913  *
914  * Returns: (transfer none): the window under the mouse pointer, or %NULL
915  *
916  * Since: 2.2
917  *
918  * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
919  **/
920 GdkWindow *
921 gdk_display_get_window_at_pointer (GdkDisplay *display,
922                                    gint       *win_x,
923                                    gint       *win_y)
924 {
925   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
926
927   return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
928 }
929
930 static void
931 multihead_get_device_state (GdkDisplay       *display,
932                             GdkDevice        *device,
933                             GdkScreen       **screen,
934                             gint             *x,
935                             gint             *y,
936                             GdkModifierType  *mask)
937 {
938   multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
939 }
940
941 static GdkWindow *
942 multihead_window_get_device_position (GdkDisplay      *display,
943                                       GdkDevice       *device,
944                                       GdkWindow       *window,
945                                       gint            *x,
946                                       gint            *y,
947                                       GdkModifierType *mask)
948 {
949   return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
950 }
951
952 static GdkWindow *
953 multihead_window_at_device_position (GdkDisplay *display,
954                                      GdkDevice  *device,
955                                      gint       *win_x,
956                                      gint       *win_y)
957 {
958   return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
959 }
960
961 static void
962 gdk_display_real_get_device_state (GdkDisplay       *display,
963                                    GdkDevice        *device,
964                                    GdkScreen       **screen,
965                                    gint             *x,
966                                    gint             *y,
967                                    GdkModifierType  *mask)
968 {
969   GdkScreen *default_screen;
970   GdkWindow *root;
971
972   if (gdk_display_is_closed (display))
973     return;
974
975   default_screen = gdk_display_get_default_screen (display);
976
977   _gdk_device_query_state (device,
978                            gdk_screen_get_root_window (default_screen),
979                            &root, NULL,
980                            x, y,
981                            NULL, NULL,
982                            mask);
983
984   *screen = gdk_window_get_screen (root);
985 }
986
987 static void
988 multihead_default_get_pointer (GdkDisplay       *display,
989                                GdkScreen       **screen,
990                                gint             *x,
991                                gint             *y,
992                                GdkModifierType  *mask)
993 {
994   gdk_display_real_get_device_state (display, display->core_pointer,
995                                      screen, x, y, mask);
996 }
997
998 static GdkWindow *
999 multihead_default_window_get_pointer (GdkDisplay      *display,
1000                                       GdkWindow       *window,
1001                                       gint            *x,
1002                                       gint            *y,
1003                                       GdkModifierType *mask)
1004 {
1005   return gdk_window_real_window_get_device_position (display,
1006                                                      display->core_pointer,
1007                                                      window, x, y, mask);
1008 }
1009
1010 static GdkWindow *
1011 multihead_default_window_at_pointer (GdkDisplay *display,
1012                                      gint       *win_x,
1013                                      gint       *win_y)
1014 {
1015   return gdk_display_real_get_window_at_device_position (display,
1016                                                          display->core_pointer,
1017                                                          win_x, win_y);
1018 }
1019
1020 /**
1021  * gdk_display_set_pointer_hooks:
1022  * @display: a #GdkDisplay
1023  * @new_hooks: (allow-none): a table of pointers to functions for getting
1024  *   quantities related to the current pointer position,
1025  *   or %NULL to restore the default table.
1026  * 
1027  * This function allows for hooking into the operation
1028  * of getting the current location of the pointer on a particular
1029  * display. This is only useful for such low-level tools as an
1030  * event recorder. Applications should never have any
1031  * reason to use this facility.
1032  *
1033  * Return value: (transfer none): the previous pointer hook table
1034  *
1035  * Since: 2.2
1036  *
1037  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1038  **/
1039 GdkDisplayPointerHooks *
1040 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
1041                                const GdkDisplayPointerHooks *new_hooks)
1042 {
1043   const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1044
1045   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1046
1047   if (new_hooks)
1048     multihead_current_pointer_hooks = new_hooks;
1049   else
1050     multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1051
1052   gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1053
1054   return (GdkDisplayPointerHooks *)result;
1055 }
1056
1057 static void
1058 singlehead_get_pointer (GdkDisplay       *display,
1059                         GdkScreen       **screen,
1060                         gint             *x,
1061                         gint             *y,
1062                         GdkModifierType  *mask)
1063 {
1064   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1065   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1066
1067   *screen = default_screen;
1068
1069   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1070 }
1071
1072 static GdkWindow*
1073 singlehead_window_get_pointer (GdkDisplay       *display,
1074                                GdkWindow        *window,
1075                                gint             *x,
1076                                gint             *y,
1077                                GdkModifierType  *mask)
1078 {
1079   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1080 }
1081
1082 static GdkWindow*
1083 singlehead_window_at_pointer   (GdkDisplay *display,
1084                                 gint       *win_x,
1085                                 gint       *win_y)
1086 {
1087   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1088
1089   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1090                                                               win_x, win_y);
1091 }
1092
1093 static GdkWindow*
1094 singlehead_default_window_get_pointer (GdkWindow       *window,
1095                                        gint            *x,
1096                                        gint            *y,
1097                                        GdkModifierType *mask)
1098 {
1099   GdkDisplay *display;
1100
1101   display = gdk_window_get_display (window);
1102
1103   return gdk_window_real_window_get_device_position (display,
1104                                                      display->core_pointer,
1105                                                      window, x, y, mask);
1106 }
1107
1108 static GdkWindow*
1109 singlehead_default_window_at_pointer  (GdkScreen       *screen,
1110                                        gint            *win_x,
1111                                        gint            *win_y)
1112 {
1113   GdkDisplay *display;
1114
1115   display = gdk_screen_get_display (screen);
1116
1117   return gdk_display_real_get_window_at_device_position (display,
1118                                                          display->core_pointer,
1119                                                          win_x, win_y);
1120 }
1121
1122 /**
1123  * gdk_set_pointer_hooks:
1124  * @new_hooks: (allow-none): a table of pointers to functions for getting
1125  *   quantities related to the current pointer position,
1126  *   or %NULL to restore the default table.
1127  * 
1128  * This function allows for hooking into the operation
1129  * of getting the current location of the pointer. This
1130  * is only useful for such low-level tools as an
1131  * event recorder. Applications should never have any
1132  * reason to use this facility.
1133  *
1134  * This function is not multihead safe. For multihead operation,
1135  * see gdk_display_set_pointer_hooks().
1136  * 
1137  * Return value: the previous pointer hook table
1138  *
1139  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1140  **/
1141 GdkPointerHooks *
1142 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1143 {
1144   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1145
1146   if (new_hooks)
1147     singlehead_current_pointer_hooks = new_hooks;
1148   else
1149     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1150
1151   gdk_display_set_pointer_hooks (gdk_display_get_default (),
1152                                  &singlehead_pointer_hooks);
1153   
1154   return (GdkPointerHooks *)result;
1155 }
1156
1157 static void
1158 generate_grab_broken_event (GdkWindow *window,
1159                             GdkDevice *device,
1160                             gboolean   implicit,
1161                             GdkWindow *grab_window)
1162 {
1163   g_return_if_fail (window != NULL);
1164
1165   if (!GDK_WINDOW_DESTROYED (window))
1166     {
1167       GdkEvent *event;
1168
1169       event = gdk_event_new (GDK_GRAB_BROKEN);
1170       event->grab_broken.window = g_object_ref (window);
1171       event->grab_broken.send_event = FALSE;
1172       event->grab_broken.implicit = implicit;
1173       event->grab_broken.grab_window = grab_window;
1174       gdk_event_set_device (event, device);
1175       event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1176
1177       gdk_event_put (event);
1178       gdk_event_free (event);
1179     }
1180 }
1181
1182 GdkDeviceGrabInfo *
1183 _gdk_display_get_last_device_grab (GdkDisplay *display,
1184                                    GdkDevice  *device)
1185 {
1186   GList *l;
1187
1188   l = g_hash_table_lookup (display->device_grabs, device);
1189
1190   if (l)
1191     {
1192       l = g_list_last (l);
1193       return l->data;
1194     }
1195
1196   return NULL;
1197 }
1198
1199 GdkDeviceGrabInfo *
1200 _gdk_display_add_device_grab (GdkDisplay       *display,
1201                               GdkDevice        *device,
1202                               GdkWindow        *window,
1203                               GdkWindow        *native_window,
1204                               GdkGrabOwnership  grab_ownership,
1205                               gboolean          owner_events,
1206                               GdkEventMask      event_mask,
1207                               unsigned long     serial_start,
1208                               guint32           time,
1209                               gboolean          implicit)
1210 {
1211   GdkDeviceGrabInfo *info, *other_info;
1212   GList *grabs, *l;
1213
1214   info = g_new0 (GdkDeviceGrabInfo, 1);
1215
1216   info->window = g_object_ref (window);
1217   info->native_window = g_object_ref (native_window);
1218   info->serial_start = serial_start;
1219   info->serial_end = G_MAXULONG;
1220   info->owner_events = owner_events;
1221   info->event_mask = event_mask;
1222   info->time = time;
1223   info->implicit = implicit;
1224   info->ownership = grab_ownership;
1225
1226   grabs = g_hash_table_lookup (display->device_grabs, device);
1227
1228   /* Find the first grab that has a larger start time (if any) and insert
1229    * before that. I.E we insert after already existing grabs with same
1230    * start time */
1231   for (l = grabs; l != NULL; l = l->next)
1232     {
1233       other_info = l->data;
1234
1235       if (info->serial_start < other_info->serial_start)
1236         break;
1237     }
1238
1239   grabs = g_list_insert_before (grabs, l, info);
1240
1241   /* Make sure the new grab end before next grab */
1242   if (l)
1243     {
1244       other_info = l->data;
1245       info->serial_end = other_info->serial_start;
1246     }
1247
1248   /* Find any previous grab and update its end time */
1249   l = g_list_find (grabs, info);
1250   l = l->prev;
1251   if (l)
1252     {
1253       other_info = l->data;
1254       other_info->serial_end = serial_start;
1255     }
1256
1257   g_hash_table_insert (display->device_grabs, device, grabs);
1258
1259   return info;
1260 }
1261
1262 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1263    This function splits things into two calls if needed, converting the
1264    coordinates to the right toplevel */
1265 static void
1266 synthesize_crossing_events (GdkDisplay      *display,
1267                             GdkDevice       *device,
1268                             GdkDevice       *source_device,
1269                             GdkWindow       *src_window,
1270                             GdkWindow       *dest_window,
1271                             GdkCrossingMode  crossing_mode,
1272                             guint32          time,
1273                             gulong           serial)
1274 {
1275   GdkWindow *src_toplevel, *dest_toplevel;
1276   GdkModifierType state;
1277   int x, y;
1278
1279   /* We use the native crossing events if all native */
1280   if (_gdk_native_windows)
1281     return;
1282   
1283   if (src_window)
1284     src_toplevel = gdk_window_get_toplevel (src_window);
1285   else
1286     src_toplevel = NULL;
1287   if (dest_window)
1288     dest_toplevel = gdk_window_get_toplevel (dest_window);
1289   else
1290     dest_toplevel = NULL;
1291
1292   if (src_toplevel == NULL && dest_toplevel == NULL)
1293     return;
1294   
1295   if (src_toplevel == NULL ||
1296       src_toplevel == dest_toplevel)
1297     {
1298       /* Same toplevels */
1299       gdk_window_get_pointer (dest_toplevel,
1300                               &x, &y, &state);
1301       _gdk_synthesize_crossing_events (display,
1302                                        src_window,
1303                                        dest_window,
1304                                        device, source_device,
1305                                        crossing_mode,
1306                                        x, y, state,
1307                                        time,
1308                                        NULL,
1309                                        serial, FALSE);
1310     }
1311   else if (dest_toplevel == NULL)
1312     {
1313       gdk_window_get_pointer (src_toplevel,
1314                               &x, &y, &state);
1315       _gdk_synthesize_crossing_events (display,
1316                                        src_window,
1317                                        NULL,
1318                                        device, source_device,
1319                                        crossing_mode,
1320                                        x, y, state,
1321                                        time,
1322                                        NULL,
1323                                        serial, FALSE);
1324     }
1325   else
1326     {
1327       /* Different toplevels */
1328       gdk_window_get_pointer (src_toplevel,
1329                               &x, &y, &state);
1330       _gdk_synthesize_crossing_events (display,
1331                                        src_window,
1332                                        NULL,
1333                                        device, source_device,
1334                                        crossing_mode,
1335                                        x, y, state,
1336                                        time,
1337                                        NULL,
1338                                        serial, FALSE);
1339       gdk_window_get_pointer (dest_toplevel,
1340                               &x, &y, &state);
1341       _gdk_synthesize_crossing_events (display,
1342                                        NULL,
1343                                        dest_window,
1344                                        device, source_device,
1345                                        crossing_mode,
1346                                        x, y, state,
1347                                        time,
1348                                        NULL,
1349                                        serial, FALSE);
1350     }
1351 }
1352
1353 static GdkWindow *
1354 get_current_toplevel (GdkDisplay      *display,
1355                       GdkDevice       *device,
1356                       int             *x_out,
1357                       int             *y_out,
1358                       GdkModifierType *state_out)
1359 {
1360   GdkWindow *pointer_window;
1361   int x, y;
1362   GdkModifierType state;
1363
1364   pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
1365
1366   if (pointer_window != NULL &&
1367       (GDK_WINDOW_DESTROYED (pointer_window) ||
1368        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1369        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1370     pointer_window = NULL;
1371
1372   *x_out = x;
1373   *y_out = y;
1374   *state_out = state;
1375
1376   return pointer_window;
1377 }
1378
1379 static void
1380 switch_to_pointer_grab (GdkDisplay        *display,
1381                         GdkDevice         *device,
1382                         GdkDevice         *source_device,
1383                         GdkDeviceGrabInfo *grab,
1384                         GdkDeviceGrabInfo *last_grab,
1385                         guint32            time,
1386                         gulong             serial)
1387 {
1388   GdkWindow *src_window, *pointer_window, *new_toplevel;
1389   GdkPointerWindowInfo *info;
1390   GList *old_grabs;
1391   GdkModifierType state;
1392   int x, y;
1393
1394   /* Temporarily unset pointer to make sure we send the crossing events below */
1395   old_grabs = g_hash_table_lookup (display->device_grabs, device);
1396   g_hash_table_steal (display->device_grabs, device);
1397   info = _gdk_display_get_pointer_info (display, device);
1398
1399   if (grab)
1400     {
1401       /* New grab is in effect */
1402
1403       /* We need to generate crossing events for the grab.
1404        * However, there are never any crossing events for implicit grabs
1405        * TODO: ... Actually, this could happen if the pointer window
1406        *           doesn't have button mask so a parent gets the event...
1407        */
1408       if (!grab->implicit)
1409         {
1410           /* We send GRAB crossing events from the window under the pointer to the
1411              grab window. Except if there is an old grab then we start from that */
1412           if (last_grab)
1413             src_window = last_grab->window;
1414           else
1415             src_window = info->window_under_pointer;
1416
1417           if (src_window != grab->window)
1418             synthesize_crossing_events (display, device, source_device,
1419                                         src_window, grab->window,
1420                                         GDK_CROSSING_GRAB, time, serial);
1421
1422           /* !owner_event Grabbing a window that we're not inside, current status is
1423              now NULL (i.e. outside grabbed window) */
1424           if (!grab->owner_events && info->window_under_pointer != grab->window)
1425             _gdk_display_set_window_under_pointer (display, device, NULL);
1426         }
1427
1428       grab->activated = TRUE;
1429     }
1430
1431   if (last_grab)
1432     {
1433       new_toplevel = NULL;
1434
1435       if (grab == NULL /* ungrab */ ||
1436           (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1437         {
1438           /* We force check what window we're in, and update the toplevel_under_pointer info,
1439            * as that won't get told of this change with toplevel enter events.
1440            */
1441           if (info->toplevel_under_pointer)
1442             g_object_unref (info->toplevel_under_pointer);
1443           info->toplevel_under_pointer = NULL;
1444
1445           new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1446           if (new_toplevel)
1447             {
1448               /* w is now toplevel and x,y in toplevel coords */
1449               info->toplevel_under_pointer = g_object_ref (new_toplevel);
1450               info->toplevel_x = x;
1451               info->toplevel_y = y;
1452               info->state = state;
1453             }
1454         }
1455
1456       if (grab == NULL) /* Ungrabbed, send events */
1457         {
1458           pointer_window = NULL;
1459           if (new_toplevel)
1460             {
1461               /* Find (possibly virtual) child window */
1462               pointer_window =
1463                 _gdk_window_find_descendant_at (new_toplevel,
1464                                                 x, y,
1465                                                 NULL, NULL);
1466             }
1467
1468           if (pointer_window != last_grab->window)
1469             synthesize_crossing_events (display, device, source_device,
1470                                         last_grab->window, pointer_window,
1471                                         GDK_CROSSING_UNGRAB, time, serial);
1472
1473           /* We're now ungrabbed, update the window_under_pointer */
1474           _gdk_display_set_window_under_pointer (display, device, pointer_window);
1475         }
1476     }
1477
1478   g_hash_table_insert (display->device_grabs, device, old_grabs);
1479 }
1480
1481 void
1482 _gdk_display_device_grab_update (GdkDisplay *display,
1483                                  GdkDevice  *device,
1484                                  GdkDevice  *source_device,
1485                                  gulong      current_serial)
1486 {
1487   GdkDeviceGrabInfo *current_grab, *next_grab;
1488   GList *grabs;
1489   guint32 time;
1490
1491   time = display->last_event_time;
1492   grabs = g_hash_table_lookup (display->device_grabs, device);
1493
1494   while (grabs != NULL)
1495     {
1496       current_grab = grabs->data;
1497
1498       if (current_grab->serial_start > current_serial)
1499         return; /* Hasn't started yet */
1500
1501       if (current_grab->serial_end > current_serial)
1502         {
1503           /* This one hasn't ended yet.
1504              its the currently active one or scheduled to be active */
1505
1506           if (!current_grab->activated)
1507             {
1508               if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1509                 switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
1510             }
1511
1512           break;
1513         }
1514
1515       next_grab = NULL;
1516       if (grabs->next)
1517         {
1518           /* This is the next active grab */
1519           next_grab = grabs->next->data;
1520
1521           if (next_grab->serial_start > current_serial)
1522             next_grab = NULL; /* Actually its not yet active */
1523         }
1524
1525       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1526           (next_grab != NULL && current_grab->window != next_grab->window))
1527         generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1528                                     device,
1529                                     current_grab->implicit,
1530                                     next_grab? next_grab->window : NULL);
1531
1532       /* Remove old grab */
1533       grabs = g_list_delete_link (grabs, grabs);
1534       g_hash_table_insert (display->device_grabs, device, grabs);
1535
1536       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1537         switch_to_pointer_grab (display, device, source_device,
1538                                 next_grab, current_grab,
1539                                 time, current_serial);
1540
1541       free_device_grab (current_grab);
1542     }
1543 }
1544
1545 static GList *
1546 grab_list_find (GList  *grabs,
1547                 gulong  serial)
1548 {
1549   GdkDeviceGrabInfo *grab;
1550
1551   while (grabs)
1552     {
1553       grab = grabs->data;
1554
1555       if (serial >= grab->serial_start && serial < grab->serial_end)
1556         return grabs;
1557
1558       grabs = grabs->next;
1559     }
1560
1561   return NULL;
1562 }
1563
1564 static GList *
1565 find_device_grab (GdkDisplay *display,
1566                    GdkDevice  *device,
1567                    gulong      serial)
1568 {
1569   GList *l;
1570
1571   l = g_hash_table_lookup (display->device_grabs, device);
1572   return grab_list_find (l, serial);
1573 }
1574
1575 GdkDeviceGrabInfo *
1576 _gdk_display_has_device_grab (GdkDisplay *display,
1577                               GdkDevice  *device,
1578                               gulong      serial)
1579 {
1580   GList *l;
1581
1582   l = find_device_grab (display, device, serial);
1583   if (l)
1584     return l->data;
1585
1586   return NULL;
1587 }
1588
1589 /* Returns true if last grab was ended
1590  * If if_child is non-NULL, end the grab only if the grabbed
1591  * window is the same as if_child or a descendant of it */
1592 gboolean
1593 _gdk_display_end_device_grab (GdkDisplay *display,
1594                               GdkDevice  *device,
1595                               gulong      serial,
1596                               GdkWindow  *if_child,
1597                               gboolean    implicit)
1598 {
1599   GdkDeviceGrabInfo *grab;
1600   GList *l;
1601
1602   l = find_device_grab (display, device, serial);
1603
1604   if (l == NULL)
1605     return FALSE;
1606
1607   grab = l->data;
1608   if (grab &&
1609       (if_child == NULL ||
1610        _gdk_window_event_parent_of (if_child, grab->window)))
1611     {
1612       grab->serial_end = serial;
1613       grab->implicit_ungrab = implicit;
1614       return l->next == NULL;
1615     }
1616   
1617   return FALSE;
1618 }
1619
1620 /* Returns TRUE if device events are not blocked by any grab */
1621 gboolean
1622 _gdk_display_check_grab_ownership (GdkDisplay *display,
1623                                    GdkDevice  *device,
1624                                    gulong      serial)
1625 {
1626   GHashTableIter iter;
1627   gpointer key, value;
1628   GdkGrabOwnership higher_ownership, device_ownership;
1629   gboolean device_is_keyboard;
1630
1631   g_hash_table_iter_init (&iter, display->device_grabs);
1632   higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1633   device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1634
1635   while (g_hash_table_iter_next (&iter, &key, &value))
1636     {
1637       GdkDeviceGrabInfo *grab;
1638       GdkDevice *dev;
1639       GList *grabs;
1640
1641       dev = key;
1642       grabs = value;
1643       grabs = grab_list_find (grabs, serial);
1644
1645       if (!grabs)
1646         continue;
1647
1648       /* Discard device if it's not of the same type */
1649       if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) ||
1650           (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD))
1651         continue;
1652
1653       grab = grabs->data;
1654
1655       if (dev == device)
1656         device_ownership = grab->ownership;
1657       else
1658         {
1659           if (grab->ownership > higher_ownership)
1660             higher_ownership = grab->ownership;
1661         }
1662     }
1663
1664   if (higher_ownership > device_ownership)
1665     {
1666       /* There's a higher priority ownership
1667        * going on for other device(s)
1668        */
1669       return FALSE;
1670     }
1671
1672   return TRUE;
1673 }
1674
1675 GdkPointerWindowInfo *
1676 _gdk_display_get_pointer_info (GdkDisplay *display,
1677                                GdkDevice  *device)
1678 {
1679   GdkPointerWindowInfo *info;
1680
1681   if (G_UNLIKELY (!device))
1682     return NULL;
1683
1684   info = g_hash_table_lookup (display->pointers_info, device);
1685
1686   if (G_UNLIKELY (!info))
1687     {
1688       info = g_slice_new0 (GdkPointerWindowInfo);
1689       g_hash_table_insert (display->pointers_info, device, info);
1690     }
1691
1692   return info;
1693 }
1694
1695 void
1696 _gdk_display_pointer_info_foreach (GdkDisplay                   *display,
1697                                    GdkDisplayPointerInfoForeach  func,
1698                                    gpointer                      user_data)
1699 {
1700   GHashTableIter iter;
1701   gpointer key, value;
1702
1703   g_hash_table_iter_init (&iter, display->pointers_info);
1704
1705   while (g_hash_table_iter_next (&iter, &key, &value))
1706     {
1707       GdkPointerWindowInfo *info = value;
1708       GdkDevice *device = key;
1709
1710       (func) (display, device, info, user_data);
1711     }
1712 }
1713
1714 /**
1715  * gdk_device_grab_info_libgtk_only:
1716  * @display: the display for which to get the grab information
1717  * @device: device to get the grab information from
1718  * @grab_window: (out) (transfer none): location to store current grab window
1719  * @owner_events: (out): location to store boolean indicating whether
1720  *   the @owner_events flag to gdk_keyboard_grab() or
1721  *   gdk_pointer_grab() was %TRUE.
1722  *
1723  * Determines information about the current keyboard grab.
1724  * This is not public API and must not be used by applications.
1725  *
1726  * Return value: %TRUE if this application currently has the
1727  *  keyboard grabbed.
1728  **/
1729 gboolean
1730 gdk_device_grab_info_libgtk_only (GdkDisplay  *display,
1731                                   GdkDevice   *device,
1732                                   GdkWindow  **grab_window,
1733                                   gboolean    *owner_events)
1734 {
1735   GdkDeviceGrabInfo *info;
1736
1737   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1738   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1739
1740   info = _gdk_display_get_last_device_grab (display, device);
1741
1742   if (info)
1743     {
1744       if (grab_window)
1745         *grab_window = info->window;
1746       if (owner_events)
1747         *owner_events = info->owner_events;
1748
1749       return TRUE;
1750     }
1751   else
1752     return FALSE;
1753 }
1754
1755 /**
1756  * gdk_display_pointer_is_grabbed:
1757  * @display: a #GdkDisplay
1758  *
1759  * Test if the pointer is grabbed.
1760  *
1761  * Returns: %TRUE if an active X pointer grab is in effect
1762  *
1763  * Since: 2.2
1764  *
1765  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1766  */
1767 gboolean
1768 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1769 {
1770   GdkDeviceManager *device_manager;
1771   GList *devices, *dev;
1772   GdkDevice *device;
1773
1774   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1775
1776   device_manager = gdk_display_get_device_manager (display);
1777   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1778
1779   for (dev = devices; dev; dev = dev->next)
1780     {
1781       device = dev->data;
1782
1783       if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
1784           gdk_display_device_is_grabbed (display, device))
1785         return TRUE;
1786     }
1787
1788   return FALSE;
1789 }
1790
1791 /**
1792  * gdk_display_device_is_grabbed:
1793  * @display: a #GdkDisplay
1794  * @device: a #GdkDevice
1795  *
1796  * Returns %TRUE if there is an ongoing grab on @device for @display.
1797  *
1798  * Returns: %TRUE if there is a grab in effect for @device.
1799  **/
1800 gboolean
1801 gdk_display_device_is_grabbed (GdkDisplay *display,
1802                                GdkDevice  *device)
1803 {
1804   GdkDeviceGrabInfo *info;
1805
1806   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1807   g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1808
1809   /* What we're interested in is the steady state (ie last grab),
1810      because we're interested e.g. if we grabbed so that we
1811      can ungrab, even if our grab is not active just yet. */
1812   info = _gdk_display_get_last_device_grab (display, device);
1813
1814   return (info && !info->implicit);
1815 }
1816
1817 /**
1818  * gdk_display_get_device_manager:
1819  * @display: a #GdkDisplay.
1820  *
1821  * Returns the #GdkDeviceManager associated to @display.
1822  *
1823  * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is
1824  *          owned by GDK and must not be freed or unreferenced.
1825  *
1826  * Since: 3.0
1827  **/
1828 GdkDeviceManager *
1829 gdk_display_get_device_manager (GdkDisplay *display)
1830 {
1831   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1832
1833   return display->device_manager;
1834 }
1835
1836 /**
1837  * gdk_display_get_name:
1838  * @display: a #GdkDisplay
1839  *
1840  * Gets the name of the display.
1841  *
1842  * Returns: a string representing the display name. This string is owned
1843  * by GDK and should not be modified or freed.
1844  *
1845  * Since: 2.2
1846  */
1847 G_CONST_RETURN gchar *
1848 gdk_display_get_name (GdkDisplay *display)
1849 {
1850   return GDK_DISPLAY_GET_CLASS(display)->get_name (display);
1851 }
1852
1853 gchar *
1854 gdk_get_display (void)
1855 {
1856   return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
1857 }
1858
1859 /**
1860  * gdk_display_get_n_screens:
1861  * @display: a #GdkDisplay
1862  *
1863  * Gets the number of screen managed by the @display.
1864  *
1865  * Returns: number of screens.
1866  *
1867  * Since: 2.2
1868  */
1869 gint
1870 gdk_display_get_n_screens (GdkDisplay *display)
1871 {
1872   return GDK_DISPLAY_GET_CLASS(display)->get_n_screens (display);
1873 }
1874
1875 /**
1876  * gdk_display_get_screen:
1877  * @display: a #GdkDisplay
1878  * @screen_num: the screen number
1879  *
1880  * Returns a screen object for one of the screens of the display.
1881  *
1882  * Returns: (transfer none): the #GdkScreen object
1883  *
1884  * Since: 2.2
1885  */
1886 GdkScreen *
1887 gdk_display_get_screen (GdkDisplay *display,
1888                         gint        screen_num)
1889 {
1890   return GDK_DISPLAY_GET_CLASS(display)->get_screen (display, screen_num);
1891 }
1892
1893 /**
1894  * gdk_display_get_default_screen:
1895  * @display: a #GdkDisplay
1896  *
1897  * Get the default #GdkScreen for @display.
1898  *
1899  * Returns: (transfer none): the default #GdkScreen object for @display
1900  *
1901  * Since: 2.2
1902  */
1903 GdkScreen *
1904 gdk_display_get_default_screen (GdkDisplay *display)
1905 {
1906   return GDK_DISPLAY_GET_CLASS(display)->get_default_screen (display);
1907 }
1908
1909 /**
1910  * gdk_display_beep:
1911  * @display: a #GdkDisplay
1912  *
1913  * Emits a short beep on @display
1914  *
1915  * Since: 2.2
1916  */
1917 void
1918 gdk_display_beep (GdkDisplay *display)
1919 {
1920   GDK_DISPLAY_GET_CLASS(display)->beep (display);
1921 }
1922
1923 /**
1924  * gdk_display_sync:
1925  * @display: a #GdkDisplay
1926  *
1927  * Flushes any requests queued for the windowing system and waits until all
1928  * requests have been handled. This is often used for making sure that the
1929  * display is synchronized with the current state of the program. Calling
1930  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
1931  * generated from earlier requests are handled before the error trap is
1932  * removed.
1933  *
1934  * This is most useful for X11. On windowing systems where requests are
1935  * handled synchronously, this function will do nothing.
1936  *
1937  * Since: 2.2
1938  */
1939 void
1940 gdk_display_sync (GdkDisplay *display)
1941 {
1942   GDK_DISPLAY_GET_CLASS(display)->sync (display);
1943 }
1944
1945 /**
1946  * gdk_display_flush:
1947  * @display: a #GdkDisplay
1948  *
1949  * Flushes any requests queued for the windowing system; this happens automatically
1950  * when the main loop blocks waiting for new events, but if your application
1951  * is drawing without returning control to the main loop, you may need
1952  * to call this function explicitely. A common case where this function
1953  * needs to be called is when an application is executing drawing commands
1954  * from a thread other than the thread where the main loop is running.
1955  *
1956  * This is most useful for X11. On windowing systems where requests are
1957  * handled synchronously, this function will do nothing.
1958  *
1959  * Since: 2.4
1960  */
1961 void
1962 gdk_display_flush (GdkDisplay *display)
1963 {
1964   GDK_DISPLAY_GET_CLASS(display)->flush (display);
1965 }
1966
1967 /**
1968  * gdk_display_get_default_group:
1969  * @display: a #GdkDisplay
1970  *
1971  * Returns the default group leader window for all toplevel windows
1972  * on @display. This window is implicitly created by GDK.
1973  * See gdk_window_set_group().
1974  *
1975  * Return value: (transfer none): The default group leader window
1976  * for @display
1977  *
1978  * Since: 2.4
1979  **/
1980 GdkWindow *
1981 gdk_display_get_default_group (GdkDisplay *display)
1982 {
1983   return GDK_DISPLAY_GET_CLASS(display)->get_default_group (display);
1984 }
1985
1986 /**
1987  * gdk_display_supports_selection_notification:
1988  * @display: a #GdkDisplay
1989  *
1990  * Returns whether #GdkEventOwnerChange events will be
1991  * sent when the owner of a selection changes.
1992  *
1993  * Return value: whether #GdkEventOwnerChange events will
1994  *               be sent.
1995  *
1996  * Since: 2.6
1997  **/
1998 gboolean
1999 gdk_display_supports_selection_notification (GdkDisplay *display)
2000 {
2001   return GDK_DISPLAY_GET_CLASS(display)->supports_selection_notification (display);
2002 }
2003
2004 /**
2005  * gdk_display_request_selection_notification:
2006  * @display: a #GdkDisplay
2007  * @selection: the #GdkAtom naming the selection for which
2008  *             ownership change notification is requested
2009  *
2010  * Request #GdkEventOwnerChange events for ownership changes
2011  * of the selection named by the given atom.
2012  *
2013  * Return value: whether #GdkEventOwnerChange events will
2014  *               be sent.
2015  *
2016  * Since: 2.6
2017  **/
2018 gboolean
2019 gdk_display_request_selection_notification (GdkDisplay *display,
2020                                             GdkAtom     selection)
2021
2022 {
2023   return GDK_DISPLAY_GET_CLASS(display)->request_selection_notification (display, selection);
2024 }
2025
2026 /**
2027  * gdk_display_supports_clipboard_persistence
2028  * @display: a #GdkDisplay
2029  *
2030  * Returns whether the speicifed display supports clipboard
2031  * persistance; i.e. if it's possible to store the clipboard data after an
2032  * application has quit. On X11 this checks if a clipboard daemon is
2033  * running.
2034  *
2035  * Returns: %TRUE if the display supports clipboard persistance.
2036  *
2037  * Since: 2.6
2038  */
2039 gboolean
2040 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
2041 {
2042   return GDK_DISPLAY_GET_CLASS(display)->supports_clipboard_persistence (display);
2043 }
2044
2045 /**
2046  * gdk_display_store_clipboard
2047  * @display:          a #GdkDisplay
2048  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
2049  * @time_:            a timestamp
2050  * @targets:          an array of targets that should be saved, or %NULL
2051  *                    if all available targets should be saved.
2052  * @n_targets:        length of the @targets array
2053  *
2054  * Issues a request to the clipboard manager to store the
2055  * clipboard data. On X11, this is a special program that works
2056  * according to the freedesktop clipboard specification, available at
2057  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
2058  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
2059  *
2060  * Since: 2.6
2061  */
2062 void
2063 gdk_display_store_clipboard (GdkDisplay    *display,
2064                              GdkWindow     *clipboard_window,
2065                              guint32        time_,
2066                              const GdkAtom *targets,
2067                              gint           n_targets)
2068 {
2069   GDK_DISPLAY_GET_CLASS(display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
2070 }
2071
2072 /**
2073  * gdk_display_supports_shapes:
2074  * @display: a #GdkDisplay
2075  *
2076  * Returns %TRUE if gdk_window_shape_combine_mask() can
2077  * be used to create shaped windows on @display.
2078  *
2079  * Returns: %TRUE if shaped windows are supported
2080  *
2081  * Since: 2.10
2082  */
2083 gboolean
2084 gdk_display_supports_shapes (GdkDisplay *display)
2085 {
2086   return GDK_DISPLAY_GET_CLASS(display)->supports_shapes (display);
2087 }
2088
2089 /**
2090  * gdk_display_supports_input_shapes:
2091  * @display: a #GdkDisplay
2092  *
2093  * Returns %TRUE if gdk_window_input_shape_combine_mask() can
2094  * be used to modify the input shape of windows on @display.
2095  *
2096  * Returns: %TRUE if windows with modified input shape are supported
2097  *
2098  * Since: 2.10
2099  */
2100 gboolean
2101 gdk_display_supports_input_shapes (GdkDisplay *display)
2102 {
2103   return GDK_DISPLAY_GET_CLASS(display)->supports_input_shapes (display);
2104 }
2105
2106 /**
2107  * gdk_display_supports_composite:
2108  * @display: a #GdkDisplay
2109  *
2110  * Returns %TRUE if gdk_window_set_composited() can be used
2111  * to redirect drawing on the window using compositing.
2112  *
2113  * Currently this only works on X11 with XComposite and
2114  * XDamage extensions available.
2115  *
2116  * Returns: %TRUE if windows may be composited.
2117  *
2118  * Since: 2.12
2119  */
2120 gboolean
2121 gdk_display_supports_composite (GdkDisplay *display)
2122 {
2123   return GDK_DISPLAY_GET_CLASS(display)->supports_composite (display);
2124 }
2125
2126 /**
2127  * gdk_display_list_devices:
2128  * @display: a #GdkDisplay
2129  *
2130  * Returns the list of available input devices attached to @display.
2131  * The list is statically allocated and should not be freed.
2132  *
2133  * Return value: (transfer none) (element-type GdkDevice):
2134  *     a list of #GdkDevice
2135  *
2136  * Since: 2.2
2137  *
2138  * Deprecated: 3.0: Use gdk_device_manager_list_devices() instead.
2139  **/
2140 GList *
2141 gdk_display_list_devices (GdkDisplay *display)
2142 {
2143   return GDK_DISPLAY_GET_CLASS(display)->list_devices (display);
2144 }
2145
2146 /**
2147  * gdk_event_send_client_message_for_display:
2148  * @display: the #GdkDisplay for the window where the message is to be sent.
2149  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
2150  * @winid: the window to send the client message to.
2151  *
2152  * On X11, sends an X ClientMessage event to a given window. On
2153  * Windows, sends a message registered with the name
2154  * GDK_WIN32_CLIENT_MESSAGE.
2155  *
2156  * This could be used for communicating between different
2157  * applications, though the amount of data is limited to 20 bytes on
2158  * X11, and to just four bytes on Windows.
2159  *
2160  * Returns: non-zero on success.
2161  *
2162  * Since: 2.2
2163  */
2164 gboolean
2165 gdk_event_send_client_message_for_display (GdkDisplay     *display,
2166                                            GdkEvent       *event,
2167                                            GdkNativeWindow winid)
2168 {
2169   return GDK_DISPLAY_GET_CLASS(display)->send_client_message (display, event, winid);
2170 }
2171
2172 /**
2173  * gdk_display_add_client_message_filter:
2174  * @display: a #GdkDisplay for which this message filter applies
2175  * @message_type: the type of ClientMessage events to receive.
2176  *   This will be checked against the @message_type field
2177  *   of the XClientMessage event struct.
2178  * @func: the function to call to process the event.
2179  * @data: user data to pass to @func.
2180  *
2181  * Adds a filter to be called when X ClientMessage events are received.
2182  * See gdk_window_add_filter() if you are interested in filtering other
2183  * types of events.
2184  *
2185  * Since: 2.2
2186  **/
2187 void
2188 gdk_display_add_client_message_filter (GdkDisplay   *display,
2189                                        GdkAtom       message_type,
2190                                        GdkFilterFunc func,
2191                                        gpointer      data)
2192 {
2193   GDK_DISPLAY_GET_CLASS(display)->add_client_message_filter (display, message_type, func, data);
2194 }
2195
2196 /**
2197  * gdk_add_client_message_filter:
2198  * @message_type: the type of ClientMessage events to receive. This will be
2199  *     checked against the <structfield>message_type</structfield> field of the
2200  *     XClientMessage event struct.
2201  * @func: the function to call to process the event.
2202  * @data: user data to pass to @func.
2203  *
2204  * Adds a filter to the default display to be called when X ClientMessage events
2205  * are received. See gdk_display_add_client_message_filter().
2206  **/
2207 void
2208 gdk_add_client_message_filter (GdkAtom       message_type,
2209                                GdkFilterFunc func,
2210                                gpointer      data)
2211 {
2212   gdk_display_add_client_message_filter (gdk_display_get_default (),
2213                                          message_type, func, data);
2214 }
2215
2216 static GdkAppLaunchContext *
2217 gdk_display_real_get_app_launch_context (GdkDisplay *display)
2218 {
2219   GdkAppLaunchContext *ctx;
2220
2221   ctx = gdk_app_launch_context_new ();
2222   gdk_app_launch_context_set_display (ctx, display);
2223
2224   return ctx;
2225 }
2226
2227 /**
2228  * gdk_display_get_app_launch_context:
2229  * @display: a #GdkDisplay
2230  *
2231  * Returns a #GdkAppLaunchContext suitable for launching
2232  * applications on the given display.
2233  *
2234  * Returns: a new #GdkAppLaunchContext for @display.
2235  *     Free with g_object_unref() when done
2236  *
2237  * Since: 3.0
2238  */
2239 GdkAppLaunchContext *
2240 gdk_display_get_app_launch_context (GdkDisplay *display)
2241 {
2242   return GDK_DISPLAY_GET_CLASS(display)->get_app_launch_context (display);
2243 }
2244
2245 /**
2246  * gdk_drag_get_protocol_for_display:
2247  * @display: the #GdkDisplay where the destination window resides
2248  * @xid: the windowing system id of the destination window.
2249  * @protocol: location where the supported DND protocol is returned.
2250  *
2251  * Finds out the DND protocol supported by a window.
2252  *
2253  * Return value: the windowing system id of the window where the drop
2254  *    should happen. This may be @xid or the id of a proxy window,
2255  *    or zero if @xid does not support Drag and Drop.
2256  *
2257  * Since: 2.2
2258  */
2259 GdkNativeWindow
2260 gdk_drag_get_protocol_for_display (GdkDisplay      *display,
2261                                    GdkNativeWindow  xid,
2262                                    GdkDragProtocol *protocol)
2263 {
2264   return GDK_DISPLAY_GET_CLASS (display)->get_drag_protocol (display, xid, protocol, NULL);
2265 }
2266
2267 /**
2268  * gdk_display_open:
2269  * @display_name: the name of the display to open
2270  *
2271  * Opens a display.
2272  *
2273  * Return value: (transfer none): a #GdkDisplay, or %NULL if the display
2274  *               could not be opened.
2275  *
2276  * Since: 2.2
2277  */
2278 GdkDisplay *
2279 gdk_display_open (const gchar *display_name)
2280 {
2281   return gdk_display_manager_open_display (gdk_display_manager_get (), display_name);
2282 }
2283
2284 gboolean
2285 gdk_display_has_pending (GdkDisplay *display)
2286 {
2287   return GDK_DISPLAY_GET_CLASS (display)->has_pending (display);
2288 }
2289
2290 /**
2291  * gdk_display_supports_cursor_alpha:
2292  * @display: a #GdkDisplay
2293  *
2294  * Returns %TRUE if cursors can use an 8bit alpha channel
2295  * on @display. Otherwise, cursors are restricted to bilevel
2296  * alpha (i.e. a mask).
2297  *
2298  * Returns: whether cursors can have alpha channels.
2299  *
2300  * Since: 2.4
2301  */
2302 gboolean
2303 gdk_display_supports_cursor_alpha (GdkDisplay *display)
2304 {
2305   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2306
2307   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_alpha (display);
2308 }
2309
2310 /**
2311  * gdk_display_supports_cursor_color:
2312  * @display: a #GdkDisplay
2313  *
2314  * Returns %TRUE if multicolored cursors are supported
2315  * on @display. Otherwise, cursors have only a forground
2316  * and a background color.
2317  *
2318  * Returns: whether cursors can have multiple colors.
2319  *
2320  * Since: 2.4
2321  */
2322 gboolean
2323 gdk_display_supports_cursor_color (GdkDisplay *display)
2324 {
2325   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2326
2327   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_color (display);
2328 }
2329
2330 /**
2331  * gdk_display_get_default_cursor_size:
2332  * @display: a #GdkDisplay
2333  *
2334  * Returns the default size to use for cursors on @display.
2335  *
2336  * Returns: the default cursor size.
2337  *
2338  * Since: 2.4
2339  */
2340 guint
2341 gdk_display_get_default_cursor_size (GdkDisplay *display)
2342 {
2343   guint width, height;
2344
2345   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
2346
2347   GDK_DISPLAY_GET_CLASS (display)->get_default_cursor_size (display,
2348                                                             &width,
2349                                                             &height);
2350
2351   return MIN (width, height);
2352 }
2353
2354 /**
2355  * gdk_display_get_maximal_cursor_size:
2356  * @display: a #GdkDisplay
2357  * @width: (out): the return location for the maximal cursor width
2358  * @height: (out): the return location for the maximal cursor height
2359  *
2360  * Gets the maximal size to use for cursors on @display.
2361  *
2362  * Since: 2.4
2363  */
2364 void
2365 gdk_display_get_maximal_cursor_size (GdkDisplay *display,
2366                                      guint       *width,
2367                                      guint       *height)
2368 {
2369   g_return_if_fail (GDK_IS_DISPLAY (display));
2370
2371   GDK_DISPLAY_GET_CLASS (display)->get_maximal_cursor_size (display,
2372                                                             width,
2373                                                             height);
2374 }
2375
2376 /**
2377  * gdk_display_warp_pointer:
2378  * @display: a #GdkDisplay
2379  * @screen: the screen of @display to warp the pointer to
2380  * @x: the x coordinate of the destination
2381  * @y: the y coordinate of the destination
2382  *
2383  * Warps the pointer of @display to the point @x,@y on
2384  * the screen @screen, unless the pointer is confined
2385  * to a window by a grab, in which case it will be moved
2386  * as far as allowed by the grab. Warping the pointer
2387  * creates events as if the user had moved the mouse
2388  * instantaneously to the destination.
2389  *
2390  * Note that the pointer should normally be under the
2391  * control of the user. This function was added to cover
2392  * some rare use cases like keyboard navigation support
2393  * for the color picker in the #GtkColorSelectionDialog.
2394  *
2395  * Since: 2.8
2396  *
2397  * Deprecated: 3.0: Use gdk_device_warp() instead.
2398  */
2399 void
2400 gdk_display_warp_pointer (GdkDisplay *display,
2401                           GdkScreen  *screen,
2402                           gint        x,
2403                           gint        y)
2404 {
2405   gdk_device_warp (display->core_pointer,
2406                    screen,
2407                    x, y);
2408 }
2409
2410 gulong
2411 _gdk_display_get_next_serial (GdkDisplay *display)
2412 {
2413   return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display);
2414 }
2415
2416
2417 /**
2418  * gdk_notify_startup_complete:
2419  *
2420  * Indicates to the GUI environment that the application has finished
2421  * loading. If the applications opens windows, this function is
2422  * normally called after opening the application's initial set of
2423  * windows.
2424  *
2425  * GTK+ will call this function automatically after opening the first
2426  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
2427  * to disable that feature.
2428  *
2429  * Since: 2.2
2430  **/
2431 void
2432 gdk_notify_startup_complete (void)
2433 {
2434   gdk_notify_startup_complete_with_id (NULL);
2435 }
2436
2437 /**
2438  * gdk_notify_startup_complete_with_id:
2439  * @startup_id: a startup-notification identifier, for which notification
2440  *              process should be completed
2441  *
2442  * Indicates to the GUI environment that the application has finished
2443  * loading, using a given identifier.
2444  *
2445  * GTK+ will call this function automatically for #GtkWindow with custom
2446  * startup-notification identifier unless
2447  * gtk_window_set_auto_startup_notification() is called to disable
2448  * that feature.
2449  *
2450  * Since: 2.12
2451  */
2452 void
2453 gdk_notify_startup_complete_with_id (const gchar* startup_id)
2454 {
2455   GdkDisplay *display;
2456
2457   display = gdk_display_get_default ();
2458   if (display)
2459     gdk_display_notify_startup_complete (display, startup_id);
2460 }
2461
2462 void
2463 gdk_display_notify_startup_complete (GdkDisplay  *display,
2464                                      const gchar *startup_id)
2465 {
2466   GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
2467 }
2468
2469 void
2470 _gdk_display_event_data_copy (GdkDisplay     *display,
2471                               const GdkEvent *event,
2472                               GdkEvent       *new_event)
2473 {
2474   GDK_DISPLAY_GET_CLASS (display)->event_data_copy (display, event, new_event);
2475 }
2476
2477 void
2478 _gdk_display_event_data_free (GdkDisplay *display,
2479                               GdkEvent   *event)
2480 {
2481   GDK_DISPLAY_GET_CLASS (display)->event_data_free (display, event);
2482 }
2483
2484 void
2485 _gdk_display_create_window_impl (GdkDisplay       *display,
2486                                  GdkWindow        *window,
2487                                  GdkWindow        *real_parent,
2488                                  GdkScreen        *screen,
2489                                  GdkEventMask      event_mask,
2490                                  GdkWindowAttr    *attributes,
2491                                  gint              attributes_mask)
2492 {
2493   GDK_DISPLAY_GET_CLASS (display)->create_window_impl (display,
2494                                                        window,
2495                                                        real_parent,
2496                                                        screen,
2497                                                        event_mask,
2498                                                        attributes,
2499                                                        attributes_mask);
2500 }
2501
2502 GdkWindow *
2503 _gdk_display_create_window (GdkDisplay *display)
2504 {
2505   return g_object_new (GDK_DISPLAY_GET_CLASS (display)->window_type, NULL);
2506 }
2507
2508 /**
2509  * gdk_keymap_get_for_display:
2510  * @display: the #GdkDisplay.
2511  *
2512  * Returns the #GdkKeymap attached to @display.
2513  *
2514  * Return value: (transfer none): the #GdkKeymap attached to @display.
2515  *
2516  * Since: 2.2
2517  */
2518 GdkKeymap*
2519 gdk_keymap_get_for_display (GdkDisplay *display)
2520 {
2521   return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
2522 }
2523
2524 typedef struct _GdkGlobalErrorTrap  GdkGlobalErrorTrap;
2525
2526 struct _GdkGlobalErrorTrap
2527 {
2528   GSList *displays;
2529 };
2530
2531 static GQueue gdk_error_traps = G_QUEUE_INIT;
2532
2533 /**
2534  * gdk_error_trap_push:
2535  *
2536  * This function allows X errors to be trapped instead of the normal
2537  * behavior of exiting the application. It should only be used if it
2538  * is not possible to avoid the X error in any other way. Errors are
2539  * ignored on all #GdkDisplay currently known to the
2540  * #GdkDisplayManager. If you don't care which error happens and just
2541  * want to ignore everything, pop with gdk_error_trap_pop_ignored().
2542  * If you need the error code, use gdk_error_trap_pop() which may have
2543  * to block and wait for the error to arrive from the X server.
2544  *
2545  * This API exists on all platforms but only does anything on X.
2546  *
2547  * You can use gdk_x11_display_error_trap_push() to ignore errors
2548  * on only a single display.
2549  *
2550 * <example>
2551  * <title>Trapping an X error</title>
2552  * <programlisting>
2553  * gdk_error_trap_push (<!-- -->);
2554  *
2555  *  // ... Call the X function which may cause an error here ...
2556  *
2557  *
2558  * if (gdk_error_trap_pop (<!-- -->))
2559  *  {
2560  *    // ... Handle the error here ...
2561  *  }
2562  * </programlisting>
2563  * </example>
2564  */
2565 void
2566 gdk_error_trap_push (void)
2567 {
2568   GdkDisplayManager *manager;
2569   GdkDisplayClass *class;
2570   GdkGlobalErrorTrap *trap;
2571   GSList *l;
2572
2573   manager = gdk_display_manager_get ();
2574   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2575
2576   if (class->push_error_trap == NULL)
2577     return;
2578
2579   trap = g_slice_new (GdkGlobalErrorTrap);
2580   trap->displays = gdk_display_manager_list_displays (manager);
2581
2582   g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
2583   for (l = trap->displays; l != NULL; l = l->next)
2584     {
2585       class->push_error_trap (l->data);
2586     }
2587
2588   g_queue_push_head (&gdk_error_traps, trap);
2589 }
2590
2591 static gint
2592 gdk_error_trap_pop_internal (gboolean need_code)
2593 {
2594   GdkDisplayManager *manager;
2595   GdkDisplayClass *class;
2596   GdkGlobalErrorTrap *trap;
2597   gint result;
2598   GSList *l;
2599
2600   manager = gdk_display_manager_get ();
2601   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2602
2603   if (class->pop_error_trap == NULL)
2604     return 0;
2605
2606   trap = g_queue_pop_head (&gdk_error_traps);
2607
2608   g_return_val_if_fail (trap != NULL, 0);
2609
2610   result = 0;
2611   for (l = trap->displays; l != NULL; l = l->next)
2612     {
2613       gint code = 0;
2614
2615       code = class->pop_error_trap (l->data, !need_code);
2616
2617       /* we use the error on the last display listed, why not. */
2618       if (code != 0)
2619         result = code;
2620     }
2621
2622   g_slist_free_full (trap->displays, g_object_unref);
2623   g_slice_free (GdkGlobalErrorTrap, trap);
2624
2625   return result;
2626 }
2627
2628 /**
2629  * gdk_error_trap_pop_ignored:
2630  *
2631  * Removes an error trap pushed with gdk_error_trap_push(), but
2632  * without bothering to wait and see whether an error occurred.  If an
2633  * error arrives later asynchronously that was triggered while the
2634  * trap was pushed, that error will be ignored.
2635  *
2636  * Since: 3.0
2637  */
2638 void
2639 gdk_error_trap_pop_ignored (void)
2640 {
2641   gdk_error_trap_pop_internal (FALSE);
2642 }
2643
2644 /**
2645  * gdk_error_trap_pop:
2646  *
2647  * Removes an error trap pushed with gdk_error_trap_push().
2648  * May block until an error has been definitively received
2649  * or not received from the X server. gdk_error_trap_pop_ignored()
2650  * is preferred if you don't need to know whether an error
2651  * occurred, because it never has to block. If you don't
2652  * need the return value of gdk_error_trap_pop(), use
2653  * gdk_error_trap_pop_ignored().
2654  *
2655  * Prior to GDK 3.0, this function would not automatically
2656  * sync for you, so you had to gdk_flush() if your last
2657  * call to Xlib was not a blocking round trip.
2658  *
2659  * Return value: X error code or 0 on success
2660  */
2661 gint
2662 gdk_error_trap_pop (void)
2663 {
2664   return gdk_error_trap_pop_internal (TRUE);
2665 }