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