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