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