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