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