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