1 /* GDK - The GIMP Drawing Kit
4 * Copyright 2001 Sun Microsystems Inc.
6 * Erwann Chenede <erwann.chenede@sun.com>
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.
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.
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.
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"
41 static void gdk_display_dispose (GObject *object);
42 static void gdk_display_finalize (GObject *object);
44 static void multihead_get_device_state (GdkDisplay *display,
49 GdkModifierType *mask);
50 static GdkWindow * multihead_window_get_device_position (GdkDisplay *display,
55 GdkModifierType *mask);
56 static GdkWindow * multihead_window_at_device_position (GdkDisplay *display,
61 static void multihead_default_get_pointer (GdkDisplay *display,
65 GdkModifierType *mask);
66 static GdkWindow * multihead_default_window_get_pointer (GdkDisplay *display,
70 GdkModifierType *mask);
71 static GdkWindow * multihead_default_window_at_pointer (GdkDisplay *display,
76 static void singlehead_get_pointer (GdkDisplay *display,
80 GdkModifierType *mask);
81 static GdkWindow* singlehead_window_get_pointer (GdkDisplay *display,
85 GdkModifierType *mask);
86 static GdkWindow* singlehead_window_at_pointer (GdkDisplay *display,
90 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow *window,
93 GdkModifierType *mask);
94 static GdkWindow* singlehead_default_window_at_pointer (GdkScreen *screen,
97 static GdkWindow *gdk_window_real_window_get_device_position (GdkDisplay *display,
102 GdkModifierType *mask);
103 static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay *display,
108 static guint signals[LAST_SIGNAL] = { 0 };
110 static char *gdk_sm_client_id;
112 static const GdkDisplayDeviceHooks default_device_hooks = {
113 _gdk_windowing_get_device_state,
114 gdk_window_real_window_get_device_position,
115 gdk_display_real_get_window_at_device_position
118 static const GdkDisplayDeviceHooks multihead_pointer_hooks = {
119 multihead_get_device_state,
120 multihead_window_get_device_position,
121 multihead_window_at_device_position
124 static const GdkDisplayPointerHooks multihead_default_pointer_hooks = {
125 multihead_default_get_pointer,
126 multihead_default_window_get_pointer,
127 multihead_default_window_at_pointer
130 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
131 singlehead_get_pointer,
132 singlehead_window_get_pointer,
133 singlehead_window_at_pointer
136 static const GdkPointerHooks singlehead_default_pointer_hooks = {
137 singlehead_default_window_get_pointer,
138 singlehead_default_window_at_pointer
141 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
142 static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
144 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
147 gdk_display_class_init (GdkDisplayClass *class)
149 GObjectClass *object_class = G_OBJECT_CLASS (class);
151 object_class->finalize = gdk_display_finalize;
152 object_class->dispose = gdk_display_dispose;
155 * GdkDisplay::opened:
156 * @display: the object on which the signal is emitted
158 * The ::opened signal is emitted when the connection to the windowing
159 * system for @display is opened.
162 g_signal_new (g_intern_static_string ("opened"),
163 G_OBJECT_CLASS_TYPE (object_class),
166 g_cclosure_marshal_VOID__VOID,
170 * GdkDisplay::closed:
171 * @display: the object on which the signal is emitted
172 * @is_error: %TRUE if the display was closed due to an error
174 * The ::closed signal is emitted when the connection to the windowing
175 * system for @display is closed.
180 g_signal_new (g_intern_static_string ("closed"),
181 G_OBJECT_CLASS_TYPE (object_class),
183 G_STRUCT_OFFSET (GdkDisplayClass, closed),
185 _gdk_marshal_VOID__BOOLEAN,
192 free_pointer_info (GdkPointerWindowInfo *info)
194 g_object_unref (info->toplevel_under_pointer);
195 g_slice_free (GdkPointerWindowInfo, info);
199 free_device_grab (GdkDeviceGrabInfo *info)
201 g_object_unref (info->window);
202 g_object_unref (info->native_window);
207 free_device_grabs_foreach (gpointer key,
213 g_list_foreach (list, (GFunc) free_device_grab, NULL);
220 device_removed_cb (GdkDeviceManager *device_manager,
224 g_hash_table_remove (display->multiple_click_info, device);
225 g_hash_table_remove (display->device_grabs, device);
226 g_hash_table_remove (display->pointers_info, device);
228 /* FIXME: change core pointer and remove from device list */
232 gdk_display_opened (GdkDisplay *display)
234 GdkDeviceManager *device_manager;
236 device_manager = gdk_display_get_device_manager (display);
238 g_signal_connect (device_manager, "device-removed",
239 G_CALLBACK (device_removed_cb), display);
243 gdk_display_init (GdkDisplay *display)
245 _gdk_displays = g_slist_prepend (_gdk_displays, display);
247 display->double_click_time = 250;
248 display->double_click_distance = 5;
250 display->device_hooks = &default_device_hooks;
252 display->device_grabs = g_hash_table_new (NULL, NULL);
253 display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
254 (GDestroyNotify) g_free);
256 display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
257 (GDestroyNotify) free_pointer_info);
259 display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
260 (GDestroyNotify) g_free);
262 g_signal_connect (display, "opened",
263 G_CALLBACK (gdk_display_opened), NULL);
267 gdk_display_dispose (GObject *object)
269 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
270 GdkDeviceManager *device_manager;
272 device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
274 g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
275 g_list_free (display->queued_events);
276 display->queued_events = NULL;
277 display->queued_tail = NULL;
279 _gdk_displays = g_slist_remove (_gdk_displays, object);
281 if (gdk_display_get_default() == display)
284 gdk_display_manager_set_default_display (gdk_display_manager_get(),
285 _gdk_displays->data);
287 gdk_display_manager_set_default_display (gdk_display_manager_get(),
292 g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, object);
294 G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
298 gdk_display_finalize (GObject *object)
300 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
302 g_hash_table_foreach_remove (display->device_grabs,
303 free_device_grabs_foreach,
305 g_hash_table_destroy (display->device_grabs);
307 g_hash_table_destroy (display->pointers_info);
308 g_hash_table_destroy (display->multiple_click_info);
310 if (display->device_manager)
311 g_object_unref (display->device_manager);
313 G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
318 * @display: a #GdkDisplay
320 * Closes the connection to the windowing system for the given display,
321 * and cleans up associated resources.
326 gdk_display_close (GdkDisplay *display)
328 g_return_if_fail (GDK_IS_DISPLAY (display));
330 if (!display->closed)
332 display->closed = TRUE;
334 g_signal_emit (display, signals[CLOSED], 0, FALSE);
335 g_object_run_dispose (G_OBJECT (display));
337 g_object_unref (display);
342 * gdk_display_is_closed:
343 * @display: a #GdkDisplay
345 * Finds out if the display has been closed.
347 * Returns: %TRUE if the display is closed.
352 gdk_display_is_closed (GdkDisplay *display)
354 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
356 return display->closed;
360 * gdk_display_get_event:
361 * @display: a #GdkDisplay
363 * Gets the next #GdkEvent to be processed for @display, fetching events from the
364 * windowing system if necessary.
366 * Return value: the next #GdkEvent to be processed, or %NULL if no events
367 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
372 gdk_display_get_event (GdkDisplay *display)
374 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
376 _gdk_events_queue (display);
377 return _gdk_event_unqueue (display);
381 * gdk_display_peek_event:
382 * @display: a #GdkDisplay
384 * Gets a copy of the first #GdkEvent in the @display's event queue, without
385 * removing the event from the queue. (Note that this function will
386 * not get more events from the windowing system. It only checks the events
387 * that have already been moved to the GDK event queue.)
389 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
390 * if no events are in the queue. The returned #GdkEvent should be freed with
396 gdk_display_peek_event (GdkDisplay *display)
400 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
402 tmp_list = _gdk_event_queue_find_first (display);
405 return gdk_event_copy (tmp_list->data);
411 * gdk_display_put_event:
412 * @display: a #GdkDisplay
413 * @event: a #GdkEvent.
415 * Appends a copy of the given event onto the front of the event
416 * queue for @display.
421 gdk_display_put_event (GdkDisplay *display,
422 const GdkEvent *event)
424 g_return_if_fail (GDK_IS_DISPLAY (display));
425 g_return_if_fail (event != NULL);
427 _gdk_event_queue_append (display, gdk_event_copy (event));
428 /* If the main loop is blocking in a different thread, wake it up */
429 g_main_context_wakeup (NULL);
433 * gdk_display_pointer_ungrab:
434 * @display: a #GdkDisplay.
435 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
437 * Release any pointer grab.
441 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
445 gdk_display_pointer_ungrab (GdkDisplay *display,
448 GdkDeviceManager *device_manager;
449 GList *devices, *dev;
452 g_return_if_fail (GDK_IS_DISPLAY (display));
454 device_manager = gdk_display_get_device_manager (display);
455 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
457 /* FIXME: Should this be generic to all backends? */
458 /* FIXME: What happens with extended devices? */
459 for (dev = devices; dev; dev = dev->next)
463 if (device->source != GDK_SOURCE_MOUSE)
466 gdk_device_ungrab (device, time_);
469 g_list_free (devices);
473 * gdk_pointer_ungrab:
474 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
475 * timestamp is available.
477 * Ungrabs the pointer on the default display, if it is grabbed by this
480 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
484 gdk_pointer_ungrab (guint32 time)
486 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
490 * gdk_pointer_is_grabbed:
492 * Returns %TRUE if the pointer on the default display is currently
493 * grabbed by this application.
495 * Note that this does not take the inmplicit pointer grab on button
496 * presses into account.
498 * Return value: %TRUE if the pointer is currently grabbed by this application.
500 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
503 gdk_pointer_is_grabbed (void)
505 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
509 * gdk_display_keyboard_ungrab:
510 * @display: a #GdkDisplay.
511 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
513 * Release any keyboard grab
517 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
521 gdk_display_keyboard_ungrab (GdkDisplay *display,
524 GdkDeviceManager *device_manager;
525 GList *devices, *dev;
528 g_return_if_fail (GDK_IS_DISPLAY (display));
530 device_manager = gdk_display_get_device_manager (display);
531 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
533 /* FIXME: Should this be generic to all backends? */
534 /* FIXME: What happens with extended devices? */
535 for (dev = devices; dev; dev = dev->next)
539 if (device->source != GDK_SOURCE_KEYBOARD)
542 gdk_device_ungrab (device, time);
545 g_list_free (devices);
549 * gdk_keyboard_ungrab:
550 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
551 * timestamp is available.
553 * Ungrabs the keyboard on the default display, if it is grabbed by this
556 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
560 gdk_keyboard_ungrab (guint32 time)
562 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
568 * Emits a short beep on the default display.
573 gdk_display_beep (gdk_display_get_default ());
577 * gdk_event_send_client_message:
578 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
579 * @winid: the window to send the X ClientMessage event to.
581 * Sends an X ClientMessage event to a given window (which must be
582 * on the default #GdkDisplay.)
583 * This could be used for communicating between different applications,
584 * though the amount of data is limited to 20 bytes.
586 * Return value: non-zero on success.
589 gdk_event_send_client_message (GdkEvent *event,
590 GdkNativeWindow winid)
592 g_return_val_if_fail (event != NULL, FALSE);
594 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
599 * gdk_event_send_clientmessage_toall:
600 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
602 * Sends an X ClientMessage event to all toplevel windows on the default
605 * Toplevel windows are determined by checking for the WM_STATE property, as
606 * described in the Inter-Client Communication Conventions Manual (ICCCM).
607 * If no windows are found with the WM_STATE property set, the message is sent
608 * to all children of the root window.
611 gdk_event_send_clientmessage_toall (GdkEvent *event)
613 g_return_if_fail (event != NULL);
615 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
619 * gdk_device_get_core_pointer:
621 * Returns the core pointer device for the default display.
623 * Return value: the core pointer device; this is owned by the
624 * display and should not be freed.
626 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
627 * gdk_event_get_device() if a #GdkEvent with pointer device
628 * information is available.
631 gdk_device_get_core_pointer (void)
633 return gdk_display_get_core_pointer (gdk_display_get_default ());
637 * gdk_display_get_core_pointer:
638 * @display: a #GdkDisplay
640 * Returns the core pointer device for the given display
642 * Return value: the core pointer device; this is owned by the
643 * display and should not be freed.
647 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
648 * gdk_event_get_device() if a #GdkEvent with device
649 * information is available.
652 gdk_display_get_core_pointer (GdkDisplay *display)
654 return display->core_pointer;
658 * gdk_set_sm_client_id:
659 * @sm_client_id: the client id assigned by the session manager when the
660 * connection was opened, or %NULL to remove the property.
662 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
663 * the window manager can save the application's state using the X11R6 ICCCM
664 * session management protocol.
666 * See the X Session Management Library documentation for more information on
667 * session management and the Inter-Client Communication Conventions Manual
668 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
669 * (Both documents are part of the X Window System distribution.)
672 gdk_set_sm_client_id (const gchar* sm_client_id)
674 GSList *displays, *tmp_list;
676 g_free (gdk_sm_client_id);
677 gdk_sm_client_id = g_strdup (sm_client_id);
679 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
680 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
681 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
683 g_slist_free (displays);
687 * _gdk_get_sm_client_id:
689 * Gets the client ID set with gdk_set_sm_client_id(), if any.
691 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
692 * has never been called.
695 _gdk_get_sm_client_id (void)
697 return gdk_sm_client_id;
701 _gdk_display_enable_motion_hints (GdkDisplay *display,
704 gulong *device_serial, serial;
706 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
710 device_serial = g_new0 (gulong, 1);
711 *device_serial = G_MAXULONG;
712 g_hash_table_insert (display->motion_hint_info, device, device_serial);
715 if (*device_serial != 0)
717 serial = _gdk_windowing_window_get_next_serial (display);
718 /* We might not actually generate the next request, so
719 make sure this triggers always, this may cause it to
720 trigger slightly too early, but this is just a hint
724 if (serial < *device_serial)
725 *device_serial = serial;
730 * gdk_display_get_device_state:
731 * @display: a #GdkDisplay.
732 * @device: device to query status to.
733 * @screen: location to store the #GdkScreen the @device is on, or %NULL.
734 * @x: location to store root window X coordinate of @device, or %NULL.
735 * @y: location to store root window Y coordinate of @device, or %NULL.
736 * @mask: location to store current modifier mask for @device, or %NULL.
738 * Gets the current location and state of @device for a given display.
743 gdk_display_get_device_state (GdkDisplay *display,
748 GdkModifierType *mask)
750 GdkScreen *tmp_screen;
752 GdkModifierType tmp_mask;
754 g_return_if_fail (GDK_IS_DISPLAY (display));
755 g_return_if_fail (GDK_IS_DEVICE (device));
757 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
760 *screen = tmp_screen;
770 * gdk_display_get_window_at_device_position:
771 * @display: a #GdkDisplay.
772 * @device: #GdkDevice to query info to.
773 * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
774 * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
776 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
777 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
779 * Returns: the #GdkWindow under the device position, or %NULL.
784 gdk_display_get_window_at_device_position (GdkDisplay *display,
792 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
793 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
795 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
806 * gdk_display_set_device_hooks:
807 * @display: a #GdkDisplay.
808 * @new_hooks: a table of pointers to functions for getting quantities related to all
809 * devices position, or %NULL to restore the default table.
811 * This function allows for hooking into the operation of getting the current location of any
812 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
813 * an event recorder. Applications should never have any reason to use this facility.
815 * Returns: The previous device hook table.
819 GdkDisplayDeviceHooks *
820 gdk_display_set_device_hooks (GdkDisplay *display,
821 const GdkDisplayDeviceHooks *new_hooks)
823 const GdkDisplayDeviceHooks *result;
825 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
826 result = display->device_hooks;
829 display->device_hooks = new_hooks;
831 display->device_hooks = &default_device_hooks;
833 return (GdkDisplayDeviceHooks *) result;
837 * gdk_display_get_pointer:
838 * @display: a #GdkDisplay
839 * @screen: (allow-none): location to store the screen that the
840 * cursor is on, or %NULL.
841 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
842 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
843 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
845 * Gets the current location of the pointer and the current modifier
846 * mask for a given display.
850 * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
853 gdk_display_get_pointer (GdkDisplay *display,
857 GdkModifierType *mask)
859 g_return_if_fail (GDK_IS_DISPLAY (display));
861 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
865 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
873 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
875 /* This might need corrections, as the native window returned
876 may contain client side children */
881 window = _gdk_window_find_descendant_at (window,
884 x = floor (xx + 0.5);
885 y = floor (yy + 0.5);
895 gdk_window_real_window_get_device_position (GdkDisplay *display,
900 GdkModifierType *mask)
902 GdkWindowObject *private;
904 GdkModifierType tmp_mask;
905 gboolean normal_child;
907 private = (GdkWindowObject *) window;
909 normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
913 /* We got the coords on the impl, convert to the window */
914 tmpx -= private->abs_x;
915 tmpy -= private->abs_y;
925 return _gdk_window_find_child_at (window, tmpx, tmpy);
930 * gdk_display_get_window_at_pointer:
931 * @display: a #GdkDisplay
932 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
933 * to the window origin, or %NULL
934 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
935 & to the window origin, or %NULL
937 * Obtains the window underneath the mouse pointer, returning the location
938 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
939 * if the window under the mouse pointer is not known to GDK (for example,
940 * belongs to another application).
942 * Returns: (transfer none): the window under the mouse pointer, or %NULL
946 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
949 gdk_display_get_window_at_pointer (GdkDisplay *display,
953 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
955 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
959 multihead_get_device_state (GdkDisplay *display,
964 GdkModifierType *mask)
966 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
970 multihead_window_get_device_position (GdkDisplay *display,
975 GdkModifierType *mask)
977 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
981 multihead_window_at_device_position (GdkDisplay *display,
986 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
990 multihead_default_get_pointer (GdkDisplay *display,
994 GdkModifierType *mask)
996 return _gdk_windowing_get_device_state (display,
997 display->core_pointer,
1002 multihead_default_window_get_pointer (GdkDisplay *display,
1006 GdkModifierType *mask)
1008 return gdk_window_real_window_get_device_position (display,
1009 display->core_pointer,
1010 window, x, y, mask);
1014 multihead_default_window_at_pointer (GdkDisplay *display,
1018 return gdk_display_real_get_window_at_device_position (display,
1019 display->core_pointer,
1024 * gdk_display_set_pointer_hooks:
1025 * @display: a #GdkDisplay
1026 * @new_hooks: a table of pointers to functions for getting
1027 * quantities related to the current pointer position,
1028 * or %NULL to restore the default table.
1030 * This function allows for hooking into the operation
1031 * of getting the current location of the pointer on a particular
1032 * display. This is only useful for such low-level tools as an
1033 * event recorder. Applications should never have any
1034 * reason to use this facility.
1036 * Return value: the previous pointer hook table
1040 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1042 GdkDisplayPointerHooks *
1043 gdk_display_set_pointer_hooks (GdkDisplay *display,
1044 const GdkDisplayPointerHooks *new_hooks)
1046 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1048 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1051 multihead_current_pointer_hooks = new_hooks;
1053 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1055 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1057 return (GdkDisplayPointerHooks *)result;
1061 singlehead_get_pointer (GdkDisplay *display,
1065 GdkModifierType *mask)
1067 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1068 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1070 *screen = default_screen;
1072 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1076 singlehead_window_get_pointer (GdkDisplay *display,
1080 GdkModifierType *mask)
1082 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1086 singlehead_window_at_pointer (GdkDisplay *display,
1090 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1092 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1097 singlehead_default_window_get_pointer (GdkWindow *window,
1100 GdkModifierType *mask)
1102 GdkDisplay *display;
1104 display = gdk_drawable_get_display (window);
1106 return gdk_window_real_window_get_device_position (display,
1107 display->core_pointer,
1108 window, x, y, mask);
1112 singlehead_default_window_at_pointer (GdkScreen *screen,
1116 GdkDisplay *display;
1118 display = gdk_screen_get_display (screen);
1120 return gdk_display_real_get_window_at_device_position (display,
1121 display->core_pointer,
1126 * gdk_set_pointer_hooks:
1127 * @new_hooks: a table of pointers to functions for getting
1128 * quantities related to the current pointer position,
1129 * or %NULL to restore the default table.
1131 * This function allows for hooking into the operation
1132 * of getting the current location of the pointer. This
1133 * is only useful for such low-level tools as an
1134 * event recorder. Applications should never have any
1135 * reason to use this facility.
1137 * This function is not multihead safe. For multihead operation,
1138 * see gdk_display_set_pointer_hooks().
1140 * Return value: the previous pointer hook table
1142 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1145 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1147 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1150 singlehead_current_pointer_hooks = new_hooks;
1152 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1154 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1155 &singlehead_pointer_hooks);
1157 return (GdkPointerHooks *)result;
1161 generate_grab_broken_event (GdkWindow *window,
1164 GdkWindow *grab_window)
1166 g_return_if_fail (window != NULL);
1168 if (!GDK_WINDOW_DESTROYED (window))
1172 event = gdk_event_new (GDK_GRAB_BROKEN);
1173 event->grab_broken.window = g_object_ref (window);
1174 event->grab_broken.send_event = FALSE;
1175 event->grab_broken.implicit = implicit;
1176 event->grab_broken.grab_window = grab_window;
1177 gdk_event_set_device (event, device);
1178 event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1180 gdk_event_put (event);
1181 gdk_event_free (event);
1186 _gdk_display_get_last_device_grab (GdkDisplay *display,
1191 l = g_hash_table_lookup (display->device_grabs, device);
1195 l = g_list_last (l);
1203 _gdk_display_add_device_grab (GdkDisplay *display,
1206 GdkWindow *native_window,
1207 GdkGrabOwnership grab_ownership,
1208 gboolean owner_events,
1209 GdkEventMask event_mask,
1210 unsigned long serial_start,
1214 GdkDeviceGrabInfo *info, *other_info;
1217 info = g_new0 (GdkDeviceGrabInfo, 1);
1219 info->window = g_object_ref (window);
1220 info->native_window = g_object_ref (native_window);
1221 info->serial_start = serial_start;
1222 info->serial_end = G_MAXULONG;
1223 info->owner_events = owner_events;
1224 info->event_mask = event_mask;
1226 info->implicit = implicit;
1227 info->ownership = grab_ownership;
1229 grabs = g_hash_table_lookup (display->device_grabs, device);
1231 /* Find the first grab that has a larger start time (if any) and insert
1232 * before that. I.E we insert after already existing grabs with same
1234 for (l = grabs; l != NULL; l = l->next)
1236 other_info = l->data;
1238 if (info->serial_start < other_info->serial_start)
1242 grabs = g_list_insert_before (grabs, l, info);
1244 /* Make sure the new grab end before next grab */
1247 other_info = l->data;
1248 info->serial_end = other_info->serial_start;
1251 /* Find any previous grab and update its end time */
1252 l = g_list_find (grabs, info);
1256 other_info = l->data;
1257 other_info->serial_end = serial_start;
1260 g_hash_table_insert (display->device_grabs, device, grabs);
1265 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1266 This function splits things into two calls if needed, converting the
1267 coordinates to the right toplevel */
1269 synthesize_crossing_events (GdkDisplay *display,
1271 GdkWindow *src_window,
1272 GdkWindow *dest_window,
1273 GdkCrossingMode crossing_mode,
1277 GdkWindow *src_toplevel, *dest_toplevel;
1278 GdkModifierType state;
1281 /* We use the native crossing events if all native */
1282 if (_gdk_native_windows)
1286 src_toplevel = gdk_window_get_toplevel (src_window);
1288 src_toplevel = NULL;
1290 dest_toplevel = gdk_window_get_toplevel (dest_window);
1292 dest_toplevel = NULL;
1294 if (src_toplevel == NULL && dest_toplevel == NULL)
1297 if (src_toplevel == NULL ||
1298 src_toplevel == dest_toplevel)
1300 /* Same toplevels */
1301 gdk_window_get_pointer (dest_toplevel,
1303 _gdk_synthesize_crossing_events (display,
1313 else if (dest_toplevel == NULL)
1315 gdk_window_get_pointer (src_toplevel,
1317 _gdk_synthesize_crossing_events (display,
1329 /* Different toplevels */
1330 gdk_window_get_pointer (src_toplevel,
1332 _gdk_synthesize_crossing_events (display,
1341 gdk_window_get_pointer (dest_toplevel,
1343 _gdk_synthesize_crossing_events (display,
1356 get_current_toplevel (GdkDisplay *display,
1360 GdkModifierType *state_out)
1362 GdkWindow *pointer_window;
1364 GdkModifierType state;
1366 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1368 if (pointer_window != NULL &&
1369 (GDK_WINDOW_DESTROYED (pointer_window) ||
1370 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1371 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1372 pointer_window = NULL;
1377 return pointer_window;
1381 switch_to_pointer_grab (GdkDisplay *display,
1383 GdkDeviceGrabInfo *grab,
1384 GdkDeviceGrabInfo *last_grab,
1388 GdkWindow *src_window, *pointer_window, *new_toplevel;
1389 GdkPointerWindowInfo *info;
1391 GdkModifierType state;
1394 /* Temporarily unset pointer to make sure we send the crossing events below */
1395 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1396 g_hash_table_steal (display->device_grabs, device);
1397 info = _gdk_display_get_pointer_info (display, device);
1401 /* New grab is in effect */
1403 /* We need to generate crossing events for the grab.
1404 * However, there are never any crossing events for implicit grabs
1405 * TODO: ... Actually, this could happen if the pointer window
1406 * doesn't have button mask so a parent gets the event...
1408 if (!grab->implicit)
1410 /* We send GRAB crossing events from the window under the pointer to the
1411 grab window. Except if there is an old grab then we start from that */
1413 src_window = last_grab->window;
1415 src_window = info->window_under_pointer;
1417 if (src_window != grab->window)
1418 synthesize_crossing_events (display, device,
1419 src_window, grab->window,
1420 GDK_CROSSING_GRAB, time, serial);
1422 /* !owner_event Grabbing a window that we're not inside, current status is
1423 now NULL (i.e. outside grabbed window) */
1424 if (!grab->owner_events && info->window_under_pointer != grab->window)
1425 _gdk_display_set_window_under_pointer (display, device, NULL);
1428 grab->activated = TRUE;
1433 new_toplevel = NULL;
1435 if (grab == NULL /* ungrab */ ||
1436 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1438 /* We force check what window we're in, and update the toplevel_under_pointer info,
1439 * as that won't get told of this change with toplevel enter events.
1441 if (info->toplevel_under_pointer)
1442 g_object_unref (info->toplevel_under_pointer);
1443 info->toplevel_under_pointer = NULL;
1445 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1448 /* w is now toplevel and x,y in toplevel coords */
1449 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1450 info->toplevel_x = x;
1451 info->toplevel_y = y;
1452 info->state = state;
1456 if (grab == NULL) /* Ungrabbed, send events */
1458 pointer_window = NULL;
1461 /* Find (possibly virtual) child window */
1463 _gdk_window_find_descendant_at (new_toplevel,
1468 if (pointer_window != last_grab->window)
1469 synthesize_crossing_events (display, device,
1470 last_grab->window, pointer_window,
1471 GDK_CROSSING_UNGRAB, time, serial);
1473 /* We're now ungrabbed, update the window_under_pointer */
1474 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1478 g_hash_table_insert (display->device_grabs, device, old_grabs);
1482 _gdk_display_device_grab_update (GdkDisplay *display,
1484 gulong current_serial)
1486 GdkDeviceGrabInfo *current_grab, *next_grab;
1490 time = display->last_event_time;
1491 grabs = g_hash_table_lookup (display->device_grabs, device);
1493 while (grabs != NULL)
1495 current_grab = grabs->data;
1497 if (current_grab->serial_start > current_serial)
1498 return; /* Hasn't started yet */
1500 if (current_grab->serial_end > current_serial)
1502 /* This one hasn't ended yet.
1503 its the currently active one or scheduled to be active */
1505 if (!current_grab->activated)
1507 if (device->source != GDK_SOURCE_KEYBOARD)
1508 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1517 /* This is the next active grab */
1518 next_grab = grabs->next->data;
1520 if (next_grab->serial_start > current_serial)
1521 next_grab = NULL; /* Actually its not yet active */
1524 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1525 (next_grab != NULL && current_grab->window != next_grab->window))
1526 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1528 current_grab->implicit,
1529 next_grab? next_grab->window : NULL);
1531 /* Remove old grab */
1532 grabs = g_list_delete_link (grabs, grabs);
1533 g_hash_table_insert (display->device_grabs, device, grabs);
1535 if (device->source != GDK_SOURCE_KEYBOARD)
1536 switch_to_pointer_grab (display, device,
1537 next_grab, current_grab,
1538 time, current_serial);
1540 free_device_grab (current_grab);
1545 grab_list_find (GList *grabs,
1548 GdkDeviceGrabInfo *grab;
1554 if (serial >= grab->serial_start && serial < grab->serial_end)
1557 grabs = grabs->next;
1564 find_device_grab (GdkDisplay *display,
1570 l = g_hash_table_lookup (display->device_grabs, device);
1571 return grab_list_find (l, serial);
1575 _gdk_display_has_device_grab (GdkDisplay *display,
1581 l = find_device_grab (display, device, serial);
1588 /* Returns true if last grab was ended
1589 * If if_child is non-NULL, end the grab only if the grabbed
1590 * window is the same as if_child or a descendant of it */
1592 _gdk_display_end_device_grab (GdkDisplay *display,
1595 GdkWindow *if_child,
1598 GdkDeviceGrabInfo *grab;
1601 l = find_device_grab (display, device, serial);
1608 (if_child == NULL ||
1609 _gdk_window_event_parent_of (if_child, grab->window)))
1611 grab->serial_end = serial;
1612 grab->implicit_ungrab = implicit;
1613 return l->next == NULL;
1619 /* Returns TRUE if device events are not blocked by any grab */
1621 _gdk_display_check_grab_ownership (GdkDisplay *display,
1625 GHashTableIter iter;
1626 gpointer key, value;
1627 GdkGrabOwnership higher_ownership, device_ownership;
1628 gboolean device_is_keyboard;
1630 g_hash_table_iter_init (&iter, display->device_grabs);
1631 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1632 device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1634 while (g_hash_table_iter_next (&iter, &key, &value))
1636 GdkDeviceGrabInfo *grab;
1642 grabs = grab_list_find (grabs, serial);
1647 /* Discard device if it's not of the same type */
1648 if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1649 (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1655 device_ownership = grab->ownership;
1658 if (grab->ownership > higher_ownership)
1659 higher_ownership = grab->ownership;
1663 if (higher_ownership > device_ownership)
1665 /* There's a higher priority ownership
1666 * going on for other device(s)
1674 GdkPointerWindowInfo *
1675 _gdk_display_get_pointer_info (GdkDisplay *display,
1678 GdkPointerWindowInfo *info;
1680 if (G_UNLIKELY (!device))
1683 info = g_hash_table_lookup (display->pointers_info, device);
1685 if (G_UNLIKELY (!info))
1687 info = g_slice_new0 (GdkPointerWindowInfo);
1688 g_hash_table_insert (display->pointers_info, device, info);
1695 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1696 GdkDisplayPointerInfoForeach func,
1699 GHashTableIter iter;
1700 gpointer key, value;
1702 g_hash_table_iter_init (&iter, display->pointers_info);
1704 while (g_hash_table_iter_next (&iter, &key, &value))
1706 GdkPointerWindowInfo *info = value;
1707 GdkDevice *device = key;
1709 (func) (display, device, info, user_data);
1714 * gdk_device_grab_info_libgtk_only:
1715 * @display: the display for which to get the grab information
1716 * @device: device to get the grab information from
1717 * @grab_window: location to store current grab window
1718 * @owner_events: location to store boolean indicating whether
1719 * the @owner_events flag to gdk_keyboard_grab() or
1720 * gdk_pointer_grab() was %TRUE.
1722 * Determines information about the current keyboard grab.
1723 * This is not public API and must not be used by applications.
1725 * Return value: %TRUE if this application currently has the
1729 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1731 GdkWindow **grab_window,
1732 gboolean *owner_events)
1734 GdkDeviceGrabInfo *info;
1736 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1737 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1739 info = _gdk_display_get_last_device_grab (display, device);
1744 *grab_window = info->window;
1746 *owner_events = info->owner_events;
1755 * gdk_display_pointer_is_grabbed:
1756 * @display: a #GdkDisplay
1758 * Test if the pointer is grabbed.
1760 * Returns: %TRUE if an active X pointer grab is in effect
1764 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1767 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1769 GdkDeviceManager *device_manager;
1770 GList *devices, *dev;
1773 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1775 device_manager = gdk_display_get_device_manager (display);
1776 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1778 for (dev = devices; dev; dev = dev->next)
1782 if (device->source == GDK_SOURCE_MOUSE &&
1783 gdk_display_device_is_grabbed (display, device))
1791 * gdk_display_device_is_grabbed:
1792 * @display: a #GdkDisplay
1793 * @device: a #GdkDevice
1795 * Returns %TRUE if there is an ongoing grab on @device for @display.
1797 * Returns: %TRUE if there is a grab in effect for @device.
1800 gdk_display_device_is_grabbed (GdkDisplay *display,
1803 GdkDeviceGrabInfo *info;
1805 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1806 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1808 /* What we're interested in is the steady state (ie last grab),
1809 because we're interested e.g. if we grabbed so that we
1810 can ungrab, even if our grab is not active just yet. */
1811 info = _gdk_display_get_last_device_grab (display, device);
1813 return (info && !info->implicit);
1817 * gdk_display_get_device_manager:
1818 * @display: a #GdkDisplay.
1820 * Returns the #GdkDeviceManager associated to @display.
1822 * Returns: A #GdkDeviceManager, or %NULL. This memory is
1823 * owned by GDK and must not be freed or unreferenced.
1828 gdk_display_get_device_manager (GdkDisplay *display)
1830 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1832 return display->device_manager;