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