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