]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
gdk: add precondition checks to many GdkDisplay functions
[~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   /* We use the native crossing events if all native */
768   if (_gdk_native_windows)
769     return;
770   
771   if (src_window)
772     src_toplevel = gdk_window_get_toplevel (src_window);
773   else
774     src_toplevel = NULL;
775   if (dest_window)
776     dest_toplevel = gdk_window_get_toplevel (dest_window);
777   else
778     dest_toplevel = NULL;
779
780   if (src_toplevel == NULL && dest_toplevel == NULL)
781     return;
782   
783   if (src_toplevel == NULL ||
784       src_toplevel == dest_toplevel)
785     {
786       /* Same toplevels */
787       gdk_window_get_pointer (dest_toplevel,
788                               &x, &y, &state);
789       _gdk_synthesize_crossing_events (display,
790                                        src_window,
791                                        dest_window,
792                                        device, source_device,
793                                        crossing_mode,
794                                        x, y, state,
795                                        time,
796                                        NULL,
797                                        serial, FALSE);
798     }
799   else if (dest_toplevel == NULL)
800     {
801       gdk_window_get_pointer (src_toplevel,
802                               &x, &y, &state);
803       _gdk_synthesize_crossing_events (display,
804                                        src_window,
805                                        NULL,
806                                        device, source_device,
807                                        crossing_mode,
808                                        x, y, state,
809                                        time,
810                                        NULL,
811                                        serial, FALSE);
812     }
813   else
814     {
815       /* Different toplevels */
816       gdk_window_get_pointer (src_toplevel,
817                               &x, &y, &state);
818       _gdk_synthesize_crossing_events (display,
819                                        src_window,
820                                        NULL,
821                                        device, source_device,
822                                        crossing_mode,
823                                        x, y, state,
824                                        time,
825                                        NULL,
826                                        serial, FALSE);
827       gdk_window_get_pointer (dest_toplevel,
828                               &x, &y, &state);
829       _gdk_synthesize_crossing_events (display,
830                                        NULL,
831                                        dest_window,
832                                        device, source_device,
833                                        crossing_mode,
834                                        x, y, state,
835                                        time,
836                                        NULL,
837                                        serial, FALSE);
838     }
839 }
840
841 static GdkWindow *
842 get_current_toplevel (GdkDisplay      *display,
843                       GdkDevice       *device,
844                       int             *x_out,
845                       int             *y_out,
846                       GdkModifierType *state_out)
847 {
848   GdkWindow *pointer_window;
849   int x, y;
850   GdkModifierType state;
851
852   pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
853
854   if (pointer_window != NULL &&
855       (GDK_WINDOW_DESTROYED (pointer_window) ||
856        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
857        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
858     pointer_window = NULL;
859
860   *x_out = x;
861   *y_out = y;
862   *state_out = state;
863
864   return pointer_window;
865 }
866
867 static void
868 switch_to_pointer_grab (GdkDisplay        *display,
869                         GdkDevice         *device,
870                         GdkDevice         *source_device,
871                         GdkDeviceGrabInfo *grab,
872                         GdkDeviceGrabInfo *last_grab,
873                         guint32            time,
874                         gulong             serial)
875 {
876   GdkWindow *src_window, *pointer_window, *new_toplevel;
877   GdkPointerWindowInfo *info;
878   GList *old_grabs;
879   GdkModifierType state;
880   int x = 0, y = 0;
881
882   /* Temporarily unset pointer to make sure we send the crossing events below */
883   old_grabs = g_hash_table_lookup (display->device_grabs, device);
884   g_hash_table_steal (display->device_grabs, device);
885   info = _gdk_display_get_pointer_info (display, device);
886
887   if (grab)
888     {
889       /* New grab is in effect */
890
891       /* We need to generate crossing events for the grab.
892        * However, there are never any crossing events for implicit grabs
893        * TODO: ... Actually, this could happen if the pointer window
894        *           doesn't have button mask so a parent gets the event...
895        */
896       if (!grab->implicit)
897         {
898           /* We send GRAB crossing events from the window under the pointer to the
899              grab window. Except if there is an old grab then we start from that */
900           if (last_grab)
901             src_window = last_grab->window;
902           else
903             src_window = info->window_under_pointer;
904
905           if (src_window != grab->window)
906             synthesize_crossing_events (display, device, source_device,
907                                         src_window, grab->window,
908                                         GDK_CROSSING_GRAB, time, serial);
909
910           /* !owner_event Grabbing a window that we're not inside, current status is
911              now NULL (i.e. outside grabbed window) */
912           if (!grab->owner_events && info->window_under_pointer != grab->window)
913             _gdk_display_set_window_under_pointer (display, device, NULL);
914         }
915
916       grab->activated = TRUE;
917     }
918
919   if (last_grab)
920     {
921       new_toplevel = NULL;
922
923       if (grab == NULL /* ungrab */ ||
924           (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
925         {
926           /* We force check what window we're in, and update the toplevel_under_pointer info,
927            * as that won't get told of this change with toplevel enter events.
928            */
929           if (info->toplevel_under_pointer)
930             g_object_unref (info->toplevel_under_pointer);
931           info->toplevel_under_pointer = NULL;
932
933           /* Ungrabbed slave devices don't have a position by
934            * itself, rather depend on its master pointer, so
935            * it doesn't make sense to track any position for
936            * these after the grab
937            */
938           if (grab || gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE)
939             new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
940
941           if (new_toplevel)
942             {
943               /* w is now toplevel and x,y in toplevel coords */
944               info->toplevel_under_pointer = g_object_ref (new_toplevel);
945               info->toplevel_x = x;
946               info->toplevel_y = y;
947               info->state = state;
948             }
949         }
950
951       if (grab == NULL) /* Ungrabbed, send events */
952         {
953           pointer_window = NULL;
954           if (new_toplevel)
955             {
956               /* Find (possibly virtual) child window */
957               pointer_window =
958                 _gdk_window_find_descendant_at (new_toplevel,
959                                                 x, y,
960                                                 NULL, NULL);
961             }
962
963           if (pointer_window != last_grab->window)
964             synthesize_crossing_events (display, device, source_device,
965                                         last_grab->window, pointer_window,
966                                         GDK_CROSSING_UNGRAB, time, serial);
967
968           /* We're now ungrabbed, update the window_under_pointer */
969           _gdk_display_set_window_under_pointer (display, device, pointer_window);
970         }
971     }
972
973   g_hash_table_insert (display->device_grabs, device, old_grabs);
974 }
975
976 void
977 _gdk_display_device_grab_update (GdkDisplay *display,
978                                  GdkDevice  *device,
979                                  GdkDevice  *source_device,
980                                  gulong      current_serial)
981 {
982   GdkDeviceGrabInfo *current_grab, *next_grab;
983   GList *grabs;
984   guint32 time;
985
986   time = display->last_event_time;
987   grabs = g_hash_table_lookup (display->device_grabs, device);
988
989   while (grabs != NULL)
990     {
991       current_grab = grabs->data;
992
993       if (current_grab->serial_start > current_serial)
994         return; /* Hasn't started yet */
995
996       if (current_grab->serial_end > current_serial)
997         {
998           /* This one hasn't ended yet.
999              its the currently active one or scheduled to be active */
1000
1001           if (!current_grab->activated)
1002             {
1003               if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1004                 switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
1005             }
1006
1007           break;
1008         }
1009
1010       next_grab = NULL;
1011       if (grabs->next)
1012         {
1013           /* This is the next active grab */
1014           next_grab = grabs->next->data;
1015
1016           if (next_grab->serial_start > current_serial)
1017             next_grab = NULL; /* Actually its not yet active */
1018         }
1019
1020       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1021           (next_grab != NULL && current_grab->window != next_grab->window))
1022         generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1023                                     device,
1024                                     current_grab->implicit,
1025                                     next_grab? next_grab->window : NULL);
1026
1027       /* Remove old grab */
1028       grabs = g_list_delete_link (grabs, grabs);
1029       g_hash_table_insert (display->device_grabs, device, grabs);
1030
1031       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1032         switch_to_pointer_grab (display, device, source_device,
1033                                 next_grab, current_grab,
1034                                 time, current_serial);
1035
1036       free_device_grab (current_grab);
1037     }
1038 }
1039
1040 static GList *
1041 grab_list_find (GList  *grabs,
1042                 gulong  serial)
1043 {
1044   GdkDeviceGrabInfo *grab;
1045
1046   while (grabs)
1047     {
1048       grab = grabs->data;
1049
1050       if (serial >= grab->serial_start && serial < grab->serial_end)
1051         return grabs;
1052
1053       grabs = grabs->next;
1054     }
1055
1056   return NULL;
1057 }
1058
1059 static GList *
1060 find_device_grab (GdkDisplay *display,
1061                    GdkDevice  *device,
1062                    gulong      serial)
1063 {
1064   GList *l;
1065
1066   l = g_hash_table_lookup (display->device_grabs, device);
1067   return grab_list_find (l, serial);
1068 }
1069
1070 GdkDeviceGrabInfo *
1071 _gdk_display_has_device_grab (GdkDisplay *display,
1072                               GdkDevice  *device,
1073                               gulong      serial)
1074 {
1075   GList *l;
1076
1077   l = find_device_grab (display, device, serial);
1078   if (l)
1079     return l->data;
1080
1081   return NULL;
1082 }
1083
1084 /* Returns true if last grab was ended
1085  * If if_child is non-NULL, end the grab only if the grabbed
1086  * window is the same as if_child or a descendant of it */
1087 gboolean
1088 _gdk_display_end_device_grab (GdkDisplay *display,
1089                               GdkDevice  *device,
1090                               gulong      serial,
1091                               GdkWindow  *if_child,
1092                               gboolean    implicit)
1093 {
1094   GdkDeviceGrabInfo *grab;
1095   GList *l;
1096
1097   l = find_device_grab (display, device, serial);
1098
1099   if (l == NULL)
1100     return FALSE;
1101
1102   grab = l->data;
1103   if (grab &&
1104       (if_child == NULL ||
1105        _gdk_window_event_parent_of (if_child, grab->window)))
1106     {
1107       grab->serial_end = serial;
1108       grab->implicit_ungrab = implicit;
1109       return l->next == NULL;
1110     }
1111   
1112   return FALSE;
1113 }
1114
1115 /* Returns TRUE if device events are not blocked by any grab */
1116 gboolean
1117 _gdk_display_check_grab_ownership (GdkDisplay *display,
1118                                    GdkDevice  *device,
1119                                    gulong      serial)
1120 {
1121   GHashTableIter iter;
1122   gpointer key, value;
1123   GdkGrabOwnership higher_ownership, device_ownership;
1124   gboolean device_is_keyboard;
1125
1126   g_hash_table_iter_init (&iter, display->device_grabs);
1127   higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1128   device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1129
1130   while (g_hash_table_iter_next (&iter, &key, &value))
1131     {
1132       GdkDeviceGrabInfo *grab;
1133       GdkDevice *dev;
1134       GList *grabs;
1135
1136       dev = key;
1137       grabs = value;
1138       grabs = grab_list_find (grabs, serial);
1139
1140       if (!grabs)
1141         continue;
1142
1143       /* Discard device if it's not of the same type */
1144       if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) ||
1145           (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD))
1146         continue;
1147
1148       grab = grabs->data;
1149
1150       if (dev == device)
1151         device_ownership = grab->ownership;
1152       else
1153         {
1154           if (grab->ownership > higher_ownership)
1155             higher_ownership = grab->ownership;
1156         }
1157     }
1158
1159   if (higher_ownership > device_ownership)
1160     {
1161       /* There's a higher priority ownership
1162        * going on for other device(s)
1163        */
1164       return FALSE;
1165     }
1166
1167   return TRUE;
1168 }
1169
1170 GdkPointerWindowInfo *
1171 _gdk_display_get_pointer_info (GdkDisplay *display,
1172                                GdkDevice  *device)
1173 {
1174   GdkPointerWindowInfo *info;
1175
1176   if (G_UNLIKELY (!device))
1177     return NULL;
1178
1179   info = g_hash_table_lookup (display->pointers_info, device);
1180
1181   if (G_UNLIKELY (!info))
1182     {
1183       info = g_slice_new0 (GdkPointerWindowInfo);
1184       g_hash_table_insert (display->pointers_info, device, info);
1185     }
1186
1187   return info;
1188 }
1189
1190 void
1191 _gdk_display_pointer_info_foreach (GdkDisplay                   *display,
1192                                    GdkDisplayPointerInfoForeach  func,
1193                                    gpointer                      user_data)
1194 {
1195   GHashTableIter iter;
1196   gpointer key, value;
1197
1198   g_hash_table_iter_init (&iter, display->pointers_info);
1199
1200   while (g_hash_table_iter_next (&iter, &key, &value))
1201     {
1202       GdkPointerWindowInfo *info = value;
1203       GdkDevice *device = key;
1204
1205       (func) (display, device, info, user_data);
1206     }
1207 }
1208
1209 /**
1210  * gdk_device_grab_info_libgtk_only:
1211  * @display: the display for which to get the grab information
1212  * @device: device to get the grab information from
1213  * @grab_window: (out) (transfer none): location to store current grab window
1214  * @owner_events: (out): location to store boolean indicating whether
1215  *   the @owner_events flag to gdk_keyboard_grab() or
1216  *   gdk_pointer_grab() was %TRUE.
1217  *
1218  * Determines information about the current keyboard grab.
1219  * This is not public API and must not be used by applications.
1220  *
1221  * Return value: %TRUE if this application currently has the
1222  *  keyboard grabbed.
1223  **/
1224 gboolean
1225 gdk_device_grab_info_libgtk_only (GdkDisplay  *display,
1226                                   GdkDevice   *device,
1227                                   GdkWindow  **grab_window,
1228                                   gboolean    *owner_events)
1229 {
1230   GdkDeviceGrabInfo *info;
1231
1232   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1233   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1234
1235   info = _gdk_display_get_last_device_grab (display, device);
1236
1237   if (info)
1238     {
1239       if (grab_window)
1240         *grab_window = info->window;
1241       if (owner_events)
1242         *owner_events = info->owner_events;
1243
1244       return TRUE;
1245     }
1246   else
1247     return FALSE;
1248 }
1249
1250 /**
1251  * gdk_display_pointer_is_grabbed:
1252  * @display: a #GdkDisplay
1253  *
1254  * Test if the pointer is grabbed.
1255  *
1256  * Returns: %TRUE if an active X pointer grab is in effect
1257  *
1258  * Since: 2.2
1259  *
1260  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1261  */
1262 gboolean
1263 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1264 {
1265   GdkDeviceManager *device_manager;
1266   GList *devices, *dev;
1267   GdkDevice *device;
1268
1269   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1270
1271   device_manager = gdk_display_get_device_manager (display);
1272   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1273
1274   for (dev = devices; dev; dev = dev->next)
1275     {
1276       device = dev->data;
1277
1278       if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
1279           gdk_display_device_is_grabbed (display, device))
1280         return TRUE;
1281     }
1282
1283   return FALSE;
1284 }
1285
1286 /**
1287  * gdk_display_device_is_grabbed:
1288  * @display: a #GdkDisplay
1289  * @device: a #GdkDevice
1290  *
1291  * Returns %TRUE if there is an ongoing grab on @device for @display.
1292  *
1293  * Returns: %TRUE if there is a grab in effect for @device.
1294  **/
1295 gboolean
1296 gdk_display_device_is_grabbed (GdkDisplay *display,
1297                                GdkDevice  *device)
1298 {
1299   GdkDeviceGrabInfo *info;
1300
1301   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1302   g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1303
1304   /* What we're interested in is the steady state (ie last grab),
1305      because we're interested e.g. if we grabbed so that we
1306      can ungrab, even if our grab is not active just yet. */
1307   info = _gdk_display_get_last_device_grab (display, device);
1308
1309   return (info && !info->implicit);
1310 }
1311
1312 /**
1313  * gdk_display_get_device_manager:
1314  * @display: a #GdkDisplay.
1315  *
1316  * Returns the #GdkDeviceManager associated to @display.
1317  *
1318  * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is
1319  *          owned by GDK and must not be freed or unreferenced.
1320  *
1321  * Since: 3.0
1322  **/
1323 GdkDeviceManager *
1324 gdk_display_get_device_manager (GdkDisplay *display)
1325 {
1326   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1327
1328   return display->device_manager;
1329 }
1330
1331 /**
1332  * gdk_display_get_name:
1333  * @display: a #GdkDisplay
1334  *
1335  * Gets the name of the display.
1336  *
1337  * Returns: a string representing the display name. This string is owned
1338  * by GDK and should not be modified or freed.
1339  *
1340  * Since: 2.2
1341  */
1342 G_CONST_RETURN gchar *
1343 gdk_display_get_name (GdkDisplay *display)
1344 {
1345   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1346
1347   return GDK_DISPLAY_GET_CLASS (display)->get_name (display);
1348 }
1349
1350 gchar *
1351 gdk_get_display (void)
1352 {
1353   return g_strdup (gdk_display_get_name (gdk_display_get_default ()));
1354 }
1355
1356 /**
1357  * gdk_display_get_n_screens:
1358  * @display: a #GdkDisplay
1359  *
1360  * Gets the number of screen managed by the @display.
1361  *
1362  * Returns: number of screens.
1363  *
1364  * Since: 2.2
1365  */
1366 gint
1367 gdk_display_get_n_screens (GdkDisplay *display)
1368 {
1369   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
1370
1371   return GDK_DISPLAY_GET_CLASS (display)->get_n_screens (display);
1372 }
1373
1374 /**
1375  * gdk_display_get_screen:
1376  * @display: a #GdkDisplay
1377  * @screen_num: the screen number
1378  *
1379  * Returns a screen object for one of the screens of the display.
1380  *
1381  * Returns: (transfer none): the #GdkScreen object
1382  *
1383  * Since: 2.2
1384  */
1385 GdkScreen *
1386 gdk_display_get_screen (GdkDisplay *display,
1387                         gint        screen_num)
1388 {
1389   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1390
1391   return GDK_DISPLAY_GET_CLASS (display)->get_screen (display, screen_num);
1392 }
1393
1394 /**
1395  * gdk_display_get_default_screen:
1396  * @display: a #GdkDisplay
1397  *
1398  * Get the default #GdkScreen for @display.
1399  *
1400  * Returns: (transfer none): the default #GdkScreen object for @display
1401  *
1402  * Since: 2.2
1403  */
1404 GdkScreen *
1405 gdk_display_get_default_screen (GdkDisplay *display)
1406 {
1407   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1408
1409   return GDK_DISPLAY_GET_CLASS (display)->get_default_screen (display);
1410 }
1411
1412 /**
1413  * gdk_display_beep:
1414  * @display: a #GdkDisplay
1415  *
1416  * Emits a short beep on @display
1417  *
1418  * Since: 2.2
1419  */
1420 void
1421 gdk_display_beep (GdkDisplay *display)
1422 {
1423   g_return_if_fail (GDK_IS_DISPLAY (display));
1424
1425   GDK_DISPLAY_GET_CLASS (display)->beep (display);
1426 }
1427
1428 /**
1429  * gdk_display_sync:
1430  * @display: a #GdkDisplay
1431  *
1432  * Flushes any requests queued for the windowing system and waits until all
1433  * requests have been handled. This is often used for making sure that the
1434  * display is synchronized with the current state of the program. Calling
1435  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
1436  * generated from earlier requests are handled before the error trap is
1437  * removed.
1438  *
1439  * This is most useful for X11. On windowing systems where requests are
1440  * handled synchronously, this function will do nothing.
1441  *
1442  * Since: 2.2
1443  */
1444 void
1445 gdk_display_sync (GdkDisplay *display)
1446 {
1447   g_return_if_fail (GDK_IS_DISPLAY (display));
1448
1449   GDK_DISPLAY_GET_CLASS (display)->sync (display);
1450 }
1451
1452 /**
1453  * gdk_display_flush:
1454  * @display: a #GdkDisplay
1455  *
1456  * Flushes any requests queued for the windowing system; this happens automatically
1457  * when the main loop blocks waiting for new events, but if your application
1458  * is drawing without returning control to the main loop, you may need
1459  * to call this function explicitely. A common case where this function
1460  * needs to be called is when an application is executing drawing commands
1461  * from a thread other than the thread where the main loop is running.
1462  *
1463  * This is most useful for X11. On windowing systems where requests are
1464  * handled synchronously, this function will do nothing.
1465  *
1466  * Since: 2.4
1467  */
1468 void
1469 gdk_display_flush (GdkDisplay *display)
1470 {
1471   g_return_if_fail (GDK_IS_DISPLAY (display));
1472
1473   GDK_DISPLAY_GET_CLASS (display)->flush (display);
1474 }
1475
1476 /**
1477  * gdk_display_get_default_group:
1478  * @display: a #GdkDisplay
1479  *
1480  * Returns the default group leader window for all toplevel windows
1481  * on @display. This window is implicitly created by GDK.
1482  * See gdk_window_set_group().
1483  *
1484  * Return value: (transfer none): The default group leader window
1485  * for @display
1486  *
1487  * Since: 2.4
1488  **/
1489 GdkWindow *
1490 gdk_display_get_default_group (GdkDisplay *display)
1491 {
1492   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1493
1494   return GDK_DISPLAY_GET_CLASS (display)->get_default_group (display);
1495 }
1496
1497 /**
1498  * gdk_display_supports_selection_notification:
1499  * @display: a #GdkDisplay
1500  *
1501  * Returns whether #GdkEventOwnerChange events will be
1502  * sent when the owner of a selection changes.
1503  *
1504  * Return value: whether #GdkEventOwnerChange events will
1505  *               be sent.
1506  *
1507  * Since: 2.6
1508  **/
1509 gboolean
1510 gdk_display_supports_selection_notification (GdkDisplay *display)
1511 {
1512   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1513
1514   return GDK_DISPLAY_GET_CLASS (display)->supports_selection_notification (display);
1515 }
1516
1517 /**
1518  * gdk_display_request_selection_notification:
1519  * @display: a #GdkDisplay
1520  * @selection: the #GdkAtom naming the selection for which
1521  *             ownership change notification is requested
1522  *
1523  * Request #GdkEventOwnerChange events for ownership changes
1524  * of the selection named by the given atom.
1525  *
1526  * Return value: whether #GdkEventOwnerChange events will
1527  *               be sent.
1528  *
1529  * Since: 2.6
1530  **/
1531 gboolean
1532 gdk_display_request_selection_notification (GdkDisplay *display,
1533                                             GdkAtom     selection)
1534
1535 {
1536   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1537
1538   return GDK_DISPLAY_GET_CLASS (display)->request_selection_notification (display, selection);
1539 }
1540
1541 /**
1542  * gdk_display_supports_clipboard_persistence
1543  * @display: a #GdkDisplay
1544  *
1545  * Returns whether the speicifed display supports clipboard
1546  * persistance; i.e. if it's possible to store the clipboard data after an
1547  * application has quit. On X11 this checks if a clipboard daemon is
1548  * running.
1549  *
1550  * Returns: %TRUE if the display supports clipboard persistance.
1551  *
1552  * Since: 2.6
1553  */
1554 gboolean
1555 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1556 {
1557   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1558
1559   return GDK_DISPLAY_GET_CLASS (display)->supports_clipboard_persistence (display);
1560 }
1561
1562 /**
1563  * gdk_display_store_clipboard
1564  * @display:          a #GdkDisplay
1565  * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1566  * @time_:            a timestamp
1567  * @targets:          (array length=n_targets): an array of targets
1568  *                    that should be saved, or %NULL
1569  *                    if all available targets should be saved.
1570  * @n_targets:        length of the @targets array
1571  *
1572  * Issues a request to the clipboard manager to store the
1573  * clipboard data. On X11, this is a special program that works
1574  * according to the freedesktop clipboard specification, available at
1575  * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1576  * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1577  *
1578  * Since: 2.6
1579  */
1580 void
1581 gdk_display_store_clipboard (GdkDisplay    *display,
1582                              GdkWindow     *clipboard_window,
1583                              guint32        time_,
1584                              const GdkAtom *targets,
1585                              gint           n_targets)
1586 {
1587   g_return_if_fail (GDK_IS_DISPLAY (display));
1588
1589   GDK_DISPLAY_GET_CLASS (display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
1590 }
1591
1592 /**
1593  * gdk_display_supports_shapes:
1594  * @display: a #GdkDisplay
1595  *
1596  * Returns %TRUE if gdk_window_shape_combine_mask() can
1597  * be used to create shaped windows on @display.
1598  *
1599  * Returns: %TRUE if shaped windows are supported
1600  *
1601  * Since: 2.10
1602  */
1603 gboolean
1604 gdk_display_supports_shapes (GdkDisplay *display)
1605 {
1606   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1607
1608   return GDK_DISPLAY_GET_CLASS (display)->supports_shapes (display);
1609 }
1610
1611 /**
1612  * gdk_display_supports_input_shapes:
1613  * @display: a #GdkDisplay
1614  *
1615  * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1616  * be used to modify the input shape of windows on @display.
1617  *
1618  * Returns: %TRUE if windows with modified input shape are supported
1619  *
1620  * Since: 2.10
1621  */
1622 gboolean
1623 gdk_display_supports_input_shapes (GdkDisplay *display)
1624 {
1625   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1626
1627   return GDK_DISPLAY_GET_CLASS (display)->supports_input_shapes (display);
1628 }
1629
1630 /**
1631  * gdk_display_supports_composite:
1632  * @display: a #GdkDisplay
1633  *
1634  * Returns %TRUE if gdk_window_set_composited() can be used
1635  * to redirect drawing on the window using compositing.
1636  *
1637  * Currently this only works on X11 with XComposite and
1638  * XDamage extensions available.
1639  *
1640  * Returns: %TRUE if windows may be composited.
1641  *
1642  * Since: 2.12
1643  */
1644 gboolean
1645 gdk_display_supports_composite (GdkDisplay *display)
1646 {
1647   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1648
1649   return GDK_DISPLAY_GET_CLASS (display)->supports_composite (display);
1650 }
1651
1652 /**
1653  * gdk_display_list_devices:
1654  * @display: a #GdkDisplay
1655  *
1656  * Returns the list of available input devices attached to @display.
1657  * The list is statically allocated and should not be freed.
1658  *
1659  * Return value: (transfer none) (element-type GdkDevice):
1660  *     a list of #GdkDevice
1661  *
1662  * Since: 2.2
1663  *
1664  * Deprecated: 3.0: Use gdk_device_manager_list_devices() instead.
1665  **/
1666 GList *
1667 gdk_display_list_devices (GdkDisplay *display)
1668 {
1669   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1670
1671   return GDK_DISPLAY_GET_CLASS (display)->list_devices (display);
1672 }
1673
1674 static GdkAppLaunchContext *
1675 gdk_display_real_get_app_launch_context (GdkDisplay *display)
1676 {
1677   GdkAppLaunchContext *ctx;
1678
1679   ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT,
1680                       "display", display,
1681                       NULL);
1682
1683   return ctx;
1684 }
1685
1686 /**
1687  * gdk_display_get_app_launch_context:
1688  * @display: a #GdkDisplay
1689  *
1690  * Returns a #GdkAppLaunchContext suitable for launching
1691  * applications on the given display.
1692  *
1693  * Returns: (transfer full): a new #GdkAppLaunchContext for @display.
1694  *     Free with g_object_unref() when done
1695  *
1696  * Since: 3.0
1697  */
1698 GdkAppLaunchContext *
1699 gdk_display_get_app_launch_context (GdkDisplay *display)
1700 {
1701   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1702
1703   return GDK_DISPLAY_GET_CLASS (display)->get_app_launch_context (display);
1704 }
1705
1706 /**
1707  * gdk_display_open:
1708  * @display_name: the name of the display to open
1709  *
1710  * Opens a display.
1711  *
1712  * Return value: (transfer none): a #GdkDisplay, or %NULL
1713  *     if the display could not be opened
1714  *
1715  * Since: 2.2
1716  */
1717 GdkDisplay *
1718 gdk_display_open (const gchar *display_name)
1719 {
1720   return gdk_display_manager_open_display (gdk_display_manager_get (),
1721                                            display_name);
1722 }
1723
1724 /**
1725  * gdk_display_has_pending:
1726  * @display: a #GdkDisplay
1727  *
1728  * Returns whether the display has events that are waiting
1729  * to be processed.
1730  *
1731  * Returns: %TRUE if there are events ready to be processed.
1732  *
1733  * Since: 3.0
1734  */
1735 gboolean
1736 gdk_display_has_pending (GdkDisplay *display)
1737 {
1738   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1739
1740   return GDK_DISPLAY_GET_CLASS (display)->has_pending (display);
1741 }
1742
1743 /**
1744  * gdk_display_supports_cursor_alpha:
1745  * @display: a #GdkDisplay
1746  *
1747  * Returns %TRUE if cursors can use an 8bit alpha channel
1748  * on @display. Otherwise, cursors are restricted to bilevel
1749  * alpha (i.e. a mask).
1750  *
1751  * Returns: whether cursors can have alpha channels.
1752  *
1753  * Since: 2.4
1754  */
1755 gboolean
1756 gdk_display_supports_cursor_alpha (GdkDisplay *display)
1757 {
1758   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1759
1760   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_alpha (display);
1761 }
1762
1763 /**
1764  * gdk_display_supports_cursor_color:
1765  * @display: a #GdkDisplay
1766  *
1767  * Returns %TRUE if multicolored cursors are supported
1768  * on @display. Otherwise, cursors have only a forground
1769  * and a background color.
1770  *
1771  * Returns: whether cursors can have multiple colors.
1772  *
1773  * Since: 2.4
1774  */
1775 gboolean
1776 gdk_display_supports_cursor_color (GdkDisplay *display)
1777 {
1778   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1779
1780   return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_color (display);
1781 }
1782
1783 /**
1784  * gdk_display_get_default_cursor_size:
1785  * @display: a #GdkDisplay
1786  *
1787  * Returns the default size to use for cursors on @display.
1788  *
1789  * Returns: the default cursor size.
1790  *
1791  * Since: 2.4
1792  */
1793 guint
1794 gdk_display_get_default_cursor_size (GdkDisplay *display)
1795 {
1796   guint width, height;
1797
1798   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1799
1800   GDK_DISPLAY_GET_CLASS (display)->get_default_cursor_size (display,
1801                                                             &width,
1802                                                             &height);
1803
1804   return MIN (width, height);
1805 }
1806
1807 /**
1808  * gdk_display_get_maximal_cursor_size:
1809  * @display: a #GdkDisplay
1810  * @width: (out): the return location for the maximal cursor width
1811  * @height: (out): the return location for the maximal cursor height
1812  *
1813  * Gets the maximal size to use for cursors on @display.
1814  *
1815  * Since: 2.4
1816  */
1817 void
1818 gdk_display_get_maximal_cursor_size (GdkDisplay *display,
1819                                      guint       *width,
1820                                      guint       *height)
1821 {
1822   g_return_if_fail (GDK_IS_DISPLAY (display));
1823
1824   GDK_DISPLAY_GET_CLASS (display)->get_maximal_cursor_size (display,
1825                                                             width,
1826                                                             height);
1827 }
1828
1829 /**
1830  * gdk_display_warp_pointer:
1831  * @display: a #GdkDisplay
1832  * @screen: the screen of @display to warp the pointer to
1833  * @x: the x coordinate of the destination
1834  * @y: the y coordinate of the destination
1835  *
1836  * Warps the pointer of @display to the point @x,@y on
1837  * the screen @screen, unless the pointer is confined
1838  * to a window by a grab, in which case it will be moved
1839  * as far as allowed by the grab. Warping the pointer
1840  * creates events as if the user had moved the mouse
1841  * instantaneously to the destination.
1842  *
1843  * Note that the pointer should normally be under the
1844  * control of the user. This function was added to cover
1845  * some rare use cases like keyboard navigation support
1846  * for the color picker in the #GtkColorSelectionDialog.
1847  *
1848  * Since: 2.8
1849  *
1850  * Deprecated: 3.0: Use gdk_device_warp() instead.
1851  */
1852 void
1853 gdk_display_warp_pointer (GdkDisplay *display,
1854                           GdkScreen  *screen,
1855                           gint        x,
1856                           gint        y)
1857 {
1858   g_return_if_fail (GDK_IS_DISPLAY (display));
1859
1860   gdk_device_warp (display->core_pointer,
1861                    screen,
1862                    x, y);
1863 }
1864
1865 gulong
1866 _gdk_display_get_next_serial (GdkDisplay *display)
1867 {
1868   return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display);
1869 }
1870
1871
1872 /**
1873  * gdk_notify_startup_complete:
1874  *
1875  * Indicates to the GUI environment that the application has finished
1876  * loading. If the applications opens windows, this function is
1877  * normally called after opening the application's initial set of
1878  * windows.
1879  *
1880  * GTK+ will call this function automatically after opening the first
1881  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
1882  * to disable that feature.
1883  *
1884  * Since: 2.2
1885  **/
1886 void
1887 gdk_notify_startup_complete (void)
1888 {
1889   gdk_notify_startup_complete_with_id (NULL);
1890 }
1891
1892 /**
1893  * gdk_notify_startup_complete_with_id:
1894  * @startup_id: a startup-notification identifier, for which
1895  *     notification process should be completed
1896  *
1897  * Indicates to the GUI environment that the application has
1898  * finished loading, using a given identifier.
1899  *
1900  * GTK+ will call this function automatically for #GtkWindow
1901  * with custom startup-notification identifier unless
1902  * gtk_window_set_auto_startup_notification() is called to
1903  * disable that feature.
1904  *
1905  * Since: 2.12
1906  */
1907 void
1908 gdk_notify_startup_complete_with_id (const gchar* startup_id)
1909 {
1910   GdkDisplay *display;
1911
1912   display = gdk_display_get_default ();
1913   if (display)
1914     gdk_display_notify_startup_complete (display, startup_id);
1915 }
1916
1917 /**
1918  * gdk_display_notify_startup_complete:
1919  * @display: a #GdkDisplay
1920  * @startup_id: a startup-notification identifier, for which
1921  *     notification process should be completed
1922  *
1923  * Indicates to the GUI environment that the application has
1924  * finished loading, using a given identifier.
1925  *
1926  * GTK+ will call this function automatically for #GtkWindow
1927  * with custom startup-notification identifier unless
1928  * gtk_window_set_auto_startup_notification() is called to
1929  * disable that feature.
1930  *
1931  * Since: 3.0
1932  */
1933 void
1934 gdk_display_notify_startup_complete (GdkDisplay  *display,
1935                                      const gchar *startup_id)
1936 {
1937   g_return_if_fail (GDK_IS_DISPLAY (display));
1938
1939   GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
1940 }
1941
1942 void
1943 _gdk_display_event_data_copy (GdkDisplay     *display,
1944                               const GdkEvent *event,
1945                               GdkEvent       *new_event)
1946 {
1947   GDK_DISPLAY_GET_CLASS (display)->event_data_copy (display, event, new_event);
1948 }
1949
1950 void
1951 _gdk_display_event_data_free (GdkDisplay *display,
1952                               GdkEvent   *event)
1953 {
1954   GDK_DISPLAY_GET_CLASS (display)->event_data_free (display, event);
1955 }
1956
1957 void
1958 _gdk_display_create_window_impl (GdkDisplay       *display,
1959                                  GdkWindow        *window,
1960                                  GdkWindow        *real_parent,
1961                                  GdkScreen        *screen,
1962                                  GdkEventMask      event_mask,
1963                                  GdkWindowAttr    *attributes,
1964                                  gint              attributes_mask)
1965 {
1966   GDK_DISPLAY_GET_CLASS (display)->create_window_impl (display,
1967                                                        window,
1968                                                        real_parent,
1969                                                        screen,
1970                                                        event_mask,
1971                                                        attributes,
1972                                                        attributes_mask);
1973 }
1974
1975 GdkWindow *
1976 _gdk_display_create_window (GdkDisplay *display)
1977 {
1978   return g_object_new (GDK_DISPLAY_GET_CLASS (display)->window_type, NULL);
1979 }
1980
1981 /**
1982  * gdk_keymap_get_for_display:
1983  * @display: the #GdkDisplay.
1984  *
1985  * Returns the #GdkKeymap attached to @display.
1986  *
1987  * Return value: (transfer none): the #GdkKeymap attached to @display.
1988  *
1989  * Since: 2.2
1990  */
1991 GdkKeymap*
1992 gdk_keymap_get_for_display (GdkDisplay *display)
1993 {
1994   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1995
1996   return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
1997 }
1998
1999 typedef struct _GdkGlobalErrorTrap  GdkGlobalErrorTrap;
2000
2001 struct _GdkGlobalErrorTrap
2002 {
2003   GSList *displays;
2004 };
2005
2006 static GQueue gdk_error_traps = G_QUEUE_INIT;
2007
2008 /**
2009  * gdk_error_trap_push:
2010  *
2011  * This function allows X errors to be trapped instead of the normal
2012  * behavior of exiting the application. It should only be used if it
2013  * is not possible to avoid the X error in any other way. Errors are
2014  * ignored on all #GdkDisplay currently known to the
2015  * #GdkDisplayManager. If you don't care which error happens and just
2016  * want to ignore everything, pop with gdk_error_trap_pop_ignored().
2017  * If you need the error code, use gdk_error_trap_pop() which may have
2018  * to block and wait for the error to arrive from the X server.
2019  *
2020  * This API exists on all platforms but only does anything on X.
2021  *
2022  * You can use gdk_x11_display_error_trap_push() to ignore errors
2023  * on only a single display.
2024  *
2025 * <example>
2026  * <title>Trapping an X error</title>
2027  * <programlisting>
2028  * gdk_error_trap_push (<!-- -->);
2029  *
2030  *  // ... Call the X function which may cause an error here ...
2031  *
2032  *
2033  * if (gdk_error_trap_pop (<!-- -->))
2034  *  {
2035  *    // ... Handle the error here ...
2036  *  }
2037  * </programlisting>
2038  * </example>
2039  */
2040 void
2041 gdk_error_trap_push (void)
2042 {
2043   GdkDisplayManager *manager;
2044   GdkDisplayClass *class;
2045   GdkGlobalErrorTrap *trap;
2046   GSList *l;
2047
2048   manager = gdk_display_manager_get ();
2049   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2050
2051   if (class->push_error_trap == NULL)
2052     return;
2053
2054   trap = g_slice_new (GdkGlobalErrorTrap);
2055   trap->displays = gdk_display_manager_list_displays (manager);
2056
2057   g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL);
2058   for (l = trap->displays; l != NULL; l = l->next)
2059     {
2060       class->push_error_trap (l->data);
2061     }
2062
2063   g_queue_push_head (&gdk_error_traps, trap);
2064 }
2065
2066 static gint
2067 gdk_error_trap_pop_internal (gboolean need_code)
2068 {
2069   GdkDisplayManager *manager;
2070   GdkDisplayClass *class;
2071   GdkGlobalErrorTrap *trap;
2072   gint result;
2073   GSList *l;
2074
2075   manager = gdk_display_manager_get ();
2076   class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager));
2077
2078   if (class->pop_error_trap == NULL)
2079     return 0;
2080
2081   trap = g_queue_pop_head (&gdk_error_traps);
2082
2083   g_return_val_if_fail (trap != NULL, 0);
2084
2085   result = 0;
2086   for (l = trap->displays; l != NULL; l = l->next)
2087     {
2088       gint code = 0;
2089
2090       code = class->pop_error_trap (l->data, !need_code);
2091
2092       /* we use the error on the last display listed, why not. */
2093       if (code != 0)
2094         result = code;
2095     }
2096
2097   g_slist_free_full (trap->displays, g_object_unref);
2098   g_slice_free (GdkGlobalErrorTrap, trap);
2099
2100   return result;
2101 }
2102
2103 /**
2104  * gdk_error_trap_pop_ignored:
2105  *
2106  * Removes an error trap pushed with gdk_error_trap_push(), but
2107  * without bothering to wait and see whether an error occurred.  If an
2108  * error arrives later asynchronously that was triggered while the
2109  * trap was pushed, that error will be ignored.
2110  *
2111  * Since: 3.0
2112  */
2113 void
2114 gdk_error_trap_pop_ignored (void)
2115 {
2116   gdk_error_trap_pop_internal (FALSE);
2117 }
2118
2119 /**
2120  * gdk_error_trap_pop:
2121  *
2122  * Removes an error trap pushed with gdk_error_trap_push().
2123  * May block until an error has been definitively received
2124  * or not received from the X server. gdk_error_trap_pop_ignored()
2125  * is preferred if you don't need to know whether an error
2126  * occurred, because it never has to block. If you don't
2127  * need the return value of gdk_error_trap_pop(), use
2128  * gdk_error_trap_pop_ignored().
2129  *
2130  * Prior to GDK 3.0, this function would not automatically
2131  * sync for you, so you had to gdk_flush() if your last
2132  * call to Xlib was not a blocking round trip.
2133  *
2134  * Return value: X error code or 0 on success
2135  */
2136 gint
2137 gdk_error_trap_pop (void)
2138 {
2139   return gdk_error_trap_pop_internal (TRUE);
2140 }