]> Pileus Git - ~andy/gtk/blob - gdk/gdkdisplay.c
bc515b540bc82ae028645a7790d775d6e7d9db77
[~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   GdkModifierType tmp_mask;
526
527   private = (GdkWindowObject *) window;
528
529   pointer_window = _gdk_windowing_window_get_pointer (display,
530                                                       window,
531                                                       &tmpx, &tmpy,
532                                                       mask);
533   /* We got the coords on the impl, conver to the window */
534   tmpx -= private->abs_x;
535   tmpy -= private->abs_y;
536   
537   if (x)
538     *x = tmpx;
539   if (y)
540     *y = tmpy;
541
542   /* We need to recalculate the true child window with the pointer in it
543      due to possible client side child windows */
544   if (pointer_window != NULL)
545     {
546       /* First get the pointer coords relative to pointer_window */
547       _gdk_windowing_window_get_pointer (display,
548                                          pointer_window,
549                                          &tmpx, &tmpy,
550                                          &tmp_mask);
551       /* Then convert that to a client side window */
552       pointer_window = _gdk_window_find_descendant_at (pointer_window,
553                                                        tmpx, tmpy, 
554                                                        NULL, NULL);
555     }
556
557   return pointer_window;
558 }
559
560 /**
561  * gdk_display_get_window_at_pointer:
562  * @display: a #GdkDisplay
563  * @win_x: return location for x coordinate of the pointer location relative 
564  *    to the window origin, or %NULL
565  * @win_y: return location for y coordinate of the pointer location relative
566  &    to the window origin, or %NULL
567  * 
568  * Obtains the window underneath the mouse pointer, returning the location
569  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL 
570  * if the window under the mouse pointer is not known to GDK (for example, 
571  * belongs to another application).
572  * 
573  * Returns: the window under the mouse pointer, or %NULL
574  *
575  * Since: 2.2
576  **/
577 GdkWindow *
578 gdk_display_get_window_at_pointer (GdkDisplay *display,
579                                    gint       *win_x,
580                                    gint       *win_y)
581 {
582   gint tmp_x, tmp_y;
583   GdkWindow *window;
584
585   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
586
587   window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
588
589   if (win_x)
590     *win_x = tmp_x;
591   if (win_y)
592     *win_y = tmp_y;
593
594   return window;
595 }
596
597 /**
598  * gdk_display_set_pointer_hooks:
599  * @display: a #GdkDisplay
600  * @new_hooks: a table of pointers to functions for getting
601  *   quantities related to the current pointer position,
602  *   or %NULL to restore the default table.
603  * 
604  * This function allows for hooking into the operation
605  * of getting the current location of the pointer on a particular
606  * display. This is only useful for such low-level tools as an
607  * event recorder. Applications should never have any
608  * reason to use this facility.
609  *
610  * Return value: the previous pointer hook table
611  *
612  * Since: 2.2
613  **/
614 GdkDisplayPointerHooks *
615 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
616                                const GdkDisplayPointerHooks *new_hooks)
617 {
618   const GdkDisplayPointerHooks *result;
619
620   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
621   result = display->pointer_hooks;
622
623   if (new_hooks)
624     display->pointer_hooks = new_hooks;
625   else
626     display->pointer_hooks = &default_pointer_hooks;
627
628   return (GdkDisplayPointerHooks *)result;
629 }
630
631 static void
632 singlehead_get_pointer (GdkDisplay       *display,
633                         GdkScreen       **screen,
634                         gint             *x,
635                         gint             *y,
636                         GdkModifierType  *mask)
637 {
638   GdkScreen *default_screen = gdk_display_get_default_screen (display);
639   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
640
641   *screen = default_screen;
642
643   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
644 }
645
646 static GdkWindow*
647 singlehead_window_get_pointer (GdkDisplay       *display,
648                                GdkWindow        *window,
649                                gint             *x,
650                                gint             *y,
651                                GdkModifierType  *mask)
652 {
653   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
654 }
655
656 static GdkWindow*
657 singlehead_window_at_pointer   (GdkDisplay *display,
658                                 gint       *win_x,
659                                 gint       *win_y)
660 {
661   GdkScreen *default_screen = gdk_display_get_default_screen (display);
662
663   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
664                                                               win_x, win_y);
665 }
666
667 static GdkWindow*
668 singlehead_default_window_get_pointer (GdkWindow       *window,
669                                        gint            *x,
670                                        gint            *y,
671                                        GdkModifierType *mask)
672 {
673   return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
674                                              window, x, y, mask);
675 }
676
677 static GdkWindow*
678 singlehead_default_window_at_pointer  (GdkScreen       *screen,
679                                        gint            *win_x,
680                                        gint            *win_y)
681 {
682   return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
683                                                  win_x, win_y);
684 }
685
686 /**
687  * gdk_set_pointer_hooks:
688  * @new_hooks: a table of pointers to functions for getting
689  *   quantities related to the current pointer position,
690  *   or %NULL to restore the default table.
691  * 
692  * This function allows for hooking into the operation
693  * of getting the current location of the pointer. This
694  * is only useful for such low-level tools as an
695  * event recorder. Applications should never have any
696  * reason to use this facility.
697  *
698  * This function is not multihead safe. For multihead operation,
699  * see gdk_display_set_pointer_hooks().
700  * 
701  * Return value: the previous pointer hook table
702  **/
703 GdkPointerHooks *
704 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
705 {
706   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
707
708   if (new_hooks)
709     singlehead_current_pointer_hooks = new_hooks;
710   else
711     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
712
713   gdk_display_set_pointer_hooks (gdk_display_get_default (),
714                                  &singlehead_pointer_hooks);
715   
716   return (GdkPointerHooks *)result;
717 }
718
719 static void
720 generate_grab_broken_event (GdkWindow *window,
721                             gboolean   keyboard,
722                             gboolean   implicit,
723                             GdkWindow *grab_window)
724 {
725   g_return_if_fail (window != NULL);
726
727   if (!GDK_WINDOW_DESTROYED (window))
728     {
729       GdkEvent event;
730       event.type = GDK_GRAB_BROKEN;
731       event.grab_broken.window = window;
732       event.grab_broken.send_event = 0;
733       event.grab_broken.keyboard = keyboard;
734       event.grab_broken.implicit = implicit;
735       event.grab_broken.grab_window = grab_window;
736       gdk_event_put (&event);
737     }
738 }
739
740 void
741 _gdk_display_set_has_pointer_grab (GdkDisplay *display,
742                                    GdkWindow *window,
743                                    GdkWindow *native_window,
744                                    gboolean owner_events,
745                                    GdkEventMask event_mask,
746                                    unsigned long serial,
747                                    guint32 time,
748                                    gboolean implicit)
749 {
750   int wx, wy;
751   
752   /* Normal GRAB events are sent by listening for enter and leave
753    * events on the native event window, which is then proxied
754    * into the virtual windows when the events are seen.
755    * However, there are two cases where X will not send these events:
756    * * When there is already a grab on the native parent of the
757    *   virtual grab window
758    * * When there is no grab, but the pointer is already in the
759    *   native parent of the virtual grab window
760    * In the first case we send the right GRAB events from the grab, but
761    * in the second case we need to generate our own UNGRAB crossing events.
762    */
763   if (display->pointer_grab.window != NULL &&
764       display->pointer_grab.window != window)
765     {
766       generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
767                                   FALSE, display->pointer_grab.implicit,
768                                   window);
769
770       /* Re-grabbing. Pretend we have no grab for now so that
771          the GRAB events get delivered */
772       display->pointer_grab.window = NULL;
773       _gdk_syntesize_crossing_events (display, 
774                                       display->pointer_grab.window,
775                                       window,
776                                       GDK_CROSSING_GRAB,
777                                       /* These may be stale... */
778                                       display->pointer_info.toplevel_x,
779                                       display->pointer_info.toplevel_y,
780                                       display->pointer_info.state,
781                                       time, TRUE, TRUE);
782     }
783   else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
784     {
785       _gdk_syntesize_crossing_events (display, 
786                                       display->pointer_info.window_under_pointer,
787                                       window,
788                                       GDK_CROSSING_GRAB,
789                                       /* These may be stale... */
790                                       display->pointer_info.toplevel_x,
791                                       display->pointer_info.toplevel_y,
792                                       display->pointer_info.state,
793                                       time, TRUE, TRUE);
794       
795     }
796
797   display->pointer_grab.window = window;
798   display->pointer_grab.native_window = native_window;
799   display->pointer_grab.serial = serial;
800   display->pointer_grab.owner_events = owner_events;
801   display->pointer_grab.event_mask = event_mask;
802   display->pointer_grab.time = time;
803   display->pointer_grab.implicit = implicit;
804   display->pointer_grab.converted_implicit = FALSE;
805 }
806
807 void
808 _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
809                                      gboolean implicit,
810                                      gboolean do_grab_one_pointer_release_event,
811                                      guint32 time)
812 {
813   int wx, wy;
814   GdkWindow *old_grab_window;
815   GdkWindow *old_native_grab_window;
816
817
818   old_grab_window = display->pointer_grab.window;
819   old_native_grab_window = display->pointer_grab.native_window;
820
821   if (do_grab_one_pointer_release_event)
822     display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
823
824   /* We need to set this to null befor syntesizing events to make sure they get
825      delivered to anything but the grab window */
826   display->pointer_grab.window = NULL;
827   
828   /* Normal UNGRAB events are sent by listening for enter and leave
829    * events on the native event window, which is then proxied
830    * into the virtual windows when the events are seen.
831    * However, there are two cases where X will not send these events:
832    * * When this ungrab is due to a new grab on the native window that
833    *   is a parent of the currently grabbed virtual window
834    * * When there is no new grab, and the pointer is already in the
835    *   grabbed virtual windows parent native window
836    * In the first case we send the right GRAB events from the grab, but
837    * in the second case we need to generate our own UNGRAB crossing events.
838    */
839
840   if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
841     {
842       _gdk_syntesize_crossing_events (display, 
843                                       old_grab_window,
844                                       display->pointer_info.window_under_pointer,
845                                       GDK_CROSSING_UNGRAB,
846                                       /* These may be stale... */
847                                       display->pointer_info.toplevel_x,
848                                       display->pointer_info.toplevel_y,
849                                       display->pointer_info.state,
850                                       time, TRUE, TRUE);
851     }
852   
853   if (implicit)
854     generate_grab_broken_event (old_grab_window,
855                                 FALSE, implicit, 
856                                 NULL);
857   
858 }
859
860
861 /**
862  * gdk_pointer_grab_info_libgtk_only:
863  * @display: the #GdkDisplay for which to get the grab information
864  * @grab_window: location to store current grab window
865  * @owner_events: location to store boolean indicating whether
866  *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
867  * 
868  * Determines information about the current pointer grab.
869  * This is not public API and must not be used by applications.
870  * 
871  * Return value: %TRUE if this application currently has the
872  *  pointer grabbed.
873  **/
874 gboolean
875 gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
876                                    GdkWindow **grab_window,
877                                    gboolean   *owner_events)
878 {
879   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
880
881   if (display->pointer_grab.window)
882     {
883       if (grab_window)
884         *grab_window = (GdkWindow *)display->pointer_grab.window;
885       if (owner_events)
886         *owner_events = display->pointer_grab.owner_events;
887
888       return TRUE;
889     }
890   else
891     return FALSE;
892 }
893
894
895 /**
896  * gdk_display_pointer_is_grabbed:
897  * @display: a #GdkDisplay
898  *
899  * Test if the pointer is grabbed.
900  *
901  * Returns: %TRUE if an active X pointer grab is in effect
902  *
903  * Since: 2.2
904  */
905 gboolean
906 gdk_display_pointer_is_grabbed (GdkDisplay *display)
907 {
908   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
909   
910   return (display->pointer_grab.window != NULL &&
911           !display->pointer_grab.implicit);
912 }
913
914 #define __GDK_DISPLAY_C__
915 #include "gdkaliasdef.c"