]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
Initial client-side-windows work
[~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 #include "gdkalias.h"
34
35 enum {
36   CLOSED,
37   LAST_SIGNAL
38 };
39
40 static void gdk_display_dispose    (GObject         *object);
41 static void gdk_display_finalize   (GObject         *object);
42
43
44 static void       singlehead_get_pointer (GdkDisplay       *display,
45                                           GdkScreen       **screen,
46                                           gint             *x,
47                                           gint             *y,
48                                           GdkModifierType  *mask);
49 static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
50                                                  GdkWindow        *window,
51                                                  gint             *x,
52                                                  gint             *y,
53                                                  GdkModifierType  *mask);
54 static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
55                                                  gint             *win_x,
56                                                  gint             *win_y);
57
58 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
59                                                          gint            *x,
60                                                          gint            *y,
61                                                          GdkModifierType *mask);
62 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
63                                                          gint            *win_x,
64                                                          gint            *win_y);
65 static GdkWindow *gdk_window_real_window_get_pointer     (GdkDisplay       *display,
66                                                           GdkWindow        *window,
67                                                           gint             *x,
68                                                           gint             *y,
69                                                           GdkModifierType  *mask);
70 static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay       *display,
71                                                           gint             *win_x,
72                                                           gint             *win_y);
73
74 static guint signals[LAST_SIGNAL] = { 0 };
75
76 static char *gdk_sm_client_id;
77
78 static const GdkDisplayPointerHooks default_pointer_hooks = {
79   _gdk_windowing_get_pointer,
80   gdk_window_real_window_get_pointer,
81   gdk_display_real_get_window_at_pointer
82 };
83
84 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
85   singlehead_get_pointer,
86   singlehead_window_get_pointer,
87   singlehead_window_at_pointer
88 };
89
90 static const GdkPointerHooks singlehead_default_pointer_hooks = {
91   singlehead_default_window_get_pointer,
92   singlehead_default_window_at_pointer
93 };
94
95 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
96
97 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
98
99 static void
100 gdk_display_class_init (GdkDisplayClass *class)
101 {
102   GObjectClass *object_class = G_OBJECT_CLASS (class);
103   
104   object_class->finalize = gdk_display_finalize;
105   object_class->dispose = gdk_display_dispose;
106
107   /**
108    * GdkDisplay::closed:
109    * @display: the object on which the signal is emitted
110    * @is_error: %TRUE if the display was closed due to an error
111    *
112    * The ::closed signal is emitted when the connection to the windowing
113    * system for @display is closed.
114    *
115    * Since: 2.2
116    */   
117   signals[CLOSED] =
118     g_signal_new (g_intern_static_string ("closed"),
119                   G_OBJECT_CLASS_TYPE (object_class),
120                   G_SIGNAL_RUN_LAST,
121                   G_STRUCT_OFFSET (GdkDisplayClass, closed),
122                   NULL, NULL,
123                   gdk_marshal_VOID__BOOLEAN,
124                   G_TYPE_NONE,
125                   1,
126                   G_TYPE_BOOLEAN);
127 }
128
129 static void
130 gdk_display_init (GdkDisplay *display)
131 {
132   _gdk_displays = g_slist_prepend (_gdk_displays, display);
133
134   display->button_click_time[0] = display->button_click_time[1] = 0;
135   display->button_window[0] = display->button_window[1] = NULL;
136   display->button_number[0] = display->button_number[1] = -1;
137   display->button_x[0] = display->button_x[1] = 0;
138   display->button_y[0] = display->button_y[1] = 0;
139
140   display->double_click_time = 250;
141   display->double_click_distance = 5;
142
143   display->pointer_hooks = &default_pointer_hooks;
144 }
145
146 static void
147 gdk_display_dispose (GObject *object)
148 {
149   GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
150
151   g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
152   g_list_free (display->queued_events);
153   display->queued_events = NULL;
154   display->queued_tail = NULL;
155
156   _gdk_displays = g_slist_remove (_gdk_displays, object);
157
158   if (gdk_display_get_default() == display)
159     {
160       if (_gdk_displays)
161         gdk_display_manager_set_default_display (gdk_display_manager_get(),
162                                                  _gdk_displays->data);
163       else
164         gdk_display_manager_set_default_display (gdk_display_manager_get(),
165                                                  NULL);
166     }
167
168   G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
169 }
170
171 static void
172 gdk_display_finalize (GObject *object)
173 {
174   G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
175 }
176
177 /**
178  * gdk_display_close:
179  * @display: a #GdkDisplay
180  *
181  * Closes the connection to the windowing system for the given display,
182  * and cleans up associated resources.
183  *
184  * Since: 2.2
185  */
186 void
187 gdk_display_close (GdkDisplay *display)
188 {
189   g_return_if_fail (GDK_IS_DISPLAY (display));
190
191   if (!display->closed)
192     {
193       display->closed = TRUE;
194       
195       g_signal_emit (display, signals[CLOSED], 0, FALSE);
196       g_object_run_dispose (G_OBJECT (display));
197       
198       g_object_unref (display);
199     }
200 }
201
202 /**
203  * gdk_display_get_event:
204  * @display: a #GdkDisplay
205  * 
206  * Gets the next #GdkEvent to be processed for @display, fetching events from the
207  * windowing system if necessary.
208  * 
209  * Return value: the next #GdkEvent to be processed, or %NULL if no events
210  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
211  *
212  * Since: 2.2
213  **/
214 GdkEvent*
215 gdk_display_get_event (GdkDisplay *display)
216 {
217   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
218   
219   _gdk_events_queue (display);
220   return _gdk_event_unqueue (display);
221 }
222
223 /**
224  * gdk_display_peek_event:
225  * @display: a #GdkDisplay 
226  * 
227  * Gets a copy of the first #GdkEvent in the @display's event queue, without
228  * removing the event from the queue.  (Note that this function will
229  * not get more events from the windowing system.  It only checks the events
230  * that have already been moved to the GDK event queue.)
231  * 
232  * Return value: a copy of the first #GdkEvent on the event queue, or %NULL 
233  * if no events are in the queue. The returned #GdkEvent should be freed with
234  * gdk_event_free().
235  *
236  * Since: 2.2
237  **/
238 GdkEvent*
239 gdk_display_peek_event (GdkDisplay *display)
240 {
241   GList *tmp_list;
242
243   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
244
245   tmp_list = _gdk_event_queue_find_first (display);
246   
247   if (tmp_list)
248     return gdk_event_copy (tmp_list->data);
249   else
250     return NULL;
251 }
252
253 /**
254  * gdk_display_put_event:
255  * @display: a #GdkDisplay
256  * @event: a #GdkEvent.
257  *
258  * Appends a copy of the given event onto the front of the event
259  * queue for @display.
260  *
261  * Since: 2.2
262  **/
263 void
264 gdk_display_put_event (GdkDisplay     *display,
265                        const GdkEvent *event)
266 {
267   g_return_if_fail (GDK_IS_DISPLAY (display));
268   g_return_if_fail (event != NULL);
269
270   _gdk_event_queue_append (display, gdk_event_copy (event));
271   /* If the main loop is blocking in a different thread, wake it up */
272   g_main_context_wakeup (NULL); 
273 }
274
275 /**
276  * gdk_pointer_ungrab:
277  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
278  *  timestamp is available.
279  *
280  * Ungrabs the pointer on the default display, if it is grabbed by this 
281  * application.
282  **/
283 void
284 gdk_pointer_ungrab (guint32 time)
285 {
286   gdk_display_pointer_ungrab (gdk_display_get_default (), time);
287 }
288
289 /**
290  * gdk_pointer_is_grabbed:
291  * 
292  * Returns %TRUE if the pointer on the default display is currently 
293  * grabbed by this application.
294  *
295  * Note that this does not take the inmplicit pointer grab on button
296  * presses into account.
297
298  * Return value: %TRUE if the pointer is currently grabbed by this application.* 
299  **/
300 gboolean
301 gdk_pointer_is_grabbed (void)
302 {
303   return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
304 }
305
306 /**
307  * gdk_keyboard_ungrab:
308  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
309  *        timestamp is available.
310  * 
311  * Ungrabs the keyboard on the default display, if it is grabbed by this 
312  * application.
313  **/
314 void
315 gdk_keyboard_ungrab (guint32 time)
316 {
317   gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
318 }
319
320 /**
321  * gdk_beep:
322  * 
323  * Emits a short beep on the default display.
324  **/
325 void
326 gdk_beep (void)
327 {
328   gdk_display_beep (gdk_display_get_default ());
329 }
330
331 /**
332  * gdk_event_send_client_message:
333  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
334  * @winid:  the window to send the X ClientMessage event to.
335  * 
336  * Sends an X ClientMessage event to a given window (which must be
337  * on the default #GdkDisplay.)
338  * This could be used for communicating between different applications,
339  * though the amount of data is limited to 20 bytes.
340  * 
341  * Return value: non-zero on success.
342  **/
343 gboolean
344 gdk_event_send_client_message (GdkEvent        *event,
345                                GdkNativeWindow  winid)
346 {
347   g_return_val_if_fail (event != NULL, FALSE);
348
349   return gdk_event_send_client_message_for_display (gdk_display_get_default (),
350                                                     event, winid);
351 }
352
353 /**
354  * gdk_event_send_clientmessage_toall:
355  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
356  *
357  * Sends an X ClientMessage event to all toplevel windows on the default
358  * #GdkScreen.
359  *
360  * Toplevel windows are determined by checking for the WM_STATE property, as
361  * described in the Inter-Client Communication Conventions Manual (ICCCM).
362  * If no windows are found with the WM_STATE property set, the message is sent
363  * to all children of the root window.
364  **/
365 void
366 gdk_event_send_clientmessage_toall (GdkEvent *event)
367 {
368   g_return_if_fail (event != NULL);
369
370   gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
371 }
372
373 /**
374  * gdk_device_get_core_pointer:
375  * 
376  * Returns the core pointer device for the default display.
377  * 
378  * Return value: the core pointer device; this is owned by the
379  *   display and should not be freed.
380  **/
381 GdkDevice *
382 gdk_device_get_core_pointer (void)
383 {
384   return gdk_display_get_core_pointer (gdk_display_get_default ());
385 }
386
387 /**
388  * gdk_display_get_core_pointer:
389  * @display: a #GdkDisplay
390  * 
391  * Returns the core pointer device for the given display
392  * 
393  * Return value: the core pointer device; this is owned by the
394  *   display and should not be freed.
395  *
396  * Since: 2.2
397  **/
398 GdkDevice *
399 gdk_display_get_core_pointer (GdkDisplay *display)
400 {
401   return display->core_pointer;
402 }
403
404 /**
405  * gdk_set_sm_client_id:
406  * @sm_client_id: the client id assigned by the session manager when the
407  *    connection was opened, or %NULL to remove the property.
408  * 
409  * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
410  * the window manager can save the application's state using the X11R6 ICCCM
411  * session management protocol.
412  *
413  * See the X Session Management Library documentation for more information on
414  * session management and the Inter-Client Communication Conventions Manual
415  * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property. 
416  * (Both documents are part of the X Window System distribution.)
417  **/
418 void
419 gdk_set_sm_client_id (const gchar* sm_client_id)
420 {
421   GSList *displays, *tmp_list;
422   
423   g_free (gdk_sm_client_id);
424   gdk_sm_client_id = g_strdup (sm_client_id);
425
426   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
427   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
428     _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
429
430   g_slist_free (displays);
431 }
432
433 /**
434  * _gdk_get_sm_client_id:
435  * 
436  * Gets the client ID set with gdk_set_sm_client_id(), if any.
437  * 
438  * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
439  *               has never been called.
440  **/
441 const char *
442 _gdk_get_sm_client_id (void)
443 {
444   return gdk_sm_client_id;
445 }
446
447 /**
448  * gdk_display_get_pointer:
449  * @display: a #GdkDisplay
450  * @screen: location to store the screen that the
451  *          cursor is on, or %NULL.
452  * @x: location to store root window X coordinate of pointer, or %NULL.
453  * @y: location to store root window Y coordinate of pointer, or %NULL.
454  * @mask: location to store current modifier mask, or %NULL
455  * 
456  * Gets the current location of the pointer and the current modifier
457  * mask for a given display.
458  *
459  * Since: 2.2
460  **/
461 void
462 gdk_display_get_pointer (GdkDisplay      *display,
463                          GdkScreen      **screen,
464                          gint            *x,
465                          gint            *y,
466                          GdkModifierType *mask)
467 {
468   GdkScreen *tmp_screen;
469   gint tmp_x, tmp_y;
470   GdkModifierType tmp_mask;
471   
472   g_return_if_fail (GDK_IS_DISPLAY (display));
473
474   display->pointer_hooks->get_pointer (display, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
475
476   if (screen)
477     *screen = tmp_screen;
478   if (x)
479     *x = tmp_x;
480   if (y)
481     *y = tmp_y;
482   if (mask)
483     *mask = tmp_mask;
484 }
485
486 static GdkWindow *
487 gdk_display_real_get_window_at_pointer (GdkDisplay *display,
488                                         gint       *win_x,
489                                         gint       *win_y)
490 {
491   GdkWindow *window;
492   gint x, y;
493
494   window = _gdk_windowing_window_at_pointer (display, &x, &y);
495
496   /* This might need corrections, as the native window returned
497      may contain client side children */
498   if (window)
499     {
500       double xx, yy;
501       
502       window = _gdk_window_find_descendant_at (window,
503                                                x, y, 
504                                                &xx, &yy);
505       x = floor (xx + 0.5);
506       y = floor (yy + 0.5);
507     }
508   
509   *win_x = x;
510   *win_y = y;
511   
512   return window;
513 }
514
515 static GdkWindow *
516 gdk_window_real_window_get_pointer (GdkDisplay       *display,
517                                     GdkWindow        *window,
518                                     gint             *x,
519                                     gint             *y,
520                                     GdkModifierType  *mask)
521 {
522   GdkWindowObject *private;
523   GdkWindow *pointer_window;
524   gint tmpx, tmpy;
525
526   private = (GdkWindowObject *) window;
527
528   pointer_window = _gdk_windowing_window_get_pointer (display,
529                                                       window,
530                                                       &tmpx, &tmpy,
531                                                       mask);
532   /* We got the coords on the impl, conver to the window */
533   tmpx += private->abs_x;
534   tmpy += private->abs_y;
535   
536   if (x)
537     *x = tmpx;
538   if (y)
539     *y = tmpy;
540
541   /* We need to recalculate the true child window with the pointer in it
542      due to possible client side child windows */
543   if (pointer_window != NULL)
544     {
545       /* First get the pointer coords relative to pointer_window */
546       _gdk_windowing_window_get_pointer (display,
547                                          pointer_window,
548                                          &tmpx, &tmpy,
549                                          NULL);
550       /* Then convert that to a client side window */
551       pointer_window = _gdk_window_find_descendant_at (pointer_window,
552                                                        tmpx, tmpy, 
553                                                        NULL, NULL);
554     }
555
556   return pointer_window;
557 }
558
559 /**
560  * gdk_display_get_window_at_pointer:
561  * @display: a #GdkDisplay
562  * @win_x: return location for x coordinate of the pointer location relative 
563  *    to the window origin, or %NULL
564  * @win_y: return location for y coordinate of the pointer location relative
565  &    to the window origin, or %NULL
566  * 
567  * Obtains the window underneath the mouse pointer, returning the location
568  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL 
569  * if the window under the mouse pointer is not known to GDK (for example, 
570  * belongs to another application).
571  * 
572  * Returns: the window under the mouse pointer, or %NULL
573  *
574  * Since: 2.2
575  **/
576 GdkWindow *
577 gdk_display_get_window_at_pointer (GdkDisplay *display,
578                                    gint       *win_x,
579                                    gint       *win_y)
580 {
581   gint tmp_x, tmp_y;
582   GdkWindow *window;
583
584   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
585
586   window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
587
588   if (win_x)
589     *win_x = tmp_x;
590   if (win_y)
591     *win_y = tmp_y;
592
593   return window;
594 }
595
596 /**
597  * gdk_display_set_pointer_hooks:
598  * @display: a #GdkDisplay
599  * @new_hooks: a table of pointers to functions for getting
600  *   quantities related to the current pointer position,
601  *   or %NULL to restore the default table.
602  * 
603  * This function allows for hooking into the operation
604  * of getting the current location of the pointer on a particular
605  * display. This is only useful for such low-level tools as an
606  * event recorder. Applications should never have any
607  * reason to use this facility.
608  *
609  * Return value: the previous pointer hook table
610  *
611  * Since: 2.2
612  **/
613 GdkDisplayPointerHooks *
614 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
615                                const GdkDisplayPointerHooks *new_hooks)
616 {
617   const GdkDisplayPointerHooks *result;
618
619   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
620   result = display->pointer_hooks;
621
622   if (new_hooks)
623     display->pointer_hooks = new_hooks;
624   else
625     display->pointer_hooks = &default_pointer_hooks;
626
627   return (GdkDisplayPointerHooks *)result;
628 }
629
630 static void
631 singlehead_get_pointer (GdkDisplay       *display,
632                         GdkScreen       **screen,
633                         gint             *x,
634                         gint             *y,
635                         GdkModifierType  *mask)
636 {
637   GdkScreen *default_screen = gdk_display_get_default_screen (display);
638   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
639
640   *screen = default_screen;
641
642   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
643 }
644
645 static GdkWindow*
646 singlehead_window_get_pointer (GdkDisplay       *display,
647                                GdkWindow        *window,
648                                gint             *x,
649                                gint             *y,
650                                GdkModifierType  *mask)
651 {
652   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
653 }
654
655 static GdkWindow*
656 singlehead_window_at_pointer   (GdkDisplay *display,
657                                 gint       *win_x,
658                                 gint       *win_y)
659 {
660   GdkScreen *default_screen = gdk_display_get_default_screen (display);
661
662   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
663                                                               win_x, win_y);
664 }
665
666 static GdkWindow*
667 singlehead_default_window_get_pointer (GdkWindow       *window,
668                                        gint            *x,
669                                        gint            *y,
670                                        GdkModifierType *mask)
671 {
672   return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
673                                              window, x, y, mask);
674 }
675
676 static GdkWindow*
677 singlehead_default_window_at_pointer  (GdkScreen       *screen,
678                                        gint            *win_x,
679                                        gint            *win_y)
680 {
681   return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
682                                                  win_x, win_y);
683 }
684
685 /**
686  * gdk_set_pointer_hooks:
687  * @new_hooks: a table of pointers to functions for getting
688  *   quantities related to the current pointer position,
689  *   or %NULL to restore the default table.
690  * 
691  * This function allows for hooking into the operation
692  * of getting the current location of the pointer. This
693  * is only useful for such low-level tools as an
694  * event recorder. Applications should never have any
695  * reason to use this facility.
696  *
697  * This function is not multihead safe. For multihead operation,
698  * see gdk_display_set_pointer_hooks().
699  * 
700  * Return value: the previous pointer hook table
701  **/
702 GdkPointerHooks *
703 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
704 {
705   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
706
707   if (new_hooks)
708     singlehead_current_pointer_hooks = new_hooks;
709   else
710     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
711
712   gdk_display_set_pointer_hooks (gdk_display_get_default (),
713                                  &singlehead_pointer_hooks);
714   
715   return (GdkPointerHooks *)result;
716 }
717
718 static void
719 generate_grab_broken_event (GdkWindow *window,
720                             gboolean   keyboard,
721                             gboolean   implicit,
722                             GdkWindow *grab_window)
723 {
724   g_return_if_fail (window != NULL);
725
726   if (!GDK_WINDOW_DESTROYED (window))
727     {
728       GdkEvent event;
729       event.type = GDK_GRAB_BROKEN;
730       event.grab_broken.window = window;
731       event.grab_broken.send_event = 0;
732       event.grab_broken.keyboard = keyboard;
733       event.grab_broken.implicit = implicit;
734       event.grab_broken.grab_window = grab_window;
735       gdk_event_put (&event);
736     }
737 }
738
739 void
740 _gdk_display_set_has_pointer_grab (GdkDisplay *display,
741                                    GdkWindow *window,
742                                    GdkWindow *native_window,
743                                    gboolean owner_events,
744                                    GdkEventMask event_mask,
745                                    unsigned long serial,
746                                    guint32 time,
747                                    gboolean implicit)
748 {
749   int wx, wy;
750   
751   /* Normal GRAB events are sent by listening for enter and leave
752    * events on the native event window, which is then proxied
753    * into the virtual windows when the events are seen.
754    * However, there are two cases where X will not send these events:
755    * * When there is already a grab on the native parent of the
756    *   virtual grab window
757    * * When there is no grab, but the pointer is already in the
758    *   native parent of the virtual grab window
759    * In the first case we send the right GRAB events from the grab, but
760    * in the second case we need to generate our own UNGRAB crossing events.
761    */
762   if (display->pointer_grab.window != NULL &&
763       display->pointer_grab.window != window)
764     {
765       generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
766                                   FALSE, display->pointer_grab.implicit,
767                                   window);
768
769       /* Re-grabbing. Pretend we have no grab for now so that
770          the GRAB events get delivered */
771       display->pointer_grab.window = NULL;
772       _gdk_syntesize_crossing_events (display, 
773                                       display->pointer_grab.window,
774                                       window,
775                                       GDK_CROSSING_GRAB,
776                                       /* These may be stale... */
777                                       display->pointer_info.toplevel_x,
778                                       display->pointer_info.toplevel_y,
779                                       display->pointer_info.state,
780                                       time, TRUE, TRUE);
781     }
782   else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
783     {
784       _gdk_syntesize_crossing_events (display, 
785                                       display->pointer_info.window_under_pointer,
786                                       window,
787                                       GDK_CROSSING_GRAB,
788                                       /* These may be stale... */
789                                       display->pointer_info.toplevel_x,
790                                       display->pointer_info.toplevel_y,
791                                       display->pointer_info.state,
792                                       time, TRUE, TRUE);
793       
794     }
795
796   display->pointer_grab.window = window;
797   display->pointer_grab.native_window = native_window;
798   display->pointer_grab.serial = serial;
799   display->pointer_grab.owner_events = owner_events;
800   display->pointer_grab.event_mask = event_mask;
801   display->pointer_grab.time = time;
802   display->pointer_grab.implicit = implicit;
803   display->pointer_grab.converted_implicit = FALSE;
804 }
805
806 void
807 _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
808                                      gboolean implicit,
809                                      gboolean do_grab_one_pointer_release_event,
810                                      guint32 time)
811 {
812   int wx, wy;
813   GdkWindow *old_grab_window;
814   GdkWindow *old_native_grab_window;
815
816
817   old_grab_window = display->pointer_grab.window;
818   old_native_grab_window = display->pointer_grab.native_window;
819
820   if (do_grab_one_pointer_release_event)
821     display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
822
823   /* We need to set this to null befor syntesizing events to make sure they get
824      delivered to anything but the grab window */
825   display->pointer_grab.window = NULL;
826   
827   /* Normal UNGRAB events are sent by listening for enter and leave
828    * events on the native event window, which is then proxied
829    * into the virtual windows when the events are seen.
830    * However, there are two cases where X will not send these events:
831    * * When this ungrab is due to a new grab on the native window that
832    *   is a parent of the currently grabbed virtual window
833    * * When there is no new grab, and the pointer is already in the
834    *   grabbed virtual windows parent native window
835    * In the first case we send the right GRAB events from the grab, but
836    * in the second case we need to generate our own UNGRAB crossing events.
837    */
838
839   if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
840     {
841       _gdk_syntesize_crossing_events (display, 
842                                       old_grab_window,
843                                       display->pointer_info.window_under_pointer,
844                                       GDK_CROSSING_UNGRAB,
845                                       /* These may be stale... */
846                                       display->pointer_info.toplevel_x,
847                                       display->pointer_info.toplevel_y,
848                                       display->pointer_info.state,
849                                       time, TRUE, TRUE);
850     }
851   
852   if (implicit)
853     generate_grab_broken_event (old_grab_window,
854                                 FALSE, implicit, 
855                                 NULL);
856   
857 }
858
859
860 /**
861  * gdk_pointer_grab_info_libgtk_only:
862  * @display: the #GdkDisplay for which to get the grab information
863  * @grab_window: location to store current grab window
864  * @owner_events: location to store boolean indicating whether
865  *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
866  * 
867  * Determines information about the current pointer grab.
868  * This is not public API and must not be used by applications.
869  * 
870  * Return value: %TRUE if this application currently has the
871  *  pointer grabbed.
872  **/
873 gboolean
874 gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
875                                    GdkWindow **grab_window,
876                                    gboolean   *owner_events)
877 {
878   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
879
880   if (display->pointer_grab.window)
881     {
882       if (grab_window)
883         *grab_window = (GdkWindow *)display->pointer_grab.window;
884       if (owner_events)
885         *owner_events = display->pointer_grab.owner_events;
886
887       return TRUE;
888     }
889   else
890     return FALSE;
891 }
892
893
894 /**
895  * gdk_display_pointer_is_grabbed:
896  * @display: a #GdkDisplay
897  *
898  * Test if the pointer is grabbed.
899  *
900  * Returns: %TRUE if an active X pointer grab is in effect
901  *
902  * Since: 2.2
903  */
904 gboolean
905 gdk_display_pointer_is_grabbed (GdkDisplay *display)
906 {
907   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
908   
909   return (display->pointer_grab.window != NULL &&
910           !display->pointer_grab.implicit);
911 }
912
913 #define __GDK_DISPLAY_C__
914 #include "gdkaliasdef.c"