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 * Returns %TRUE if the display is closed.
350 gdk_display_is_closed (GdkDisplay *display)
352 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
354 return display->closed;
358 * gdk_display_get_event:
359 * @display: a #GdkDisplay
361 * Gets the next #GdkEvent to be processed for @display, fetching events from the
362 * windowing system if necessary.
364 * Return value: the next #GdkEvent to be processed, or %NULL if no events
365 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
370 gdk_display_get_event (GdkDisplay *display)
372 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
374 _gdk_events_queue (display);
375 return _gdk_event_unqueue (display);
379 * gdk_display_peek_event:
380 * @display: a #GdkDisplay
382 * Gets a copy of the first #GdkEvent in the @display's event queue, without
383 * removing the event from the queue. (Note that this function will
384 * not get more events from the windowing system. It only checks the events
385 * that have already been moved to the GDK event queue.)
387 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
388 * if no events are in the queue. The returned #GdkEvent should be freed with
394 gdk_display_peek_event (GdkDisplay *display)
398 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
400 tmp_list = _gdk_event_queue_find_first (display);
403 return gdk_event_copy (tmp_list->data);
409 * gdk_display_put_event:
410 * @display: a #GdkDisplay
411 * @event: a #GdkEvent.
413 * Appends a copy of the given event onto the front of the event
414 * queue for @display.
419 gdk_display_put_event (GdkDisplay *display,
420 const GdkEvent *event)
422 g_return_if_fail (GDK_IS_DISPLAY (display));
423 g_return_if_fail (event != NULL);
425 _gdk_event_queue_append (display, gdk_event_copy (event));
426 /* If the main loop is blocking in a different thread, wake it up */
427 g_main_context_wakeup (NULL);
431 * gdk_display_pointer_ungrab:
432 * @display: a #GdkDisplay.
433 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
435 * Release any pointer grab.
439 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
443 gdk_display_pointer_ungrab (GdkDisplay *display,
446 GdkDeviceManager *device_manager;
447 GList *devices, *dev;
450 g_return_if_fail (GDK_IS_DISPLAY (display));
452 device_manager = gdk_display_get_device_manager (display);
453 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
455 /* FIXME: Should this be generic to all backends? */
456 /* FIXME: What happens with extended devices? */
457 for (dev = devices; dev; dev = dev->next)
461 if (device->source != GDK_SOURCE_MOUSE)
464 gdk_device_ungrab (device, time_);
467 g_list_free (devices);
471 * gdk_pointer_ungrab:
472 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
473 * timestamp is available.
475 * Ungrabs the pointer on the default display, if it is grabbed by this
478 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
482 gdk_pointer_ungrab (guint32 time)
484 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
488 * gdk_pointer_is_grabbed:
490 * Returns %TRUE if the pointer on the default display is currently
491 * grabbed by this application.
493 * Note that this does not take the inmplicit pointer grab on button
494 * presses into account.
496 * Return value: %TRUE if the pointer is currently grabbed by this application.
498 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
501 gdk_pointer_is_grabbed (void)
503 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
507 * gdk_display_keyboard_ungrab:
508 * @display: a #GdkDisplay.
509 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
511 * Release any keyboard grab
515 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
519 gdk_display_keyboard_ungrab (GdkDisplay *display,
522 GdkDeviceManager *device_manager;
523 GList *devices, *dev;
526 g_return_if_fail (GDK_IS_DISPLAY (display));
528 device_manager = gdk_display_get_device_manager (display);
529 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
531 /* FIXME: Should this be generic to all backends? */
532 /* FIXME: What happens with extended devices? */
533 for (dev = devices; dev; dev = dev->next)
537 if (device->source != GDK_SOURCE_KEYBOARD)
540 gdk_device_ungrab (device, time);
543 g_list_free (devices);
547 * gdk_keyboard_ungrab:
548 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
549 * timestamp is available.
551 * Ungrabs the keyboard on the default display, if it is grabbed by this
554 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
558 gdk_keyboard_ungrab (guint32 time)
560 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
566 * Emits a short beep on the default display.
571 gdk_display_beep (gdk_display_get_default ());
575 * gdk_event_send_client_message:
576 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
577 * @winid: the window to send the X ClientMessage event to.
579 * Sends an X ClientMessage event to a given window (which must be
580 * on the default #GdkDisplay.)
581 * This could be used for communicating between different applications,
582 * though the amount of data is limited to 20 bytes.
584 * Return value: non-zero on success.
587 gdk_event_send_client_message (GdkEvent *event,
588 GdkNativeWindow winid)
590 g_return_val_if_fail (event != NULL, FALSE);
592 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
597 * gdk_event_send_clientmessage_toall:
598 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
600 * Sends an X ClientMessage event to all toplevel windows on the default
603 * Toplevel windows are determined by checking for the WM_STATE property, as
604 * described in the Inter-Client Communication Conventions Manual (ICCCM).
605 * If no windows are found with the WM_STATE property set, the message is sent
606 * to all children of the root window.
609 gdk_event_send_clientmessage_toall (GdkEvent *event)
611 g_return_if_fail (event != NULL);
613 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
617 * gdk_device_get_core_pointer:
619 * Returns the core pointer device for the default display.
621 * Return value: the core pointer device; this is owned by the
622 * display and should not be freed.
624 * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
625 * gdk_event_get_device() if a #GdkEvent with pointer device
626 * information is available.
629 gdk_device_get_core_pointer (void)
631 return gdk_display_get_core_pointer (gdk_display_get_default ());
635 * gdk_display_get_core_pointer:
636 * @display: a #GdkDisplay
638 * Returns the core pointer device for the given display
640 * Return value: the core pointer device; this is owned by the
641 * display and should not be freed.
645 * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
646 * gdk_event_get_device() if a #GdkEvent with device
647 * information is available.
650 gdk_display_get_core_pointer (GdkDisplay *display)
652 return display->core_pointer;
656 * gdk_set_sm_client_id:
657 * @sm_client_id: the client id assigned by the session manager when the
658 * connection was opened, or %NULL to remove the property.
660 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
661 * the window manager can save the application's state using the X11R6 ICCCM
662 * session management protocol.
664 * See the X Session Management Library documentation for more information on
665 * session management and the Inter-Client Communication Conventions Manual
666 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
667 * (Both documents are part of the X Window System distribution.)
670 gdk_set_sm_client_id (const gchar* sm_client_id)
672 GSList *displays, *tmp_list;
674 g_free (gdk_sm_client_id);
675 gdk_sm_client_id = g_strdup (sm_client_id);
677 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
678 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
679 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
681 g_slist_free (displays);
685 * _gdk_get_sm_client_id:
687 * Gets the client ID set with gdk_set_sm_client_id(), if any.
689 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
690 * has never been called.
693 _gdk_get_sm_client_id (void)
695 return gdk_sm_client_id;
699 _gdk_display_enable_motion_hints (GdkDisplay *display,
702 gulong *device_serial, serial;
704 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
708 device_serial = g_new0 (gulong, 1);
709 *device_serial = G_MAXULONG;
710 g_hash_table_insert (display->motion_hint_info, device, device_serial);
713 if (*device_serial != 0)
715 serial = _gdk_windowing_window_get_next_serial (display);
716 /* We might not actually generate the next request, so
717 make sure this triggers always, this may cause it to
718 trigger slightly too early, but this is just a hint
722 if (serial < *device_serial)
723 *device_serial = serial;
728 * gdk_display_get_device_state:
729 * @display: a #GdkDisplay.
730 * @device: device to query status to.
731 * @screen: location to store the #GdkScreen the @device is on, or %NULL.
732 * @x: location to store root window X coordinate of @device, or %NULL.
733 * @y: location to store root window Y coordinate of @device, or %NULL.
734 * @mask: location to store current modifier mask for @device, or %NULL.
736 * Gets the current location and state of @device for a given display.
741 gdk_display_get_device_state (GdkDisplay *display,
746 GdkModifierType *mask)
748 GdkScreen *tmp_screen;
750 GdkModifierType tmp_mask;
752 g_return_if_fail (GDK_IS_DISPLAY (display));
753 g_return_if_fail (GDK_IS_DEVICE (device));
755 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
758 *screen = tmp_screen;
768 * gdk_display_get_window_at_device_position:
769 * @display: a #GdkDisplay.
770 * @device: #GdkDevice to query info to.
771 * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
772 * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
774 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
775 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
777 * Returns: the #GdkWindow under the device position, or %NULL.
782 gdk_display_get_window_at_device_position (GdkDisplay *display,
790 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
791 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
793 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
804 * gdk_display_set_device_hooks:
805 * @display: a #GdkDisplay.
806 * @new_hooks: a table of pointers to functions for getting quantities related to all
807 * devices position, or %NULL to restore the default table.
809 * This function allows for hooking into the operation of getting the current location of any
810 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
811 * an event recorder. Applications should never have any reason to use this facility.
813 * Returns: The previous device hook table.
817 GdkDisplayDeviceHooks *
818 gdk_display_set_device_hooks (GdkDisplay *display,
819 const GdkDisplayDeviceHooks *new_hooks)
821 const GdkDisplayDeviceHooks *result;
823 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
824 result = display->device_hooks;
827 display->device_hooks = new_hooks;
829 display->device_hooks = &default_device_hooks;
831 return (GdkDisplayDeviceHooks *) result;
835 * gdk_display_get_pointer:
836 * @display: a #GdkDisplay
837 * @screen: (allow-none): location to store the screen that the
838 * cursor is on, or %NULL.
839 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
840 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
841 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
843 * Gets the current location of the pointer and the current modifier
844 * mask for a given display.
848 * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
851 gdk_display_get_pointer (GdkDisplay *display,
855 GdkModifierType *mask)
857 g_return_if_fail (GDK_IS_DISPLAY (display));
859 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
863 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
871 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
873 /* This might need corrections, as the native window returned
874 may contain client side children */
879 window = _gdk_window_find_descendant_at (window,
882 x = floor (xx + 0.5);
883 y = floor (yy + 0.5);
893 gdk_window_real_window_get_device_position (GdkDisplay *display,
898 GdkModifierType *mask)
900 GdkWindowObject *private;
902 GdkModifierType tmp_mask;
903 gboolean normal_child;
905 private = (GdkWindowObject *) window;
907 normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
911 /* We got the coords on the impl, convert to the window */
912 tmpx -= private->abs_x;
913 tmpy -= private->abs_y;
923 return _gdk_window_find_child_at (window, tmpx, tmpy);
928 * gdk_display_get_window_at_pointer:
929 * @display: a #GdkDisplay
930 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
931 * to the window origin, or %NULL
932 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
933 & to the window origin, or %NULL
935 * Obtains the window underneath the mouse pointer, returning the location
936 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
937 * if the window under the mouse pointer is not known to GDK (for example,
938 * belongs to another application).
940 * Returns: (transfer none): the window under the mouse pointer, or %NULL
944 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
947 gdk_display_get_window_at_pointer (GdkDisplay *display,
951 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
953 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
957 multihead_get_device_state (GdkDisplay *display,
962 GdkModifierType *mask)
964 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
968 multihead_window_get_device_position (GdkDisplay *display,
973 GdkModifierType *mask)
975 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
979 multihead_window_at_device_position (GdkDisplay *display,
984 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
988 multihead_default_get_pointer (GdkDisplay *display,
992 GdkModifierType *mask)
994 return _gdk_windowing_get_device_state (display,
995 display->core_pointer,
1000 multihead_default_window_get_pointer (GdkDisplay *display,
1004 GdkModifierType *mask)
1006 return gdk_window_real_window_get_device_position (display,
1007 display->core_pointer,
1008 window, x, y, mask);
1012 multihead_default_window_at_pointer (GdkDisplay *display,
1016 return gdk_display_real_get_window_at_device_position (display,
1017 display->core_pointer,
1022 * gdk_display_set_pointer_hooks:
1023 * @display: a #GdkDisplay
1024 * @new_hooks: a table of pointers to functions for getting
1025 * quantities related to the current pointer position,
1026 * or %NULL to restore the default table.
1028 * This function allows for hooking into the operation
1029 * of getting the current location of the pointer on a particular
1030 * display. This is only useful for such low-level tools as an
1031 * event recorder. Applications should never have any
1032 * reason to use this facility.
1034 * Return value: the previous pointer hook table
1038 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1040 GdkDisplayPointerHooks *
1041 gdk_display_set_pointer_hooks (GdkDisplay *display,
1042 const GdkDisplayPointerHooks *new_hooks)
1044 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1046 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1049 multihead_current_pointer_hooks = new_hooks;
1051 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1053 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1055 return (GdkDisplayPointerHooks *)result;
1059 singlehead_get_pointer (GdkDisplay *display,
1063 GdkModifierType *mask)
1065 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1066 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1068 *screen = default_screen;
1070 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1074 singlehead_window_get_pointer (GdkDisplay *display,
1078 GdkModifierType *mask)
1080 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1084 singlehead_window_at_pointer (GdkDisplay *display,
1088 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1090 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1095 singlehead_default_window_get_pointer (GdkWindow *window,
1098 GdkModifierType *mask)
1100 GdkDisplay *display;
1102 display = gdk_drawable_get_display (window);
1104 return gdk_window_real_window_get_device_position (display,
1105 display->core_pointer,
1106 window, x, y, mask);
1110 singlehead_default_window_at_pointer (GdkScreen *screen,
1114 GdkDisplay *display;
1116 display = gdk_screen_get_display (screen);
1118 return gdk_display_real_get_window_at_device_position (display,
1119 display->core_pointer,
1124 * gdk_set_pointer_hooks:
1125 * @new_hooks: a table of pointers to functions for getting
1126 * quantities related to the current pointer position,
1127 * or %NULL to restore the default table.
1129 * This function allows for hooking into the operation
1130 * of getting the current location of the pointer. This
1131 * is only useful for such low-level tools as an
1132 * event recorder. Applications should never have any
1133 * reason to use this facility.
1135 * This function is not multihead safe. For multihead operation,
1136 * see gdk_display_set_pointer_hooks().
1138 * Return value: the previous pointer hook table
1140 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1143 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1145 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1148 singlehead_current_pointer_hooks = new_hooks;
1150 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1152 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1153 &singlehead_pointer_hooks);
1155 return (GdkPointerHooks *)result;
1159 generate_grab_broken_event (GdkWindow *window,
1162 GdkWindow *grab_window)
1164 g_return_if_fail (window != NULL);
1166 if (!GDK_WINDOW_DESTROYED (window))
1170 event = gdk_event_new (GDK_GRAB_BROKEN);
1171 event->grab_broken.window = g_object_ref (window);
1172 event->grab_broken.send_event = FALSE;
1173 event->grab_broken.implicit = implicit;
1174 event->grab_broken.grab_window = grab_window;
1175 gdk_event_set_device (event, device);
1176 event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1178 gdk_event_put (event);
1179 gdk_event_free (event);
1184 _gdk_display_get_last_device_grab (GdkDisplay *display,
1189 l = g_hash_table_lookup (display->device_grabs, device);
1193 l = g_list_last (l);
1201 _gdk_display_add_device_grab (GdkDisplay *display,
1204 GdkWindow *native_window,
1205 GdkGrabOwnership grab_ownership,
1206 gboolean owner_events,
1207 GdkEventMask event_mask,
1208 unsigned long serial_start,
1212 GdkDeviceGrabInfo *info, *other_info;
1215 info = g_new0 (GdkDeviceGrabInfo, 1);
1217 info->window = g_object_ref (window);
1218 info->native_window = g_object_ref (native_window);
1219 info->serial_start = serial_start;
1220 info->serial_end = G_MAXULONG;
1221 info->owner_events = owner_events;
1222 info->event_mask = event_mask;
1224 info->implicit = implicit;
1225 info->ownership = grab_ownership;
1227 grabs = g_hash_table_lookup (display->device_grabs, device);
1229 /* Find the first grab that has a larger start time (if any) and insert
1230 * before that. I.E we insert after already existing grabs with same
1232 for (l = grabs; l != NULL; l = l->next)
1234 other_info = l->data;
1236 if (info->serial_start < other_info->serial_start)
1240 grabs = g_list_insert_before (grabs, l, info);
1242 /* Make sure the new grab end before next grab */
1245 other_info = l->data;
1246 info->serial_end = other_info->serial_start;
1249 /* Find any previous grab and update its end time */
1250 l = g_list_find (grabs, info);
1254 other_info = l->data;
1255 other_info->serial_end = serial_start;
1258 g_hash_table_insert (display->device_grabs, device, grabs);
1263 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1264 This function splits things into two calls if needed, converting the
1265 coordinates to the right toplevel */
1267 synthesize_crossing_events (GdkDisplay *display,
1269 GdkWindow *src_window,
1270 GdkWindow *dest_window,
1271 GdkCrossingMode crossing_mode,
1275 GdkWindow *src_toplevel, *dest_toplevel;
1276 GdkModifierType state;
1279 /* We use the native crossing events if all native */
1280 if (_gdk_native_windows)
1284 src_toplevel = gdk_window_get_toplevel (src_window);
1286 src_toplevel = NULL;
1288 dest_toplevel = gdk_window_get_toplevel (dest_window);
1290 dest_toplevel = NULL;
1292 if (src_toplevel == NULL && dest_toplevel == NULL)
1295 if (src_toplevel == NULL ||
1296 src_toplevel == dest_toplevel)
1298 /* Same toplevels */
1299 gdk_window_get_pointer (dest_toplevel,
1301 _gdk_synthesize_crossing_events (display,
1311 else if (dest_toplevel == NULL)
1313 gdk_window_get_pointer (src_toplevel,
1315 _gdk_synthesize_crossing_events (display,
1327 /* Different toplevels */
1328 gdk_window_get_pointer (src_toplevel,
1330 _gdk_synthesize_crossing_events (display,
1339 gdk_window_get_pointer (dest_toplevel,
1341 _gdk_synthesize_crossing_events (display,
1354 get_current_toplevel (GdkDisplay *display,
1358 GdkModifierType *state_out)
1360 GdkWindow *pointer_window;
1362 GdkModifierType state;
1364 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1366 if (pointer_window != NULL &&
1367 (GDK_WINDOW_DESTROYED (pointer_window) ||
1368 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1369 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1370 pointer_window = NULL;
1375 return pointer_window;
1379 switch_to_pointer_grab (GdkDisplay *display,
1381 GdkDeviceGrabInfo *grab,
1382 GdkDeviceGrabInfo *last_grab,
1386 GdkWindow *src_window, *pointer_window, *new_toplevel;
1387 GdkPointerWindowInfo *info;
1389 GdkModifierType state;
1392 /* Temporarily unset pointer to make sure we send the crossing events below */
1393 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1394 g_hash_table_steal (display->device_grabs, device);
1395 info = _gdk_display_get_pointer_info (display, device);
1399 /* New grab is in effect */
1401 /* We need to generate crossing events for the grab.
1402 * However, there are never any crossing events for implicit grabs
1403 * TODO: ... Actually, this could happen if the pointer window
1404 * doesn't have button mask so a parent gets the event...
1406 if (!grab->implicit)
1408 /* We send GRAB crossing events from the window under the pointer to the
1409 grab window. Except if there is an old grab then we start from that */
1411 src_window = last_grab->window;
1413 src_window = info->window_under_pointer;
1415 if (src_window != grab->window)
1416 synthesize_crossing_events (display, device,
1417 src_window, grab->window,
1418 GDK_CROSSING_GRAB, time, serial);
1420 /* !owner_event Grabbing a window that we're not inside, current status is
1421 now NULL (i.e. outside grabbed window) */
1422 if (!grab->owner_events && info->window_under_pointer != grab->window)
1423 _gdk_display_set_window_under_pointer (display, device, NULL);
1426 grab->activated = TRUE;
1431 new_toplevel = NULL;
1433 if (grab == NULL /* ungrab */ ||
1434 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1436 /* We force check what window we're in, and update the toplevel_under_pointer info,
1437 * as that won't get told of this change with toplevel enter events.
1439 if (info->toplevel_under_pointer)
1440 g_object_unref (info->toplevel_under_pointer);
1441 info->toplevel_under_pointer = NULL;
1443 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1446 /* w is now toplevel and x,y in toplevel coords */
1447 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1448 info->toplevel_x = x;
1449 info->toplevel_y = y;
1450 info->state = state;
1454 if (grab == NULL) /* Ungrabbed, send events */
1456 pointer_window = NULL;
1459 /* Find (possibly virtual) child window */
1461 _gdk_window_find_descendant_at (new_toplevel,
1466 if (pointer_window != last_grab->window)
1467 synthesize_crossing_events (display, device,
1468 last_grab->window, pointer_window,
1469 GDK_CROSSING_UNGRAB, time, serial);
1471 /* We're now ungrabbed, update the window_under_pointer */
1472 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1476 g_hash_table_insert (display->device_grabs, device, old_grabs);
1480 _gdk_display_device_grab_update (GdkDisplay *display,
1482 gulong current_serial)
1484 GdkDeviceGrabInfo *current_grab, *next_grab;
1488 time = display->last_event_time;
1489 grabs = g_hash_table_lookup (display->device_grabs, device);
1491 while (grabs != NULL)
1493 current_grab = grabs->data;
1495 if (current_grab->serial_start > current_serial)
1496 return; /* Hasn't started yet */
1498 if (current_grab->serial_end > current_serial)
1500 /* This one hasn't ended yet.
1501 its the currently active one or scheduled to be active */
1503 if (!current_grab->activated)
1505 if (device->source != GDK_SOURCE_KEYBOARD)
1506 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1515 /* This is the next active grab */
1516 next_grab = grabs->next->data;
1518 if (next_grab->serial_start > current_serial)
1519 next_grab = NULL; /* Actually its not yet active */
1522 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1523 (next_grab != NULL && current_grab->window != next_grab->window))
1524 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1526 current_grab->implicit,
1527 next_grab? next_grab->window : NULL);
1529 /* Remove old grab */
1530 grabs = g_list_delete_link (grabs, grabs);
1531 g_hash_table_insert (display->device_grabs, device, grabs);
1533 if (device->source != GDK_SOURCE_KEYBOARD)
1534 switch_to_pointer_grab (display, device,
1535 next_grab, current_grab,
1536 time, current_serial);
1538 free_device_grab (current_grab);
1543 grab_list_find (GList *grabs,
1546 GdkDeviceGrabInfo *grab;
1552 if (serial >= grab->serial_start && serial < grab->serial_end)
1555 grabs = grabs->next;
1562 find_device_grab (GdkDisplay *display,
1568 l = g_hash_table_lookup (display->device_grabs, device);
1569 return grab_list_find (l, serial);
1573 _gdk_display_has_device_grab (GdkDisplay *display,
1579 l = find_device_grab (display, device, serial);
1586 /* Returns true if last grab was ended
1587 * If if_child is non-NULL, end the grab only if the grabbed
1588 * window is the same as if_child or a descendant of it */
1590 _gdk_display_end_device_grab (GdkDisplay *display,
1593 GdkWindow *if_child,
1596 GdkDeviceGrabInfo *grab;
1599 l = find_device_grab (display, device, serial);
1606 (if_child == NULL ||
1607 _gdk_window_event_parent_of (if_child, grab->window)))
1609 grab->serial_end = serial;
1610 grab->implicit_ungrab = implicit;
1611 return l->next == NULL;
1617 /* Returns TRUE if device events are not blocked by any grab */
1619 _gdk_display_check_grab_ownership (GdkDisplay *display,
1623 GHashTableIter iter;
1624 gpointer key, value;
1625 GdkGrabOwnership higher_ownership, device_ownership;
1626 gboolean device_is_keyboard;
1628 g_hash_table_iter_init (&iter, display->device_grabs);
1629 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1630 device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1632 while (g_hash_table_iter_next (&iter, &key, &value))
1634 GdkDeviceGrabInfo *grab;
1640 grabs = grab_list_find (grabs, serial);
1645 /* Discard device if it's not of the same type */
1646 if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1647 (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1653 device_ownership = grab->ownership;
1656 if (grab->ownership > higher_ownership)
1657 higher_ownership = grab->ownership;
1661 if (higher_ownership > device_ownership)
1663 /* There's a higher priority ownership
1664 * going on for other device(s)
1672 GdkPointerWindowInfo *
1673 _gdk_display_get_pointer_info (GdkDisplay *display,
1676 GdkPointerWindowInfo *info;
1678 if (G_UNLIKELY (!device))
1681 info = g_hash_table_lookup (display->pointers_info, device);
1683 if (G_UNLIKELY (!info))
1685 info = g_slice_new0 (GdkPointerWindowInfo);
1686 g_hash_table_insert (display->pointers_info, device, info);
1693 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1694 GdkDisplayPointerInfoForeach func,
1697 GHashTableIter iter;
1698 gpointer key, value;
1700 g_hash_table_iter_init (&iter, display->pointers_info);
1702 while (g_hash_table_iter_next (&iter, &key, &value))
1704 GdkPointerWindowInfo *info = value;
1705 GdkDevice *device = key;
1707 (func) (display, device, info, user_data);
1712 * gdk_device_grab_info_libgtk_only:
1713 * @display: the display for which to get the grab information
1714 * @device: device to get the grab information from
1715 * @grab_window: location to store current grab window
1716 * @owner_events: location to store boolean indicating whether
1717 * the @owner_events flag to gdk_keyboard_grab() or
1718 * gdk_pointer_grab() was %TRUE.
1720 * Determines information about the current keyboard grab.
1721 * This is not public API and must not be used by applications.
1723 * Return value: %TRUE if this application currently has the
1727 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1729 GdkWindow **grab_window,
1730 gboolean *owner_events)
1732 GdkDeviceGrabInfo *info;
1734 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1735 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1737 info = _gdk_display_get_last_device_grab (display, device);
1742 *grab_window = info->window;
1744 *owner_events = info->owner_events;
1753 * gdk_display_pointer_is_grabbed:
1754 * @display: a #GdkDisplay
1756 * Test if the pointer is grabbed.
1758 * Returns: %TRUE if an active X pointer grab is in effect
1762 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1765 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1767 GdkDeviceManager *device_manager;
1768 GList *devices, *dev;
1771 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1773 device_manager = gdk_display_get_device_manager (display);
1774 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1776 for (dev = devices; dev; dev = dev->next)
1780 if (device->source == GDK_SOURCE_MOUSE &&
1781 gdk_display_device_is_grabbed (display, device))
1789 * gdk_display_device_is_grabbed:
1790 * @display: a #GdkDisplay
1791 * @device: a #GdkDevice
1793 * Returns %TRUE if there is an ongoing grab on @device for @display.
1795 * Returns: %TRUE if there is a grab in effect for @device.
1798 gdk_display_device_is_grabbed (GdkDisplay *display,
1801 GdkDeviceGrabInfo *info;
1803 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1804 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1806 /* What we're interested in is the steady state (ie last grab),
1807 because we're interested e.g. if we grabbed so that we
1808 can ungrab, even if our grab is not active just yet. */
1809 info = _gdk_display_get_last_device_grab (display, device);
1811 return (info && !info->implicit);
1815 * gdk_display_get_device_manager:
1816 * @display: a #GdkDisplay.
1818 * Returns the #GdkDeviceManager associated to @display.
1820 * Returns: A #GdkDeviceManager, or %NULL. This memory is
1821 * owned by GDK and must not be freed or unreferenced.
1826 gdk_display_get_device_manager (GdkDisplay *display)
1828 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1830 return display->device_manager;