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 
G_DEFINE_TYPE(GdkDisplay,gdk_display,G_TYPE_OBJECT)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
gdk_display_init(GdkDisplay * display)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
gdk_display_dispose(GObject * object)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
gdk_display_finalize(GObject * object)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
gdk_display_close(GdkDisplay * display)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_is_closed:
204  * @display: a #GdkDisplay
205  *
206  * Finds out if the display has been closed.
207  *
208  * Returns: %TRUE if the display is closed.
209  *
210  * Since: 2.22
211  */
212 gboolean
gdk_display_is_closed(GdkDisplay * display)213 gdk_display_is_closed  (GdkDisplay  *display)
214 {
215   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
216 
217   return display->closed;
218 }
219 
220 /**
221  * gdk_display_get_event:
222  * @display: a #GdkDisplay
223  *
224  * Gets the next #GdkEvent to be processed for @display, fetching events from the
225  * windowing system if necessary.
226  *
227  * Return value: the next #GdkEvent to be processed, or %NULL if no events
228  * are pending. The returned #GdkEvent should be freed with gdk_event_free().
229  *
230  * Since: 2.2
231  **/
232 GdkEvent*
gdk_display_get_event(GdkDisplay * display)233 gdk_display_get_event (GdkDisplay *display)
234 {
235   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
236 
237   _gdk_events_queue (display);
238   return _gdk_event_unqueue (display);
239 }
240 
241 /**
242  * gdk_display_peek_event:
243  * @display: a #GdkDisplay
244  *
245  * Gets a copy of the first #GdkEvent in the @display's event queue, without
246  * removing the event from the queue.  (Note that this function will
247  * not get more events from the windowing system.  It only checks the events
248  * that have already been moved to the GDK event queue.)
249  *
250  * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
251  * if no events are in the queue. The returned #GdkEvent should be freed with
252  * gdk_event_free().
253  *
254  * Since: 2.2
255  **/
256 GdkEvent*
gdk_display_peek_event(GdkDisplay * display)257 gdk_display_peek_event (GdkDisplay *display)
258 {
259   GList *tmp_list;
260 
261   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
262 
263   tmp_list = _gdk_event_queue_find_first (display);
264 
265   if (tmp_list)
266     return gdk_event_copy (tmp_list->data);
267   else
268     return NULL;
269 }
270 
271 /**
272  * gdk_display_put_event:
273  * @display: a #GdkDisplay
274  * @event: a #GdkEvent.
275  *
276  * Appends a copy of the given event onto the front of the event
277  * queue for @display.
278  *
279  * Since: 2.2
280  **/
281 void
gdk_display_put_event(GdkDisplay * display,const GdkEvent * event)282 gdk_display_put_event (GdkDisplay     *display,
283 		       const GdkEvent *event)
284 {
285   g_return_if_fail (GDK_IS_DISPLAY (display));
286   g_return_if_fail (event != NULL);
287 
288   _gdk_event_queue_append (display, gdk_event_copy (event));
289   /* If the main loop is blocking in a different thread, wake it up */
290   g_main_context_wakeup (NULL);
291 }
292 
293 /**
294  * gdk_pointer_ungrab:
295  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
296  *  timestamp is available.
297  *
298  * Ungrabs the pointer on the default display, if it is grabbed by this
299  * application.
300  **/
301 void
gdk_pointer_ungrab(guint32 time)302 gdk_pointer_ungrab (guint32 time)
303 {
304   gdk_display_pointer_ungrab (gdk_display_get_default (), time);
305 }
306 
307 /**
308  * gdk_pointer_is_grabbed:
309  *
310  * Returns %TRUE if the pointer on the default display is currently
311  * grabbed by this application.
312  *
313  * Note that this does not take the inmplicit pointer grab on button
314  * presses into account.
315 
316  * Return value: %TRUE if the pointer is currently grabbed by this application.*
317  **/
318 gboolean
gdk_pointer_is_grabbed(void)319 gdk_pointer_is_grabbed (void)
320 {
321   return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
322 }
323 
324 /**
325  * gdk_keyboard_ungrab:
326  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
327  *        timestamp is available.
328  *
329  * Ungrabs the keyboard on the default display, if it is grabbed by this
330  * application.
331  **/
332 void
gdk_keyboard_ungrab(guint32 time)333 gdk_keyboard_ungrab (guint32 time)
334 {
335   gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
336 }
337 
338 /**
339  * gdk_beep:
340  *
341  * Emits a short beep on the default display.
342  **/
343 void
gdk_beep(void)344 gdk_beep (void)
345 {
346   gdk_display_beep (gdk_display_get_default ());
347 }
348 
349 /**
350  * gdk_event_send_client_message:
351  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
352  * @winid:  the window to send the X ClientMessage event to.
353  *
354  * Sends an X ClientMessage event to a given window (which must be
355  * on the default #GdkDisplay.)
356  * This could be used for communicating between different applications,
357  * though the amount of data is limited to 20 bytes.
358  *
359  * Return value: non-zero on success.
360  **/
361 gboolean
gdk_event_send_client_message(GdkEvent * event,GdkNativeWindow winid)362 gdk_event_send_client_message (GdkEvent        *event,
363 			       GdkNativeWindow  winid)
364 {
365   g_return_val_if_fail (event != NULL, FALSE);
366 
367   return gdk_event_send_client_message_for_display (gdk_display_get_default (),
368 						    event, winid);
369 }
370 
371 /**
372  * gdk_event_send_clientmessage_toall:
373  * @event: the #GdkEvent to send, which should be a #GdkEventClient.
374  *
375  * Sends an X ClientMessage event to all toplevel windows on the default
376  * #GdkScreen.
377  *
378  * Toplevel windows are determined by checking for the WM_STATE property, as
379  * described in the Inter-Client Communication Conventions Manual (ICCCM).
380  * If no windows are found with the WM_STATE property set, the message is sent
381  * to all children of the root window.
382  **/
383 void
gdk_event_send_clientmessage_toall(GdkEvent * event)384 gdk_event_send_clientmessage_toall (GdkEvent *event)
385 {
386   g_return_if_fail (event != NULL);
387 
388   gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
389 }
390 
391 /**
392  * gdk_device_get_core_pointer:
393  *
394  * Returns the core pointer device for the default display.
395  *
396  * Return value: the core pointer device; this is owned by the
397  *   display and should not be freed.
398  **/
399 GdkDevice *
gdk_device_get_core_pointer(void)400 gdk_device_get_core_pointer (void)
401 {
402   return gdk_display_get_core_pointer (gdk_display_get_default ());
403 }
404 
405 /**
406  * gdk_display_get_core_pointer:
407  * @display: a #GdkDisplay
408  *
409  * Returns the core pointer device for the given display
410  *
411  * Return value: the core pointer device; this is owned by the
412  *   display and should not be freed.
413  *
414  * Since: 2.2
415  **/
416 GdkDevice *
gdk_display_get_core_pointer(GdkDisplay * display)417 gdk_display_get_core_pointer (GdkDisplay *display)
418 {
419   return display->core_pointer;
420 }
421 
422 /**
423  * gdk_set_sm_client_id:
424  * @sm_client_id: the client id assigned by the session manager when the
425  *    connection was opened, or %NULL to remove the property.
426  *
427  * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
428  * the window manager can save the application's state using the X11R6 ICCCM
429  * session management protocol.
430  *
431  * See the X Session Management Library documentation for more information on
432  * session management and the Inter-Client Communication Conventions Manual
433  * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
434  * (Both documents are part of the X Window System distribution.)
435  *
436  * Deprecated:2.24: Use gdk_x11_set_sm_client_id() instead
437  **/
438 void
gdk_set_sm_client_id(const gchar * sm_client_id)439 gdk_set_sm_client_id (const gchar* sm_client_id)
440 {
441   GSList *displays, *tmp_list;
442 
443   g_free (gdk_sm_client_id);
444   gdk_sm_client_id = g_strdup (sm_client_id);
445 
446   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
447   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
448     _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
449 
450   g_slist_free (displays);
451 }
452 
453 /**
454  * _gdk_get_sm_client_id:
455  *
456  * Gets the client ID set with gdk_set_sm_client_id(), if any.
457  *
458  * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
459  *               has never been called.
460  **/
461 const char *
_gdk_get_sm_client_id(void)462 _gdk_get_sm_client_id (void)
463 {
464   return gdk_sm_client_id;
465 }
466 
467 void
_gdk_display_enable_motion_hints(GdkDisplay * display)468 _gdk_display_enable_motion_hints (GdkDisplay *display)
469 {
470   gulong serial;
471 
472   if (display->pointer_info.motion_hint_serial != 0)
473     {
474       serial = _gdk_windowing_window_get_next_serial (display);
475       /* We might not actually generate the next request, so
476 	 make sure this triggers always, this may cause it to
477 	 trigger slightly too early, but this is just a hint
478 	 anyway. */
479       if (serial > 0)
480 	serial--;
481       if (serial < display->pointer_info.motion_hint_serial)
482 	display->pointer_info.motion_hint_serial = serial;
483     }
484 }
485 
486 /**
487  * gdk_display_get_pointer:
488  * @display: a #GdkDisplay
489  * @screen: (out) (allow-none): location to store the screen that the
490  *          cursor is on, or %NULL.
491  * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
492  * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
493  * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
494  *
495  * Gets the current location of the pointer and the current modifier
496  * mask for a given display.
497  *
498  * Since: 2.2
499  **/
500 void
gdk_display_get_pointer(GdkDisplay * display,GdkScreen ** screen,gint * x,gint * y,GdkModifierType * mask)501 gdk_display_get_pointer (GdkDisplay      *display,
502 			 GdkScreen      **screen,
503 			 gint            *x,
504 			 gint            *y,
505 			 GdkModifierType *mask)
506 {
507   GdkScreen *tmp_screen;
508   gint tmp_x, tmp_y;
509   GdkModifierType tmp_mask;
510 
511   g_return_if_fail (GDK_IS_DISPLAY (display));
512 
513   display->pointer_hooks->get_pointer (display, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
514 
515   if (screen)
516     *screen = tmp_screen;
517   if (x)
518     *x = tmp_x;
519   if (y)
520     *y = tmp_y;
521   if (mask)
522     *mask = tmp_mask;
523 }
524 
525 static GdkWindow *
gdk_display_real_get_window_at_pointer(GdkDisplay * display,gint * win_x,gint * win_y)526 gdk_display_real_get_window_at_pointer (GdkDisplay *display,
527                                         gint       *win_x,
528                                         gint       *win_y)
529 {
530   GdkWindow *window;
531   gint x, y;
532 
533   window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL, FALSE);
534 
535   /* This might need corrections, as the native window returned
536      may contain client side children */
537   if (window)
538     {
539       double xx, yy;
540 
541       window = _gdk_window_find_descendant_at (window,
542 					       x, y,
543 					       &xx, &yy);
544       x = floor (xx + 0.5);
545       y = floor (yy + 0.5);
546     }
547 
548   *win_x = x;
549   *win_y = y;
550 
551   return window;
552 }
553 
554 static GdkWindow *
gdk_window_real_window_get_pointer(GdkDisplay * display,GdkWindow * window,gint * x,gint * y,GdkModifierType * mask)555 gdk_window_real_window_get_pointer (GdkDisplay       *display,
556                                     GdkWindow        *window,
557                                     gint             *x,
558                                     gint             *y,
559                                     GdkModifierType  *mask)
560 {
561   GdkWindowObject *private;
562   gint tmpx, tmpy;
563   GdkModifierType tmp_mask;
564   gboolean normal_child;
565 
566   private = (GdkWindowObject *) window;
567 
568   normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_pointer (window,
569 									 &tmpx, &tmpy,
570 									 &tmp_mask);
571   /* We got the coords on the impl, convert to the window */
572   tmpx -= private->abs_x;
573   tmpy -= private->abs_y;
574 
575   if (x)
576     *x = tmpx;
577   if (y)
578     *y = tmpy;
579   if (mask)
580     *mask = tmp_mask;
581 
582   if (normal_child)
583     return _gdk_window_find_child_at (window, tmpx, tmpy);
584   return NULL;
585 }
586 
587 /**
588  * gdk_display_get_window_at_pointer:
589  * @display: a #GdkDisplay
590  * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
591  *    to the window origin, or %NULL
592  * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
593  &    to the window origin, or %NULL
594  *
595  * Obtains the window underneath the mouse pointer, returning the location
596  * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
597  * if the window under the mouse pointer is not known to GDK (for example,
598  * belongs to another application).
599  *
600  * Returns: (transfer none): the window under the mouse pointer, or %NULL
601  *
602  * Since: 2.2
603  **/
604 GdkWindow *
gdk_display_get_window_at_pointer(GdkDisplay * display,gint * win_x,gint * win_y)605 gdk_display_get_window_at_pointer (GdkDisplay *display,
606 				   gint       *win_x,
607 				   gint       *win_y)
608 {
609   gint tmp_x, tmp_y;
610   GdkWindow *window;
611 
612   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
613 
614   window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
615 
616   if (win_x)
617     *win_x = tmp_x;
618   if (win_y)
619     *win_y = tmp_y;
620 
621   return window;
622 }
623 
624 /**
625  * gdk_display_set_pointer_hooks:
626  * @display: a #GdkDisplay
627  * @new_hooks: a table of pointers to functions for getting
628  *   quantities related to the current pointer position,
629  *   or %NULL to restore the default table.
630  *
631  * This function allows for hooking into the operation
632  * of getting the current location of the pointer on a particular
633  * display. This is only useful for such low-level tools as an
634  * event recorder. Applications should never have any
635  * reason to use this facility.
636  *
637  * Return value: the previous pointer hook table
638  *
639  * Since: 2.2
640  *
641  * Deprecated: 2.24: This function will go away in GTK 3 for lack of use cases.
642  **/
643 GdkDisplayPointerHooks *
gdk_display_set_pointer_hooks(GdkDisplay * display,const GdkDisplayPointerHooks * new_hooks)644 gdk_display_set_pointer_hooks (GdkDisplay                   *display,
645 			       const GdkDisplayPointerHooks *new_hooks)
646 {
647   const GdkDisplayPointerHooks *result;
648 
649   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
650   result = display->pointer_hooks;
651 
652   if (new_hooks)
653     display->pointer_hooks = new_hooks;
654   else
655     display->pointer_hooks = &default_pointer_hooks;
656 
657   return (GdkDisplayPointerHooks *)result;
658 }
659 
660 static void
singlehead_get_pointer(GdkDisplay * display,GdkScreen ** screen,gint * x,gint * y,GdkModifierType * mask)661 singlehead_get_pointer (GdkDisplay       *display,
662 			GdkScreen       **screen,
663 			gint             *x,
664 			gint             *y,
665 			GdkModifierType  *mask)
666 {
667   GdkScreen *default_screen = gdk_display_get_default_screen (display);
668   GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
669 
670   *screen = default_screen;
671 
672   singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
673 }
674 
675 static GdkWindow*
singlehead_window_get_pointer(GdkDisplay * display,GdkWindow * window,gint * x,gint * y,GdkModifierType * mask)676 singlehead_window_get_pointer (GdkDisplay       *display,
677 			       GdkWindow        *window,
678 			       gint             *x,
679 			       gint             *y,
680 			       GdkModifierType  *mask)
681 {
682   return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
683 }
684 
685 static GdkWindow*
singlehead_window_at_pointer(GdkDisplay * display,gint * win_x,gint * win_y)686 singlehead_window_at_pointer   (GdkDisplay *display,
687 				gint       *win_x,
688 				gint       *win_y)
689 {
690   GdkScreen *default_screen = gdk_display_get_default_screen (display);
691 
692   return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
693 							      win_x, win_y);
694 }
695 
696 static GdkWindow*
singlehead_default_window_get_pointer(GdkWindow * window,gint * x,gint * y,GdkModifierType * mask)697 singlehead_default_window_get_pointer (GdkWindow       *window,
698 				       gint            *x,
699 				       gint            *y,
700 				       GdkModifierType *mask)
701 {
702   return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
703                                              window, x, y, mask);
704 }
705 
706 static GdkWindow*
singlehead_default_window_at_pointer(GdkScreen * screen,gint * win_x,gint * win_y)707 singlehead_default_window_at_pointer  (GdkScreen       *screen,
708 				       gint            *win_x,
709 				       gint            *win_y)
710 {
711   return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
712                                                  win_x, win_y);
713 }
714 
715 /**
716  * gdk_set_pointer_hooks:
717  * @new_hooks: a table of pointers to functions for getting
718  *   quantities related to the current pointer position,
719  *   or %NULL to restore the default table.
720  *
721  * This function allows for hooking into the operation
722  * of getting the current location of the pointer. This
723  * is only useful for such low-level tools as an
724  * event recorder. Applications should never have any
725  * reason to use this facility.
726  *
727  * This function is not multihead safe. For multihead operation,
728  * see gdk_display_set_pointer_hooks().
729  *
730  * Return value: the previous pointer hook table
731  *
732  * Deprecated: 2.24: This function will go away in GTK 3 for lack of use cases.
733  **/
734 GdkPointerHooks *
gdk_set_pointer_hooks(const GdkPointerHooks * new_hooks)735 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
736 {
737   const GdkPointerHooks *result = singlehead_current_pointer_hooks;
738 
739   if (new_hooks)
740     singlehead_current_pointer_hooks = new_hooks;
741   else
742     singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
743 
744   gdk_display_set_pointer_hooks (gdk_display_get_default (),
745 				 &singlehead_pointer_hooks);
746 
747   return (GdkPointerHooks *)result;
748 }
749 
750 static void
generate_grab_broken_event(GdkWindow * window,gboolean keyboard,gboolean implicit,GdkWindow * grab_window)751 generate_grab_broken_event (GdkWindow *window,
752 			    gboolean   keyboard,
753 			    gboolean   implicit,
754 			    GdkWindow *grab_window)
755 {
756   g_return_if_fail (window != NULL);
757 
758   if (!GDK_WINDOW_DESTROYED (window))
759     {
760       GdkEvent event;
761       event.type = GDK_GRAB_BROKEN;
762       event.grab_broken.window = window;
763       event.grab_broken.send_event = 0;
764       event.grab_broken.keyboard = keyboard;
765       event.grab_broken.implicit = implicit;
766       event.grab_broken.grab_window = grab_window;
767       gdk_event_put (&event);
768     }
769 }
770 
771 GdkPointerGrabInfo *
_gdk_display_get_last_pointer_grab(GdkDisplay * display)772 _gdk_display_get_last_pointer_grab (GdkDisplay *display)
773 {
774   GList *l;
775 
776   l = g_list_last (display->pointer_grabs);
777 
778   if (l == NULL)
779     return NULL;
780   else
781     return (GdkPointerGrabInfo *)l->data;
782 }
783 
784 
785 GdkPointerGrabInfo *
_gdk_display_add_pointer_grab(GdkDisplay * display,GdkWindow * window,GdkWindow * native_window,gboolean owner_events,GdkEventMask event_mask,unsigned long serial_start,guint32 time,gboolean implicit)786 _gdk_display_add_pointer_grab (GdkDisplay *display,
787 			       GdkWindow *window,
788 			       GdkWindow *native_window,
789 			       gboolean owner_events,
790 			       GdkEventMask event_mask,
791 			       unsigned long serial_start,
792 			       guint32 time,
793 			       gboolean implicit)
794 {
795   GdkPointerGrabInfo *info, *other_info;
796   GList *l;
797 
798   info = g_new0 (GdkPointerGrabInfo, 1);
799 
800   info->window = g_object_ref (window);
801   info->native_window = g_object_ref (native_window);
802   info->serial_start = serial_start;
803   info->serial_end = G_MAXULONG;
804   info->owner_events = owner_events;
805   info->event_mask = event_mask;
806   info->time = time;
807   info->implicit = implicit;
808 
809   /* Find the first grab that has a larger start time (if any) and insert
810    * before that. I.E we insert after already existing grabs with same
811    * start time */
812   for (l = display->pointer_grabs; l != NULL; l = l->next)
813     {
814       other_info = l->data;
815 
816       if (info->serial_start < other_info->serial_start)
817 	break;
818     }
819   display->pointer_grabs =
820     g_list_insert_before (display->pointer_grabs, l, info);
821 
822   /* Make sure the new grab end before next grab */
823   if (l)
824     {
825       other_info = l->data;
826       info->serial_end = other_info->serial_start;
827     }
828 
829   /* Find any previous grab and update its end time */
830   l = g_list_find  (display->pointer_grabs, info);
831   l = l->prev;
832   if (l)
833     {
834       other_info = l->data;
835       other_info->serial_end = serial_start;
836     }
837 
838   return info;
839 }
840 
841 static void
free_pointer_grab(GdkPointerGrabInfo * info)842 free_pointer_grab (GdkPointerGrabInfo *info)
843 {
844   g_object_unref (info->window);
845   g_object_unref (info->native_window);
846   g_free (info);
847 }
848 
849 /* _gdk_synthesize_crossing_events only works inside one toplevel.
850    This function splits things into two calls if needed, converting the
851    coordinates to the right toplevel */
852 static void
synthesize_crossing_events(GdkDisplay * display,GdkWindow * src_window,GdkWindow * dest_window,GdkCrossingMode crossing_mode,guint32 time,gulong serial)853 synthesize_crossing_events (GdkDisplay *display,
854 			    GdkWindow *src_window,
855 			    GdkWindow *dest_window,
856 			    GdkCrossingMode crossing_mode,
857 			    guint32 time,
858 			    gulong serial)
859 {
860   GdkWindow *src_toplevel, *dest_toplevel;
861   GdkModifierType state;
862   int x, y;
863 
864   /* We use the native crossing events if all native */
865   if (_gdk_native_windows)
866     return;
867 
868   if (src_window)
869     src_toplevel = gdk_window_get_toplevel (src_window);
870   else
871     src_toplevel = NULL;
872   if (dest_window)
873     dest_toplevel = gdk_window_get_toplevel (dest_window);
874   else
875     dest_toplevel = NULL;
876 
877   if (src_toplevel == NULL && dest_toplevel == NULL)
878     return;
879 
880   if (src_toplevel == NULL ||
881       src_toplevel == dest_toplevel)
882     {
883       /* Same toplevels */
884       gdk_window_get_pointer (dest_toplevel,
885 			      &x, &y, &state);
886       _gdk_synthesize_crossing_events (display,
887 				       src_window,
888 				       dest_window,
889 				       crossing_mode,
890 				       x, y, state,
891 				       time,
892 				       NULL,
893 				       serial, FALSE);
894     }
895   else if (dest_toplevel == NULL)
896     {
897       gdk_window_get_pointer (src_toplevel,
898 			      &x, &y, &state);
899       _gdk_synthesize_crossing_events (display,
900 				       src_window,
901 				       NULL,
902 				       crossing_mode,
903 				       x, y, state,
904 				       time,
905 				       NULL,
906 				       serial, FALSE);
907     }
908   else
909     {
910       /* Different toplevels */
911       gdk_window_get_pointer (src_toplevel,
912 			      &x, &y, &state);
913       _gdk_synthesize_crossing_events (display,
914 				       src_window,
915 				       NULL,
916 				       crossing_mode,
917 				       x, y, state,
918 				       time,
919 				       NULL,
920 				       serial, FALSE);
921       gdk_window_get_pointer (dest_toplevel,
922 			      &x, &y, &state);
923       _gdk_synthesize_crossing_events (display,
924 				       NULL,
925 				       dest_window,
926 				       crossing_mode,
927 				       x, y, state,
928 				       time,
929 				       NULL,
930 				       serial, FALSE);
931     }
932 }
933 
934 static GdkWindow *
get_current_toplevel(GdkDisplay * display,int * x_out,int * y_out,GdkModifierType * state_out)935 get_current_toplevel (GdkDisplay *display,
936 		      int *x_out, int *y_out,
937 		      GdkModifierType *state_out)
938 {
939   GdkWindow *pointer_window;
940   int x, y;
941   GdkModifierType state;
942 
943   pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state, TRUE);
944   if (pointer_window != NULL &&
945       (GDK_WINDOW_DESTROYED (pointer_window) ||
946        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
947        GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
948     pointer_window = NULL;
949 
950   *x_out = x;
951   *y_out = y;
952   *state_out = state;
953   return pointer_window;
954 }
955 
956 static void
switch_to_pointer_grab(GdkDisplay * display,GdkPointerGrabInfo * grab,GdkPointerGrabInfo * last_grab,guint32 time,gulong serial)957 switch_to_pointer_grab (GdkDisplay *display,
958 			GdkPointerGrabInfo *grab,
959 			GdkPointerGrabInfo *last_grab,
960 			guint32 time,
961 			gulong serial)
962 {
963   GdkWindow *src_window, *pointer_window, *new_toplevel;
964   GList *old_grabs;
965   GdkModifierType state;
966   int x, y;
967 
968   /* Temporarily unset pointer to make sure we send the crossing events below */
969   old_grabs = display->pointer_grabs;
970   display->pointer_grabs = NULL;
971 
972   if (grab)
973     {
974       /* New grab is in effect */
975 
976       /* We need to generate crossing events for the grab.
977        * However, there are never any crossing events for implicit grabs
978        * TODO: ... Actually, this could happen if the pointer window
979        *           doesn't have button mask so a parent gets the event...
980        */
981       if (!grab->implicit)
982 	{
983 	  /* We send GRAB crossing events from the window under the pointer to the
984 	     grab window. Except if there is an old grab then we start from that */
985 	  if (last_grab)
986 	    src_window = last_grab->window;
987 	  else
988 	    src_window = display->pointer_info.window_under_pointer;
989 
990 	  if (src_window != grab->window)
991 	    {
992 	      synthesize_crossing_events (display,
993 					  src_window, grab->window,
994 					  GDK_CROSSING_GRAB, time, serial);
995 	    }
996 
997 	  /* !owner_event Grabbing a window that we're not inside, current status is
998 	     now NULL (i.e. outside grabbed window) */
999 	  if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
1000 	    _gdk_display_set_window_under_pointer (display, NULL);
1001 	}
1002 
1003       grab->activated = TRUE;
1004     }
1005 
1006   if (last_grab)
1007     {
1008       new_toplevel = NULL;
1009 
1010       if (grab == NULL /* ungrab */ ||
1011 	  (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1012 	{
1013 	  /* We force check what window we're in, and update the toplevel_under_pointer info,
1014 	   * as that won't get told of this change with toplevel enter events.
1015 	   */
1016 	  if (display->pointer_info.toplevel_under_pointer)
1017 	    g_object_unref (display->pointer_info.toplevel_under_pointer);
1018 	  display->pointer_info.toplevel_under_pointer = NULL;
1019 
1020 	  new_toplevel = get_current_toplevel (display, &x, &y, &state);
1021 	  if (new_toplevel)
1022 	    {
1023 	      /* w is now toplevel and x,y in toplevel coords */
1024 	      display->pointer_info.toplevel_under_pointer = g_object_ref (new_toplevel);
1025 	      display->pointer_info.toplevel_x = x;
1026 	      display->pointer_info.toplevel_y = y;
1027 	      display->pointer_info.state = state;
1028 	    }
1029 	}
1030 
1031       if (grab == NULL) /* Ungrabbed, send events */
1032 	{
1033 	  pointer_window = NULL;
1034 	  if (new_toplevel)
1035 	    {
1036 	      /* Find (possibly virtual) child window */
1037 	      pointer_window =
1038 		_gdk_window_find_descendant_at (new_toplevel,
1039 						x, y,
1040 						NULL, NULL);
1041 	    }
1042 
1043 	  if (pointer_window != last_grab->window)
1044 	    synthesize_crossing_events (display,
1045 					last_grab->window, pointer_window,
1046 					GDK_CROSSING_UNGRAB, time, serial);
1047 
1048 	  /* We're now ungrabbed, update the window_under_pointer */
1049 	  _gdk_display_set_window_under_pointer (display, pointer_window);
1050 	}
1051     }
1052 
1053   display->pointer_grabs = old_grabs;
1054 
1055 }
1056 
1057 void
_gdk_display_pointer_grab_update(GdkDisplay * display,gulong current_serial)1058 _gdk_display_pointer_grab_update (GdkDisplay *display,
1059 				  gulong current_serial)
1060 {
1061   GdkPointerGrabInfo *current_grab, *next_grab;
1062   guint32 time;
1063 
1064   time = display->last_event_time;
1065 
1066   while (display->pointer_grabs != NULL)
1067     {
1068       current_grab = display->pointer_grabs->data;
1069 
1070       if (current_grab->serial_start > current_serial)
1071 	return; /* Hasn't started yet */
1072 
1073       if (current_grab->serial_end > current_serial)
1074 	{
1075 	  /* This one hasn't ended yet.
1076 	     its the currently active one or scheduled to be active */
1077 
1078 	  if (!current_grab->activated)
1079 	    switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
1080 
1081 	  break;
1082 	}
1083 
1084 
1085       next_grab = NULL;
1086       if (display->pointer_grabs->next)
1087 	{
1088 	  /* This is the next active grab */
1089 	  next_grab = display->pointer_grabs->next->data;
1090 
1091 	  if (next_grab->serial_start > current_serial)
1092 	    next_grab = NULL; /* Actually its not yet active */
1093 	}
1094 
1095       if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1096 	  (next_grab != NULL && current_grab->window != next_grab->window))
1097 	generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1098 				    FALSE, current_grab->implicit,
1099 				    next_grab? next_grab->window : NULL);
1100 
1101       /* Remove old grab */
1102       display->pointer_grabs =
1103 	g_list_delete_link (display->pointer_grabs,
1104 			    display->pointer_grabs);
1105 
1106       switch_to_pointer_grab (display,
1107 			      next_grab, current_grab,
1108 			      time, current_serial);
1109 
1110       free_pointer_grab (current_grab);
1111     }
1112 }
1113 
1114 static GList *
find_pointer_grab(GdkDisplay * display,gulong serial)1115 find_pointer_grab (GdkDisplay *display,
1116 		   gulong serial)
1117 {
1118   GdkPointerGrabInfo *grab;
1119   GList *l;
1120 
1121   for (l = display->pointer_grabs; l != NULL; l = l->next)
1122     {
1123       grab = l->data;
1124 
1125       if (serial >= grab->serial_start && serial < grab->serial_end)
1126 	return l;
1127     }
1128 
1129   return NULL;
1130 }
1131 
1132 
1133 
1134 GdkPointerGrabInfo *
_gdk_display_has_pointer_grab(GdkDisplay * display,gulong serial)1135 _gdk_display_has_pointer_grab (GdkDisplay *display,
1136 			       gulong serial)
1137 {
1138   GList *l;
1139 
1140   l = find_pointer_grab (display, serial);
1141   if (l)
1142     return l->data;
1143 
1144   return NULL;
1145 }
1146 
1147 /* Returns true if last grab was ended
1148  * If if_child is non-NULL, end the grab only if the grabbed
1149  * window is the same as if_child or a descendant of it */
1150 gboolean
_gdk_display_end_pointer_grab(GdkDisplay * display,gulong serial,GdkWindow * if_child,gboolean implicit)1151 _gdk_display_end_pointer_grab (GdkDisplay *display,
1152 			       gulong serial,
1153 			       GdkWindow *if_child,
1154 			       gboolean implicit)
1155 {
1156   GdkPointerGrabInfo *grab;
1157   GList *l;
1158 
1159   l = find_pointer_grab (display, serial);
1160 
1161   if (l == NULL)
1162     return FALSE;
1163 
1164   grab = l->data;
1165   if (grab &&
1166       (if_child == NULL ||
1167        _gdk_window_event_parent_of (if_child, grab->window)))
1168     {
1169       grab->serial_end = serial;
1170       grab->implicit_ungrab = implicit;
1171       return l->next == NULL;
1172     }
1173 
1174   return FALSE;
1175 }
1176 
1177 void
_gdk_display_set_has_keyboard_grab(GdkDisplay * display,GdkWindow * window,GdkWindow * native_window,gboolean owner_events,unsigned long serial,guint32 time)1178 _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
1179 				    GdkWindow *window,
1180 				    GdkWindow *native_window,
1181 				    gboolean owner_events,
1182 				    unsigned long serial,
1183 				    guint32 time)
1184 {
1185   if (display->keyboard_grab.window != NULL &&
1186       display->keyboard_grab.window != window)
1187     generate_grab_broken_event (display->keyboard_grab.window,
1188 				TRUE, FALSE, window);
1189 
1190   display->keyboard_grab.window = window;
1191   display->keyboard_grab.native_window = native_window;
1192   display->keyboard_grab.owner_events = owner_events;
1193   display->keyboard_grab.serial = serial;
1194   display->keyboard_grab.time = time;
1195 }
1196 
1197 void
_gdk_display_unset_has_keyboard_grab(GdkDisplay * display,gboolean implicit)1198 _gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
1199 				      gboolean implicit)
1200 {
1201   if (implicit)
1202     generate_grab_broken_event (display->keyboard_grab.window,
1203 				TRUE, FALSE, NULL);
1204   display->keyboard_grab.window = NULL;
1205 }
1206 
1207 /**
1208  * gdk_keyboard_grab_info_libgtk_only:
1209  * @display: the display for which to get the grab information
1210  * @grab_window: location to store current grab window
1211  * @owner_events: location to store boolean indicating whether
1212  *   the @owner_events flag to gdk_keyboard_grab() was %TRUE.
1213  *
1214  * Determines information about the current keyboard grab.
1215  * This is not public API and must not be used by applications.
1216  *
1217  * Return value: %TRUE if this application currently has the
1218  *  keyboard grabbed.
1219  **/
1220 gboolean
gdk_keyboard_grab_info_libgtk_only(GdkDisplay * display,GdkWindow ** grab_window,gboolean * owner_events)1221 gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1222 				    GdkWindow **grab_window,
1223 				    gboolean   *owner_events)
1224 {
1225   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1226 
1227   if (display->keyboard_grab.window)
1228     {
1229       if (grab_window)
1230         *grab_window = display->keyboard_grab.window;
1231       if (owner_events)
1232         *owner_events = display->keyboard_grab.owner_events;
1233 
1234       return TRUE;
1235     }
1236   else
1237     return FALSE;
1238 }
1239 
1240 /**
1241  * gdk_pointer_grab_info_libgtk_only:
1242  * @display: the #GdkDisplay for which to get the grab information
1243  * @grab_window: location to store current grab window
1244  * @owner_events: location to store boolean indicating whether
1245  *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
1246  *
1247  * Determines information about the current pointer grab.
1248  * This is not public API and must not be used by applications.
1249  *
1250  * Return value: %TRUE if this application currently has the
1251  *  pointer grabbed.
1252  **/
1253 gboolean
gdk_pointer_grab_info_libgtk_only(GdkDisplay * display,GdkWindow ** grab_window,gboolean * owner_events)1254 gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
1255 				   GdkWindow **grab_window,
1256 				   gboolean   *owner_events)
1257 {
1258   GdkPointerGrabInfo *info;
1259 
1260   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1261 
1262   /* What we're interested in is the steady state (ie last grab),
1263      because we're interested e.g. if we grabbed so that we
1264      can ungrab, even if our grab is not active just yet. */
1265   info = _gdk_display_get_last_pointer_grab (display);
1266 
1267   if (info)
1268     {
1269       if (grab_window)
1270         *grab_window = info->window;
1271       if (owner_events)
1272         *owner_events = info->owner_events;
1273 
1274       return TRUE;
1275     }
1276   else
1277     return FALSE;
1278 }
1279 
1280 
1281 /**
1282  * gdk_display_pointer_is_grabbed:
1283  * @display: a #GdkDisplay
1284  *
1285  * Test if the pointer is grabbed.
1286  *
1287  * Returns: %TRUE if an active X pointer grab is in effect
1288  *
1289  * Since: 2.2
1290  */
1291 gboolean
gdk_display_pointer_is_grabbed(GdkDisplay * display)1292 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1293 {
1294   GdkPointerGrabInfo *info;
1295 
1296   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1297 
1298   /* What we're interested in is the steady state (ie last grab),
1299      because we're interested e.g. if we grabbed so that we
1300      can ungrab, even if our grab is not active just yet. */
1301   info = _gdk_display_get_last_pointer_grab (display);
1302 
1303   return (info && !info->implicit);
1304 }
1305 
1306 #define __GDK_DISPLAY_C__
1307 #include "gdkaliasdef.c"
1308