]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
gdk: Do final copy with OPERATOR_SOURCE in end_implicit_paint
[~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 #include <math.h>
26 #include <glib.h>
27 #include "gdk.h"                /* gdk_event_send_client_message() */
28 #include "gdkdisplay.h"
29 #include "gdkwindowimpl.h"
30 #include "gdkinternals.h"
31 #include "gdkmarshalers.h"
32 #include "gdkscreen.h"
33
34
35 enum {
36   OPENED,
37   CLOSED,
38   LAST_SIGNAL
39 };
40
41 static void gdk_display_dispose     (GObject         *object);
42 static void gdk_display_finalize    (GObject         *object);
43
44 static void        multihead_get_device_state           (GdkDisplay       *display,
45                                                          GdkDevice        *device,
46                                                          GdkScreen       **screen,
47                                                          gint             *x,
48                                                          gint             *y,
49                                                          GdkModifierType  *mask);
50 static GdkWindow * multihead_window_get_device_position (GdkDisplay       *display,
51                                                          GdkDevice        *device,
52                                                          GdkWindow        *window,
53                                                          gint             *x,
54                                                          gint             *y,
55                                                          GdkModifierType  *mask);
56 static GdkWindow * multihead_window_at_device_position  (GdkDisplay       *display,
57                                                          GdkDevice        *device,
58                                                          gint             *win_x,
59                                                          gint             *win_y);
60
61 static void        multihead_default_get_pointer        (GdkDisplay       *display,
62                                                          GdkScreen       **screen,
63                                                          gint             *x,
64                                                          gint             *y,
65                                                          GdkModifierType  *mask);
66 static GdkWindow * multihead_default_window_get_pointer (GdkDisplay      *display,
67                                                          GdkWindow       *window,
68                                                          gint            *x,
69                                                          gint            *y,
70                                                          GdkModifierType *mask);
71 static GdkWindow * multihead_default_window_at_pointer  (GdkDisplay      *display,
72                                                          gint            *win_x,
73                                                          gint            *win_y);
74
75
76 static void       singlehead_get_pointer (GdkDisplay       *display,
77                                           GdkScreen       **screen,
78                                           gint             *x,
79                                           gint             *y,
80                                           GdkModifierType  *mask);
81 static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
82                                                  GdkWindow        *window,
83                                                  gint             *x,
84                                                  gint             *y,
85                                                  GdkModifierType  *mask);
86 static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
87                                                  gint             *win_x,
88                                                  gint             *win_y);
89
90 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
91                                                          gint            *x,
92                                                          gint            *y,
93                                                          GdkModifierType *mask);
94 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
95                                                          gint            *win_x,
96                                                          gint            *win_y);
97 static GdkWindow *gdk_window_real_window_get_device_position     (GdkDisplay       *display,
98                                                                   GdkDevice        *device,
99                                                                   GdkWindow        *window,
100                                                                   gint             *x,
101                                                                   gint             *y,
102                                                                   GdkModifierType  *mask);
103 static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay       *display,
104                                                                   GdkDevice        *device,
105                                                                   gint             *win_x,
106                                                                   gint             *win_y);
107
108 static guint signals[LAST_SIGNAL] = { 0 };
109
110 static char *gdk_sm_client_id;
111
112 static const GdkDisplayDeviceHooks default_device_hooks = {
113   _gdk_windowing_get_device_state,
114   gdk_window_real_window_get_device_position,
115   gdk_display_real_get_window_at_device_position
116 };
117
118 static const GdkDisplayDeviceHooks multihead_pointer_hooks = {
119   multihead_get_device_state,
120   multihead_window_get_device_position,
121   multihead_window_at_device_position
122 };
123
124 static const GdkDisplayPointerHooks multihead_default_pointer_hooks = {
125   multihead_default_get_pointer,
126   multihead_default_window_get_pointer,
127   multihead_default_window_at_pointer
128 };
129
130 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
131   singlehead_get_pointer,
132   singlehead_window_get_pointer,
133   singlehead_window_at_pointer
134 };
135
136 static const GdkPointerHooks singlehead_default_pointer_hooks = {
137   singlehead_default_window_get_pointer,
138   singlehead_default_window_at_pointer
139 };
140
141 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
142 static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
143
144 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
145
146 static void
147 gdk_display_class_init (GdkDisplayClass *class)
148 {
149   GObjectClass *object_class = G_OBJECT_CLASS (class);
150
151   object_class->finalize = gdk_display_finalize;
152   object_class->dispose = gdk_display_dispose;
153
154   /**
155    * GdkDisplay::opened:
156    * @display: the object on which the signal is emitted
157    *
158    * The ::opened signal is emitted when the connection to the windowing
159    * system for @display is opened.
160    */
161   signals[OPENED] =
162     g_signal_new (g_intern_static_string ("opened"),
163                   G_OBJECT_CLASS_TYPE (object_class),
164                   G_SIGNAL_RUN_LAST,
165                   0, NULL, NULL,
166                   g_cclosure_marshal_VOID__VOID,
167                   G_TYPE_NONE, 0);
168
169   /**
170    * GdkDisplay::closed:
171    * @display: the object on which the signal is emitted
172    * @is_error: %TRUE if the display was closed due to an error
173    *
174    * The ::closed signal is emitted when the connection to the windowing
175    * system for @display is closed.
176    *
177    * Since: 2.2
178    */   
179   signals[CLOSED] =
180     g_signal_new (g_intern_static_string ("closed"),
181                   G_OBJECT_CLASS_TYPE (object_class),
182                   G_SIGNAL_RUN_LAST,
183                   G_STRUCT_OFFSET (GdkDisplayClass, closed),
184                   NULL, NULL,
185                   _gdk_marshal_VOID__BOOLEAN,
186                   G_TYPE_NONE,
187                   1,
188                   G_TYPE_BOOLEAN);
189 }
190
191 static void
192 free_pointer_info (GdkPointerWindowInfo *info)
193 {
194   g_object_unref (info->toplevel_under_pointer);
195   g_slice_free (GdkPointerWindowInfo, info);
196 }
197
198 static void
199 free_device_grab (GdkDeviceGrabInfo *info)
200 {
201   g_object_unref (info->window);
202   g_object_unref (info->native_window);
203   g_free (info);
204 }
205
206 static gboolean
207 free_device_grabs_foreach (gpointer key,
208                            gpointer value,
209                            gpointer user_data)
210 {
211   GList *list = value;
212
213   g_list_foreach (list, (GFunc) free_device_grab, NULL);
214   g_list_free (list);
215
216   return TRUE;
217 }
218
219 static void
220 device_removed_cb (GdkDeviceManager *device_manager,
221                    GdkDevice        *device,
222                    GdkDisplay       *display)
223 {
224   g_hash_table_remove (display->multiple_click_info, device);
225   g_hash_table_remove (display->device_grabs, device);
226   g_hash_table_remove (display->pointers_info, device);
227
228   /* FIXME: change core pointer and remove from device list */
229 }
230
231 static void
232 gdk_display_opened (GdkDisplay *display)
233 {
234   GdkDeviceManager *device_manager;
235
236   device_manager = gdk_display_get_device_manager (display);
237
238   g_signal_connect (device_manager, "device-removed",
239                     G_CALLBACK (device_removed_cb), display);
240 }
241
242 static void
243 gdk_display_init (GdkDisplay *display)
244 {
245   _gdk_displays = g_slist_prepend (_gdk_displays, display);
246
247   display->double_click_time = 250;
248   display->double_click_distance = 5;
249
250   display->device_hooks = &default_device_hooks;
251
252   display->device_grabs = g_hash_table_new (NULL, NULL);
253   display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
254                                                      (GDestroyNotify) g_free);
255
256   display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
257                                                   (GDestroyNotify) free_pointer_info);
258
259   display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
260                                                         (GDestroyNotify) g_free);
261
262   g_signal_connect (display, "opened",
263                     G_CALLBACK (gdk_display_opened), NULL);
264 }
265
266 static void
267 gdk_display_dispose (GObject *object)
268 {
269   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
270   GdkDeviceManager *device_manager;
271
272   device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
273
274   g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
275   g_list_free (display->queued_events);
276   display->queued_events = NULL;
277   display->queued_tail = NULL;
278
279   _gdk_displays = g_slist_remove (_gdk_displays, object);
280
281   if (gdk_display_get_default() == display)
282     {
283       if (_gdk_displays)
284         gdk_display_manager_set_default_display (gdk_display_manager_get(),
285                                                  _gdk_displays->data);
286       else
287         gdk_display_manager_set_default_display (gdk_display_manager_get(),
288                                                  NULL);
289     }
290
291   if (device_manager)
292     g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, object);
293
294   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
295 }
296
297 static void
298 gdk_display_finalize (GObject *object)
299 {
300   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
301
302   g_hash_table_foreach_remove (display->device_grabs,
303                                free_device_grabs_foreach,
304                                NULL);
305   g_hash_table_destroy (display->device_grabs);
306
307   g_hash_table_destroy (display->pointers_info);
308   g_hash_table_destroy (display->multiple_click_info);
309
310   if (display->device_manager)
311     g_object_unref (display->device_manager);
312
313   G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
314 }
315
316 /**
317  * gdk_display_close:
318  * @display: a #GdkDisplay
319  *
320  * Closes the connection to the windowing system for the given display,
321  * and cleans up associated resources.
322  *
323  * Since: 2.2
324  */
325 void
326 gdk_display_close (GdkDisplay *display)
327 {
328   g_return_if_fail (GDK_IS_DISPLAY (display));
329
330   if (!display->closed)
331     {
332       display->closed = TRUE;
333       
334       g_signal_emit (display, signals[CLOSED], 0, FALSE);
335       g_object_run_dispose (G_OBJECT (display));
336       
337       g_object_unref (display);
338     }
339 }
340
341 /**
342  * gdk_display_is_closed:
343  * @display: a #GdkDisplay
344  *
345  * Returns %TRUE if the display is closed.
346  *
347  * Since: 2.22
348  */
349 gboolean
350 gdk_display_is_closed  (GdkDisplay  *display)
351 {
352   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
353
354   return display->closed;
355 }
356
357 /**
358  * gdk_display_get_event:
359  * @display: a #GdkDisplay
360  * 
361  * Gets the next #GdkEvent to be processed for @display, fetching events from the
362  * windowing system if necessary.
363  * 
364  * Return value: the next #GdkEvent to be processed, or %NULL if no events
365  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
366  *
367  * Since: 2.2
368  **/
369 GdkEvent*
370 gdk_display_get_event (GdkDisplay *display)
371 {
372   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
373   
374   _gdk_events_queue (display);
375   return _gdk_event_unqueue (display);
376 }
377
378 /**
379  * gdk_display_peek_event:
380  * @display: a #GdkDisplay 
381  * 
382  * Gets a copy of the first #GdkEvent in the @display's event queue, without
383  * removing the event from the queue.  (Note that this function will
384  * not get more events from the windowing system.  It only checks the events
385  * that have already been moved to the GDK event queue.)
386  * 
387  * Return value: a copy of the first #GdkEvent on the event queue, or %NULL 
388  * if no events are in the queue. The returned #GdkEvent should be freed with
389  * gdk_event_free().
390  *
391  * Since: 2.2
392  **/
393 GdkEvent*
394 gdk_display_peek_event (GdkDisplay *display)
395 {
396   GList *tmp_list;
397
398   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
399
400   tmp_list = _gdk_event_queue_find_first (display);
401   
402   if (tmp_list)
403     return gdk_event_copy (tmp_list->data);
404   else
405     return NULL;
406 }
407
408 /**
409  * gdk_display_put_event:
410  * @display: a #GdkDisplay
411  * @event: a #GdkEvent.
412  *
413  * Appends a copy of the given event onto the front of the event
414  * queue for @display.
415  *
416  * Since: 2.2
417  **/
418 void
419 gdk_display_put_event (GdkDisplay     *display,
420                        const GdkEvent *event)
421 {
422   g_return_if_fail (GDK_IS_DISPLAY (display));
423   g_return_if_fail (event != NULL);
424
425   _gdk_event_queue_append (display, gdk_event_copy (event));
426   /* If the main loop is blocking in a different thread, wake it up */
427   g_main_context_wakeup (NULL); 
428 }
429
430 /**
431  * gdk_display_pointer_ungrab:
432  * @display: a #GdkDisplay.
433  * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
434  *
435  * Release any pointer grab.
436  *
437  * Since: 2.2
438  *
439  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
440  *             instead.
441  */
442 void
443 gdk_display_pointer_ungrab (GdkDisplay *display,
444                             guint32     time_)
445 {
446   GdkDeviceManager *device_manager;
447   GList *devices, *dev;
448   GdkDevice *device;
449
450   g_return_if_fail (GDK_IS_DISPLAY (display));
451
452   device_manager = gdk_display_get_device_manager (display);
453   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
454
455   /* FIXME: Should this be generic to all backends? */
456   /* FIXME: What happens with extended devices? */
457   for (dev = devices; dev; dev = dev->next)
458     {
459       device = dev->data;
460
461       if (device->source != GDK_SOURCE_MOUSE)
462         continue;
463
464       gdk_device_ungrab (device, time_);
465     }
466
467   g_list_free (devices);
468 }
469
470 /**
471  * gdk_pointer_ungrab:
472  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
473  *  timestamp is available.
474  *
475  * Ungrabs the pointer on the default display, if it is grabbed by this 
476  * application.
477  *
478  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
479  *             instead.
480  **/
481 void
482 gdk_pointer_ungrab (guint32 time)
483 {
484   gdk_display_pointer_ungrab (gdk_display_get_default (), time);
485 }
486
487 /**
488  * gdk_pointer_is_grabbed:
489  * 
490  * Returns %TRUE if the pointer on the default display is currently 
491  * grabbed by this application.
492  *
493  * Note that this does not take the inmplicit pointer grab on button
494  * presses into account.
495  *
496  * Return value: %TRUE if the pointer is currently grabbed by this application.
497  *
498  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
499  **/
500 gboolean
501 gdk_pointer_is_grabbed (void)
502 {
503   return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
504 }
505
506 /**
507  * gdk_display_keyboard_ungrab:
508  * @display: a #GdkDisplay.
509  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
510  *
511  * Release any keyboard grab
512  *
513  * Since: 2.2
514  *
515  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
516  *             instead.
517  */
518 void
519 gdk_display_keyboard_ungrab (GdkDisplay *display,
520                              guint32     time)
521 {
522   GdkDeviceManager *device_manager;
523   GList *devices, *dev;
524   GdkDevice *device;
525
526   g_return_if_fail (GDK_IS_DISPLAY (display));
527
528   device_manager = gdk_display_get_device_manager (display);
529   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
530
531   /* FIXME: Should this be generic to all backends? */
532   /* FIXME: What happens with extended devices? */
533   for (dev = devices; dev; dev = dev->next)
534     {
535       device = dev->data;
536
537       if (device->source != GDK_SOURCE_KEYBOARD)
538         continue;
539
540       gdk_device_ungrab (device, time);
541     }
542
543   g_list_free (devices);
544 }
545
546 /**
547  * gdk_keyboard_ungrab:
548  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
549  *        timestamp is available.
550  * 
551  * Ungrabs the keyboard on the default display, if it is grabbed by this 
552  * application.
553  *
554  * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
555  *             instead.
556  **/
557 void
558 gdk_keyboard_ungrab (guint32 time)
559 {
560   gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
561 }
562
563 /**
564  * gdk_beep:
565  * 
566  * Emits a short beep on the default display.
567  **/
568 void
569 gdk_beep (void)
570 {
571   gdk_display_beep (gdk_display_get_default ());
572 }
573
574 /**
575  * gdk_event_send_client_message:
576  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
577  * @winid:  the window to send the X ClientMessage event to.
578  * 
579  * Sends an X ClientMessage event to a given window (which must be
580  * on the default #GdkDisplay.)
581  * This could be used for communicating between different applications,
582  * though the amount of data is limited to 20 bytes.
583  * 
584  * Return value: non-zero on success.
585  **/
586 gboolean
587 gdk_event_send_client_message (GdkEvent        *event,
588                                GdkNativeWindow  winid)
589 {
590   g_return_val_if_fail (event != NULL, FALSE);
591
592   return gdk_event_send_client_message_for_display (gdk_display_get_default (),
593                                                     event, winid);
594 }
595
596 /**
597  * gdk_event_send_clientmessage_toall:
598  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
599  *
600  * Sends an X ClientMessage event to all toplevel windows on the default
601  * #GdkScreen.
602  *
603  * Toplevel windows are determined by checking for the WM_STATE property, as
604  * described in the Inter-Client Communication Conventions Manual (ICCCM).
605  * If no windows are found with the WM_STATE property set, the message is sent
606  * to all children of the root window.
607  **/
608 void
609 gdk_event_send_clientmessage_toall (GdkEvent *event)
610 {
611   g_return_if_fail (event != NULL);
612
613   gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
614 }
615
616 /**
617  * gdk_device_get_core_pointer:
618  * 
619  * Returns the core pointer device for the default display.
620  * 
621  * Return value: the core pointer device; this is owned by the
622  *   display and should not be freed.
623  *
624  * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
625  *             gdk_event_get_device() if a #GdkEvent with pointer device
626  *             information is available.
627  **/
628 GdkDevice *
629 gdk_device_get_core_pointer (void)
630 {
631   return gdk_display_get_core_pointer (gdk_display_get_default ());
632 }
633
634 /**
635  * gdk_display_get_core_pointer:
636  * @display: a #GdkDisplay
637  * 
638  * Returns the core pointer device for the given display
639  * 
640  * Return value: the core pointer device; this is owned by the
641  *   display and should not be freed.
642  *
643  * Since: 2.2
644  *
645  * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
646  *             gdk_event_get_device() if a #GdkEvent with device
647  *             information is available.
648  **/
649 GdkDevice *
650 gdk_display_get_core_pointer (GdkDisplay *display)
651 {
652   return display->core_pointer;
653 }
654
655 /**
656  * gdk_set_sm_client_id:
657  * @sm_client_id: the client id assigned by the session manager when the
658  *    connection was opened, or %NULL to remove the property.
659  * 
660  * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
661  * the window manager can save the application's state using the X11R6 ICCCM
662  * session management protocol.
663  *
664  * See the X Session Management Library documentation for more information on
665  * session management and the Inter-Client Communication Conventions Manual
666  * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property. 
667  * (Both documents are part of the X Window System distribution.)
668  **/
669 void
670 gdk_set_sm_client_id (const gchar* sm_client_id)
671 {
672   GSList *displays, *tmp_list;
673   
674   g_free (gdk_sm_client_id);
675   gdk_sm_client_id = g_strdup (sm_client_id);
676
677   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
678   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
679     _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
680
681   g_slist_free (displays);
682 }
683
684 /**
685  * _gdk_get_sm_client_id:
686  * 
687  * Gets the client ID set with gdk_set_sm_client_id(), if any.
688  * 
689  * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
690  *               has never been called.
691  **/
692 const char *
693 _gdk_get_sm_client_id (void)
694 {
695   return gdk_sm_client_id;
696 }
697
698 void
699 _gdk_display_enable_motion_hints (GdkDisplay *display,
700                                   GdkDevice  *device)
701 {
702   gulong *device_serial, serial;
703
704   device_serial = g_hash_table_lookup (display->motion_hint_info, device);
705
706   if (!device_serial)
707     {
708       device_serial = g_new0 (gulong, 1);
709       *device_serial = G_MAXULONG;
710       g_hash_table_insert (display->motion_hint_info, device, device_serial);
711     }
712
713   if (*device_serial != 0)
714     {
715       serial = _gdk_windowing_window_get_next_serial (display);
716       /* We might not actually generate the next request, so
717          make sure this triggers always, this may cause it to
718          trigger slightly too early, but this is just a hint
719          anyway. */
720       if (serial > 0)
721         serial--;
722       if (serial < *device_serial)
723         *device_serial = serial;
724     }
725 }
726
727 /**
728  * gdk_display_get_device_state:
729  * @display: a #GdkDisplay.
730  * @device: device to query status to.
731  * @screen: location to store the #GdkScreen the @device is on, or %NULL.
732  * @x: location to store root window X coordinate of @device, or %NULL.
733  * @y: location to store root window Y coordinate of @device, or %NULL.
734  * @mask: location to store current modifier mask for @device, or %NULL.
735  *
736  * Gets the current location and state of @device for a given display.
737  *
738  * Since: 3.0
739  **/
740 void
741 gdk_display_get_device_state (GdkDisplay       *display,
742                               GdkDevice        *device,
743                               GdkScreen       **screen,
744                               gint             *x,
745                               gint             *y,
746                               GdkModifierType  *mask)
747 {
748   GdkScreen *tmp_screen;
749   gint tmp_x, tmp_y;
750   GdkModifierType tmp_mask;
751
752   g_return_if_fail (GDK_IS_DISPLAY (display));
753   g_return_if_fail (GDK_IS_DEVICE (device));
754
755   display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
756
757   if (screen)
758     *screen = tmp_screen;
759   if (x)
760     *x = tmp_x;
761   if (y)
762     *y = tmp_y;
763   if (mask)
764     *mask = tmp_mask;
765 }
766
767 /**
768  * gdk_display_get_window_at_device_position:
769  * @display: a #GdkDisplay.
770  * @device: #GdkDevice to query info to.
771  * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
772  * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
773  *
774  * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
775  * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
776  *
777  * Returns: the #GdkWindow under the device position, or %NULL.
778  *
779  * Since: 3.0
780  **/
781 GdkWindow *
782 gdk_display_get_window_at_device_position (GdkDisplay *display,
783                                            GdkDevice  *device,
784                                            gint       *win_x,
785                                            gint       *win_y)
786 {
787   gint tmp_x, tmp_y;
788   GdkWindow *window;
789
790   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
791   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
792
793   window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
794
795   if (win_x)
796     *win_x = tmp_x;
797   if (win_y)
798     *win_y = tmp_y;
799
800   return window;
801 }
802
803 /**
804  * gdk_display_set_device_hooks:
805  * @display: a #GdkDisplay.
806  * @new_hooks: a table of pointers to functions for getting quantities related to all
807  *             devices position, or %NULL to restore the default table.
808  *
809  * This function allows for hooking into the operation of getting the current location of any
810  * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
811  * an event recorder. Applications should never have any reason to use this facility.
812  *
813  * Returns: The previous device hook table.
814  *
815  * Since: 3.0
816  **/
817 GdkDisplayDeviceHooks *
818 gdk_display_set_device_hooks (GdkDisplay                  *display,
819                               const GdkDisplayDeviceHooks *new_hooks)
820 {
821   const GdkDisplayDeviceHooks *result;
822
823   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
824   result = display->device_hooks;
825
826   if (new_hooks)
827     display->device_hooks = new_hooks;
828   else
829     display->device_hooks = &default_device_hooks;
830
831   return (GdkDisplayDeviceHooks *) result;
832 }
833
834 /**
835  * gdk_display_get_pointer:
836  * @display: a #GdkDisplay
837  * @screen: (allow-none): location to store the screen that the
838  *          cursor is on, or %NULL.
839  * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
840  * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
841  * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
842  *
843  * Gets the current location of the pointer and the current modifier
844  * mask for a given display.
845  *
846  * Since: 2.2
847  *
848  * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
849  **/
850 void
851 gdk_display_get_pointer (GdkDisplay      *display,
852                          GdkScreen      **screen,
853                          gint            *x,
854                          gint            *y,
855                          GdkModifierType *mask)
856 {
857   g_return_if_fail (GDK_IS_DISPLAY (display));
858
859   gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
860 }
861
862 static GdkWindow *
863 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
864                                                 GdkDevice  *device,
865                                                 gint       *win_x,
866                                                 gint       *win_y)
867 {
868   GdkWindow *window;
869   gint x, y;
870
871   window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
872
873   /* This might need corrections, as the native window returned
874      may contain client side children */
875   if (window)
876     {
877       double xx, yy;
878
879       window = _gdk_window_find_descendant_at (window,
880                                                x, y,
881                                                &xx, &yy);
882       x = floor (xx + 0.5);
883       y = floor (yy + 0.5);
884     }
885
886   *win_x = x;
887   *win_y = y;
888
889   return window;
890 }
891
892 static GdkWindow *
893 gdk_window_real_window_get_device_position (GdkDisplay       *display,
894                                             GdkDevice        *device,
895                                             GdkWindow        *window,
896                                             gint             *x,
897                                             gint             *y,
898                                             GdkModifierType  *mask)
899 {
900   GdkWindowObject *private;
901   gint tmpx, tmpy;
902   GdkModifierType tmp_mask;
903   gboolean normal_child;
904
905   private = (GdkWindowObject *) window;
906
907   normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
908                                                                               device,
909                                                                               &tmpx, &tmpy,
910                                                                               &tmp_mask);
911   /* We got the coords on the impl, convert to the window */
912   tmpx -= private->abs_x;
913   tmpy -= private->abs_y;
914
915   if (x)
916     *x = tmpx;
917   if (y)
918     *y = tmpy;
919   if (mask)
920     *mask = tmp_mask;
921
922   if (normal_child)
923     return _gdk_window_find_child_at (window, tmpx, tmpy);
924   return NULL;
925 }
926
927 /**
928  * gdk_display_get_window_at_pointer:
929  * @display: a #GdkDisplay
930  * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
931  *    to the window origin, or %NULL
932  * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
933  &    to the window origin, or %NULL
934  *
935  * Obtains the window underneath the mouse pointer, returning the location
936  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
937  * if the window under the mouse pointer is not known to GDK (for example, 
938  * belongs to another application).
939  *
940  * Returns: (transfer none): the window under the mouse pointer, or %NULL
941  *
942  * Since: 2.2
943  *
944  * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
945  **/
946 GdkWindow *
947 gdk_display_get_window_at_pointer (GdkDisplay *display,
948                                    gint       *win_x,
949                                    gint       *win_y)
950 {
951   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
952
953   return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
954 }
955
956 static void
957 multihead_get_device_state (GdkDisplay       *display,
958                             GdkDevice        *device,
959                             GdkScreen       **screen,
960                             gint             *x,
961                             gint             *y,
962                             GdkModifierType  *mask)
963 {
964   multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
965 }
966
967 static GdkWindow *
968 multihead_window_get_device_position (GdkDisplay      *display,
969                                       GdkDevice       *device,
970                                       GdkWindow       *window,
971                                       gint            *x,
972                                       gint            *y,
973                                       GdkModifierType *mask)
974 {
975   return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
976 }
977
978 static GdkWindow *
979 multihead_window_at_device_position (GdkDisplay *display,
980                                      GdkDevice  *device,
981                                      gint       *win_x,
982                                      gint       *win_y)
983 {
984   return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
985 }
986
987 static void
988 multihead_default_get_pointer (GdkDisplay       *display,
989                                GdkScreen       **screen,
990                                gint             *x,
991                                gint             *y,
992                                GdkModifierType  *mask)
993 {
994   return _gdk_windowing_get_device_state (display,
995                                           display->core_pointer,
996                                           screen, x, y, mask);
997 }
998
999 static GdkWindow *
1000 multihead_default_window_get_pointer (GdkDisplay      *display,
1001                                       GdkWindow       *window,
1002                                       gint            *x,
1003                                       gint            *y,
1004                                       GdkModifierType *mask)
1005 {
1006   return gdk_window_real_window_get_device_position (display,
1007                                                      display->core_pointer,
1008                                                      window, x, y, mask);
1009 }
1010
1011 static GdkWindow *
1012 multihead_default_window_at_pointer (GdkDisplay *display,
1013                                      gint       *win_x,
1014                                      gint       *win_y)
1015 {
1016   return gdk_display_real_get_window_at_device_position (display,
1017                                                          display->core_pointer,
1018                                                          win_x, win_y);
1019 }
1020
1021 /**
1022  * gdk_display_set_pointer_hooks:
1023  * @display: a #GdkDisplay
1024  * @new_hooks: a table of pointers to functions for getting
1025  *   quantities related to the current pointer position,
1026  *   or %NULL to restore the default table.
1027  * 
1028  * This function allows for hooking into the operation
1029  * of getting the current location of the pointer on a particular
1030  * display. This is only useful for such low-level tools as an
1031  * event recorder. Applications should never have any
1032  * reason to use this facility.
1033  *
1034  * Return value: the previous pointer hook table
1035  *
1036  * Since: 2.2
1037  *
1038  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1039  **/
1040 GdkDisplayPointerHooks *
1041 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
1042                                const GdkDisplayPointerHooks *new_hooks)
1043 {
1044   const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1045
1046   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1047
1048   if (new_hooks)
1049     multihead_current_pointer_hooks = new_hooks;
1050   else
1051     multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1052
1053   gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1054
1055   return (GdkDisplayPointerHooks *)result;
1056 }
1057
1058 static void
1059 singlehead_get_pointer (GdkDisplay       *display,
1060                         GdkScreen       **screen,
1061                         gint             *x,
1062                         gint             *y,
1063                         GdkModifierType  *mask)
1064 {
1065   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1066   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1067
1068   *screen = default_screen;
1069
1070   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1071 }
1072
1073 static GdkWindow*
1074 singlehead_window_get_pointer (GdkDisplay       *display,
1075                                GdkWindow        *window,
1076                                gint             *x,
1077                                gint             *y,
1078                                GdkModifierType  *mask)
1079 {
1080   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1081 }
1082
1083 static GdkWindow*
1084 singlehead_window_at_pointer   (GdkDisplay *display,
1085                                 gint       *win_x,
1086                                 gint       *win_y)
1087 {
1088   GdkScreen *default_screen = gdk_display_get_default_screen (display);
1089
1090   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1091                                                               win_x, win_y);
1092 }
1093
1094 static GdkWindow*
1095 singlehead_default_window_get_pointer (GdkWindow       *window,
1096                                        gint            *x,
1097                                        gint            *y,
1098                                        GdkModifierType *mask)
1099 {
1100   GdkDisplay *display;
1101
1102   display = gdk_drawable_get_display (window);
1103
1104   return gdk_window_real_window_get_device_position (display,
1105                                                      display->core_pointer,
1106                                                      window, x, y, mask);
1107 }
1108
1109 static GdkWindow*
1110 singlehead_default_window_at_pointer  (GdkScreen       *screen,
1111                                        gint            *win_x,
1112                                        gint            *win_y)
1113 {
1114   GdkDisplay *display;
1115
1116   display = gdk_screen_get_display (screen);
1117
1118   return gdk_display_real_get_window_at_device_position (display,
1119                                                          display->core_pointer,
1120                                                          win_x, win_y);
1121 }
1122
1123 /**
1124  * gdk_set_pointer_hooks:
1125  * @new_hooks: a table of pointers to functions for getting
1126  *   quantities related to the current pointer position,
1127  *   or %NULL to restore the default table.
1128  * 
1129  * This function allows for hooking into the operation
1130  * of getting the current location of the pointer. This
1131  * is only useful for such low-level tools as an
1132  * event recorder. Applications should never have any
1133  * reason to use this facility.
1134  *
1135  * This function is not multihead safe. For multihead operation,
1136  * see gdk_display_set_pointer_hooks().
1137  * 
1138  * Return value: the previous pointer hook table
1139  *
1140  * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1141  **/
1142 GdkPointerHooks *
1143 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1144 {
1145   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1146
1147   if (new_hooks)
1148     singlehead_current_pointer_hooks = new_hooks;
1149   else
1150     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1151
1152   gdk_display_set_pointer_hooks (gdk_display_get_default (),
1153                                  &singlehead_pointer_hooks);
1154   
1155   return (GdkPointerHooks *)result;
1156 }
1157
1158 static void
1159 generate_grab_broken_event (GdkWindow *window,
1160                             GdkDevice *device,
1161                             gboolean   implicit,
1162                             GdkWindow *grab_window)
1163 {
1164   g_return_if_fail (window != NULL);
1165
1166   if (!GDK_WINDOW_DESTROYED (window))
1167     {
1168       GdkEvent *event;
1169
1170       event = gdk_event_new (GDK_GRAB_BROKEN);
1171       event->grab_broken.window = g_object_ref (window);
1172       event->grab_broken.send_event = FALSE;
1173       event->grab_broken.implicit = implicit;
1174       event->grab_broken.grab_window = grab_window;
1175       gdk_event_set_device (event, device);
1176       event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1177
1178       gdk_event_put (event);
1179       gdk_event_free (event);
1180     }
1181 }
1182
1183 GdkDeviceGrabInfo *
1184 _gdk_display_get_last_device_grab (GdkDisplay *display,
1185                                    GdkDevice  *device)
1186 {
1187   GList *l;
1188
1189   l = g_hash_table_lookup (display->device_grabs, device);
1190
1191   if (l)
1192     {
1193       l = g_list_last (l);
1194       return l->data;
1195     }
1196
1197   return NULL;
1198 }
1199
1200 GdkDeviceGrabInfo *
1201 _gdk_display_add_device_grab (GdkDisplay       *display,
1202                               GdkDevice        *device,
1203                               GdkWindow        *window,
1204                               GdkWindow        *native_window,
1205                               GdkGrabOwnership  grab_ownership,
1206                               gboolean          owner_events,
1207                               GdkEventMask      event_mask,
1208                               unsigned long     serial_start,
1209                               guint32           time,
1210                               gboolean          implicit)
1211 {
1212   GdkDeviceGrabInfo *info, *other_info;
1213   GList *grabs, *l;
1214
1215   info = g_new0 (GdkDeviceGrabInfo, 1);
1216
1217   info->window = g_object_ref (window);
1218   info->native_window = g_object_ref (native_window);
1219   info->serial_start = serial_start;
1220   info->serial_end = G_MAXULONG;
1221   info->owner_events = owner_events;
1222   info->event_mask = event_mask;
1223   info->time = time;
1224   info->implicit = implicit;
1225   info->ownership = grab_ownership;
1226
1227   grabs = g_hash_table_lookup (display->device_grabs, device);
1228
1229   /* Find the first grab that has a larger start time (if any) and insert
1230    * before that. I.E we insert after already existing grabs with same
1231    * start time */
1232   for (l = grabs; l != NULL; l = l->next)
1233     {
1234       other_info = l->data;
1235
1236       if (info->serial_start < other_info->serial_start)
1237         break;
1238     }
1239
1240   grabs = g_list_insert_before (grabs, l, info);
1241
1242   /* Make sure the new grab end before next grab */
1243   if (l)
1244     {
1245       other_info = l->data;
1246       info->serial_end = other_info->serial_start;
1247     }
1248
1249   /* Find any previous grab and update its end time */
1250   l = g_list_find (grabs, info);
1251   l = l->prev;
1252   if (l)
1253     {
1254       other_info = l->data;
1255       other_info->serial_end = serial_start;
1256     }
1257
1258   g_hash_table_insert (display->device_grabs, device, grabs);
1259
1260   return info;
1261 }
1262
1263 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1264    This function splits things into two calls if needed, converting the
1265    coordinates to the right toplevel */
1266 static void
1267 synthesize_crossing_events (GdkDisplay      *display,
1268                             GdkDevice       *device,
1269                             GdkWindow       *src_window,
1270                             GdkWindow       *dest_window,
1271                             GdkCrossingMode  crossing_mode,
1272                             guint32          time,
1273                             gulong           serial)
1274 {
1275   GdkWindow *src_toplevel, *dest_toplevel;
1276   GdkModifierType state;
1277   int x, y;
1278
1279   /* We use the native crossing events if all native */
1280   if (_gdk_native_windows)
1281     return;
1282   
1283   if (src_window)
1284     src_toplevel = gdk_window_get_toplevel (src_window);
1285   else
1286     src_toplevel = NULL;
1287   if (dest_window)
1288     dest_toplevel = gdk_window_get_toplevel (dest_window);
1289   else
1290     dest_toplevel = NULL;
1291
1292   if (src_toplevel == NULL && dest_toplevel == NULL)
1293     return;
1294   
1295   if (src_toplevel == NULL ||
1296       src_toplevel == dest_toplevel)
1297     {
1298       /* Same toplevels */
1299       gdk_window_get_pointer (dest_toplevel,
1300                               &x, &y, &state);
1301       _gdk_synthesize_crossing_events (display,
1302                                        src_window,
1303                                        dest_window,
1304                                        device,
1305                                        crossing_mode,
1306                                        x, y, state,
1307                                        time,
1308                                        NULL,
1309                                        serial, FALSE);
1310     }
1311   else if (dest_toplevel == NULL)
1312     {
1313       gdk_window_get_pointer (src_toplevel,
1314                               &x, &y, &state);
1315       _gdk_synthesize_crossing_events (display,
1316                                        src_window,
1317                                        NULL,
1318                                        device,
1319                                        crossing_mode,
1320                                        x, y, state,
1321                                        time,
1322                                        NULL,
1323                                        serial, FALSE);
1324     }
1325   else
1326     {
1327       /* Different toplevels */
1328       gdk_window_get_pointer (src_toplevel,
1329                               &x, &y, &state);
1330       _gdk_synthesize_crossing_events (display,
1331                                        src_window,
1332                                        NULL,
1333                                        device,
1334                                        crossing_mode,
1335                                        x, y, state,
1336                                        time,
1337                                        NULL,
1338                                        serial, FALSE);
1339       gdk_window_get_pointer (dest_toplevel,
1340                               &x, &y, &state);
1341       _gdk_synthesize_crossing_events (display,
1342                                        NULL,
1343                                        dest_window,
1344                                        device,
1345                                        crossing_mode,
1346                                        x, y, state,
1347                                        time,
1348                                        NULL,
1349                                        serial, FALSE);
1350     }
1351 }
1352
1353 static GdkWindow *
1354 get_current_toplevel (GdkDisplay      *display,
1355                       GdkDevice       *device,
1356                       int             *x_out,
1357                       int             *y_out,
1358                       GdkModifierType *state_out)
1359 {
1360   GdkWindow *pointer_window;
1361   int x, y;
1362   GdkModifierType state;
1363
1364   pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1365
1366   if (pointer_window != NULL &&
1367       (GDK_WINDOW_DESTROYED (pointer_window) ||
1368        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1369        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1370     pointer_window = NULL;
1371
1372   *x_out = x;
1373   *y_out = y;
1374   *state_out = state;
1375   return pointer_window;
1376 }
1377
1378 static void
1379 switch_to_pointer_grab (GdkDisplay        *display,
1380                         GdkDevice         *device,
1381                         GdkDeviceGrabInfo *grab,
1382                         GdkDeviceGrabInfo *last_grab,
1383                         guint32            time,
1384                         gulong             serial)
1385 {
1386   GdkWindow *src_window, *pointer_window, *new_toplevel;
1387   GdkPointerWindowInfo *info;
1388   GList *old_grabs;
1389   GdkModifierType state;
1390   int x, y;
1391
1392   /* Temporarily unset pointer to make sure we send the crossing events below */
1393   old_grabs = g_hash_table_lookup (display->device_grabs, device);
1394   g_hash_table_steal (display->device_grabs, device);
1395   info = _gdk_display_get_pointer_info (display, device);
1396
1397   if (grab)
1398     {
1399       /* New grab is in effect */
1400
1401       /* We need to generate crossing events for the grab.
1402        * However, there are never any crossing events for implicit grabs
1403        * TODO: ... Actually, this could happen if the pointer window
1404        *           doesn't have button mask so a parent gets the event...
1405        */
1406       if (!grab->implicit)
1407         {
1408           /* We send GRAB crossing events from the window under the pointer to the
1409              grab window. Except if there is an old grab then we start from that */
1410           if (last_grab)
1411             src_window = last_grab->window;
1412           else
1413             src_window = info->window_under_pointer;
1414
1415           if (src_window != grab->window)
1416             synthesize_crossing_events (display, device,
1417                                         src_window, grab->window,
1418                                         GDK_CROSSING_GRAB, time, serial);
1419
1420           /* !owner_event Grabbing a window that we're not inside, current status is
1421              now NULL (i.e. outside grabbed window) */
1422           if (!grab->owner_events && info->window_under_pointer != grab->window)
1423             _gdk_display_set_window_under_pointer (display, device, NULL);
1424         }
1425
1426       grab->activated = TRUE;
1427     }
1428
1429   if (last_grab)
1430     {
1431       new_toplevel = NULL;
1432
1433       if (grab == NULL /* ungrab */ ||
1434           (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1435         {
1436           /* We force check what window we're in, and update the toplevel_under_pointer info,
1437            * as that won't get told of this change with toplevel enter events.
1438            */
1439           if (info->toplevel_under_pointer)
1440             g_object_unref (info->toplevel_under_pointer);
1441           info->toplevel_under_pointer = NULL;
1442
1443           new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1444           if (new_toplevel)
1445             {
1446               /* w is now toplevel and x,y in toplevel coords */
1447               info->toplevel_under_pointer = g_object_ref (new_toplevel);
1448               info->toplevel_x = x;
1449               info->toplevel_y = y;
1450               info->state = state;
1451             }
1452         }
1453
1454       if (grab == NULL) /* Ungrabbed, send events */
1455         {
1456           pointer_window = NULL;
1457           if (new_toplevel)
1458             {
1459               /* Find (possibly virtual) child window */
1460               pointer_window =
1461                 _gdk_window_find_descendant_at (new_toplevel,
1462                                                 x, y,
1463                                                 NULL, NULL);
1464             }
1465
1466           if (pointer_window != last_grab->window)
1467             synthesize_crossing_events (display, device,
1468                                         last_grab->window, pointer_window,
1469                                         GDK_CROSSING_UNGRAB, time, serial);
1470
1471           /* We're now ungrabbed, update the window_under_pointer */
1472           _gdk_display_set_window_under_pointer (display, device, pointer_window);
1473         }
1474     }
1475
1476   g_hash_table_insert (display->device_grabs, device, old_grabs);
1477 }
1478
1479 void
1480 _gdk_display_device_grab_update (GdkDisplay *display,
1481                                  GdkDevice  *device,
1482                                  gulong      current_serial)
1483 {
1484   GdkDeviceGrabInfo *current_grab, *next_grab;
1485   GList *grabs;
1486   guint32 time;
1487
1488   time = display->last_event_time;
1489   grabs = g_hash_table_lookup (display->device_grabs, device);
1490
1491   while (grabs != NULL)
1492     {
1493       current_grab = grabs->data;
1494
1495       if (current_grab->serial_start > current_serial)
1496         return; /* Hasn't started yet */
1497
1498       if (current_grab->serial_end > current_serial)
1499         {
1500           /* This one hasn't ended yet.
1501              its the currently active one or scheduled to be active */
1502
1503           if (!current_grab->activated)
1504             {
1505               if (device->source != GDK_SOURCE_KEYBOARD)
1506                 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1507             }
1508
1509           break;
1510         }
1511
1512       next_grab = NULL;
1513       if (grabs->next)
1514         {
1515           /* This is the next active grab */
1516           next_grab = grabs->next->data;
1517
1518           if (next_grab->serial_start > current_serial)
1519             next_grab = NULL; /* Actually its not yet active */
1520         }
1521
1522       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1523           (next_grab != NULL && current_grab->window != next_grab->window))
1524         generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1525                                     device,
1526                                     current_grab->implicit,
1527                                     next_grab? next_grab->window : NULL);
1528
1529       /* Remove old grab */
1530       grabs = g_list_delete_link (grabs, grabs);
1531       g_hash_table_insert (display->device_grabs, device, grabs);
1532
1533       if (device->source != GDK_SOURCE_KEYBOARD)
1534         switch_to_pointer_grab (display, device,
1535                                 next_grab, current_grab,
1536                                 time, current_serial);
1537
1538       free_device_grab (current_grab);
1539     }
1540 }
1541
1542 static GList *
1543 grab_list_find (GList  *grabs,
1544                 gulong  serial)
1545 {
1546   GdkDeviceGrabInfo *grab;
1547
1548   while (grabs)
1549     {
1550       grab = grabs->data;
1551
1552       if (serial >= grab->serial_start && serial < grab->serial_end)
1553         return grabs;
1554
1555       grabs = grabs->next;
1556     }
1557
1558   return NULL;
1559 }
1560
1561 static GList *
1562 find_device_grab (GdkDisplay *display,
1563                    GdkDevice  *device,
1564                    gulong      serial)
1565 {
1566   GList *l;
1567
1568   l = g_hash_table_lookup (display->device_grabs, device);
1569   return grab_list_find (l, serial);
1570 }
1571
1572 GdkDeviceGrabInfo *
1573 _gdk_display_has_device_grab (GdkDisplay *display,
1574                               GdkDevice  *device,
1575                               gulong      serial)
1576 {
1577   GList *l;
1578
1579   l = find_device_grab (display, device, serial);
1580   if (l)
1581     return l->data;
1582
1583   return NULL;
1584 }
1585
1586 /* Returns true if last grab was ended
1587  * If if_child is non-NULL, end the grab only if the grabbed
1588  * window is the same as if_child or a descendant of it */
1589 gboolean
1590 _gdk_display_end_device_grab (GdkDisplay *display,
1591                               GdkDevice  *device,
1592                               gulong      serial,
1593                               GdkWindow  *if_child,
1594                               gboolean    implicit)
1595 {
1596   GdkDeviceGrabInfo *grab;
1597   GList *l;
1598
1599   l = find_device_grab (display, device, serial);
1600
1601   if (l == NULL)
1602     return FALSE;
1603
1604   grab = l->data;
1605   if (grab &&
1606       (if_child == NULL ||
1607        _gdk_window_event_parent_of (if_child, grab->window)))
1608     {
1609       grab->serial_end = serial;
1610       grab->implicit_ungrab = implicit;
1611       return l->next == NULL;
1612     }
1613   
1614   return FALSE;
1615 }
1616
1617 /* Returns TRUE if device events are not blocked by any grab */
1618 gboolean
1619 _gdk_display_check_grab_ownership (GdkDisplay *display,
1620                                    GdkDevice  *device,
1621                                    gulong      serial)
1622 {
1623   GHashTableIter iter;
1624   gpointer key, value;
1625   GdkGrabOwnership higher_ownership, device_ownership;
1626   gboolean device_is_keyboard;
1627
1628   g_hash_table_iter_init (&iter, display->device_grabs);
1629   higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1630   device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1631
1632   while (g_hash_table_iter_next (&iter, &key, &value))
1633     {
1634       GdkDeviceGrabInfo *grab;
1635       GdkDevice *dev;
1636       GList *grabs;
1637
1638       dev = key;
1639       grabs = value;
1640       grabs = grab_list_find (grabs, serial);
1641
1642       if (!grabs)
1643         continue;
1644
1645       /* Discard device if it's not of the same type */
1646       if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1647           (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1648         continue;
1649
1650       grab = grabs->data;
1651
1652       if (dev == device)
1653         device_ownership = grab->ownership;
1654       else
1655         {
1656           if (grab->ownership > higher_ownership)
1657             higher_ownership = grab->ownership;
1658         }
1659     }
1660
1661   if (higher_ownership > device_ownership)
1662     {
1663       /* There's a higher priority ownership
1664        * going on for other device(s)
1665        */
1666       return FALSE;
1667     }
1668
1669   return TRUE;
1670 }
1671
1672 GdkPointerWindowInfo *
1673 _gdk_display_get_pointer_info (GdkDisplay *display,
1674                                GdkDevice  *device)
1675 {
1676   GdkPointerWindowInfo *info;
1677
1678   if (G_UNLIKELY (!device))
1679     return NULL;
1680
1681   info = g_hash_table_lookup (display->pointers_info, device);
1682
1683   if (G_UNLIKELY (!info))
1684     {
1685       info = g_slice_new0 (GdkPointerWindowInfo);
1686       g_hash_table_insert (display->pointers_info, device, info);
1687     }
1688
1689   return info;
1690 }
1691
1692 void
1693 _gdk_display_pointer_info_foreach (GdkDisplay                   *display,
1694                                    GdkDisplayPointerInfoForeach  func,
1695                                    gpointer                      user_data)
1696 {
1697   GHashTableIter iter;
1698   gpointer key, value;
1699
1700   g_hash_table_iter_init (&iter, display->pointers_info);
1701
1702   while (g_hash_table_iter_next (&iter, &key, &value))
1703     {
1704       GdkPointerWindowInfo *info = value;
1705       GdkDevice *device = key;
1706
1707       (func) (display, device, info, user_data);
1708     }
1709 }
1710
1711 /**
1712  * gdk_device_grab_info_libgtk_only:
1713  * @display: the display for which to get the grab information
1714  * @device: device to get the grab information from
1715  * @grab_window: location to store current grab window
1716  * @owner_events: location to store boolean indicating whether
1717  *   the @owner_events flag to gdk_keyboard_grab() or
1718  *   gdk_pointer_grab() was %TRUE.
1719  *
1720  * Determines information about the current keyboard grab.
1721  * This is not public API and must not be used by applications.
1722  *
1723  * Return value: %TRUE if this application currently has the
1724  *  keyboard grabbed.
1725  **/
1726 gboolean
1727 gdk_device_grab_info_libgtk_only (GdkDisplay  *display,
1728                                   GdkDevice   *device,
1729                                   GdkWindow  **grab_window,
1730                                   gboolean    *owner_events)
1731 {
1732   GdkDeviceGrabInfo *info;
1733
1734   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1735   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1736
1737   info = _gdk_display_get_last_device_grab (display, device);
1738
1739   if (info)
1740     {
1741       if (grab_window)
1742         *grab_window = info->window;
1743       if (owner_events)
1744         *owner_events = info->owner_events;
1745
1746       return TRUE;
1747     }
1748   else
1749     return FALSE;
1750 }
1751
1752 /**
1753  * gdk_display_pointer_is_grabbed:
1754  * @display: a #GdkDisplay
1755  *
1756  * Test if the pointer is grabbed.
1757  *
1758  * Returns: %TRUE if an active X pointer grab is in effect
1759  *
1760  * Since: 2.2
1761  *
1762  * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1763  */
1764 gboolean
1765 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1766 {
1767   GdkDeviceManager *device_manager;
1768   GList *devices, *dev;
1769   GdkDevice *device;
1770
1771   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1772
1773   device_manager = gdk_display_get_device_manager (display);
1774   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1775
1776   for (dev = devices; dev; dev = dev->next)
1777     {
1778       device = dev->data;
1779
1780       if (device->source == GDK_SOURCE_MOUSE &&
1781           gdk_display_device_is_grabbed (display, device))
1782         return TRUE;
1783     }
1784
1785   return FALSE;
1786 }
1787
1788 /**
1789  * gdk_display_device_is_grabbed:
1790  * @display: a #GdkDisplay
1791  * @device: a #GdkDevice
1792  *
1793  * Returns %TRUE if there is an ongoing grab on @device for @display.
1794  *
1795  * Returns: %TRUE if there is a grab in effect for @device.
1796  **/
1797 gboolean
1798 gdk_display_device_is_grabbed (GdkDisplay *display,
1799                                GdkDevice  *device)
1800 {
1801   GdkDeviceGrabInfo *info;
1802
1803   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1804   g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1805
1806   /* What we're interested in is the steady state (ie last grab),
1807      because we're interested e.g. if we grabbed so that we
1808      can ungrab, even if our grab is not active just yet. */
1809   info = _gdk_display_get_last_device_grab (display, device);
1810
1811   return (info && !info->implicit);
1812 }
1813
1814 /**
1815  * gdk_display_get_device_manager:
1816  * @display: a #GdkDisplay.
1817  *
1818  * Returns the #GdkDeviceManager associated to @display.
1819  *
1820  * Returns: A #GdkDeviceManager, or %NULL. This memory is
1821  *          owned by GDK and must not be freed or unreferenced.
1822  *
1823  * Since: 3.0
1824  **/
1825 GdkDeviceManager *
1826 gdk_display_get_device_manager (GdkDisplay *display)
1827 {
1828   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1829
1830   return display->device_manager;
1831 }