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(),
293 /* this is to make it drop devices which may require using the X
294 * display and therefore can't be cleaned up in finalize.
295 * It will also disconnect device_removed_cb
297 g_object_run_dispose (G_OBJECT (display->device_manager));
300 G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
304 gdk_display_finalize (GObject *object)
306 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
308 g_hash_table_foreach_remove (display->device_grabs,
309 free_device_grabs_foreach,
311 g_hash_table_destroy (display->device_grabs);
313 g_hash_table_destroy (display->pointers_info);
314 g_hash_table_destroy (display->multiple_click_info);
316 if (display->device_manager)
317 g_object_unref (display->device_manager);
319 G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
324 * @display: a #GdkDisplay
326 * Closes the connection to the windowing system for the given display,
327 * and cleans up associated resources.
332 gdk_display_close (GdkDisplay *display)
334 g_return_if_fail (GDK_IS_DISPLAY (display));
336 if (!display->closed)
338 display->closed = TRUE;
340 g_signal_emit (display, signals[CLOSED], 0, FALSE);
341 g_object_run_dispose (G_OBJECT (display));
343 g_object_unref (display);
348 * gdk_display_is_closed:
349 * @display: a #GdkDisplay
351 * Finds out if the display has been closed.
353 * Returns: %TRUE if the display is closed.
358 gdk_display_is_closed (GdkDisplay *display)
360 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
362 return display->closed;
366 * gdk_display_get_event:
367 * @display: a #GdkDisplay
369 * Gets the next #GdkEvent to be processed for @display, fetching events from the
370 * windowing system if necessary.
372 * Return value: the next #GdkEvent to be processed, or %NULL if no events
373 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
378 gdk_display_get_event (GdkDisplay *display)
380 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
382 _gdk_events_queue (display);
383 return _gdk_event_unqueue (display);
387 * gdk_display_peek_event:
388 * @display: a #GdkDisplay
390 * Gets a copy of the first #GdkEvent in the @display's event queue, without
391 * removing the event from the queue. (Note that this function will
392 * not get more events from the windowing system. It only checks the events
393 * that have already been moved to the GDK event queue.)
395 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
396 * if no events are in the queue. The returned #GdkEvent should be freed with
402 gdk_display_peek_event (GdkDisplay *display)
406 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
408 tmp_list = _gdk_event_queue_find_first (display);
411 return gdk_event_copy (tmp_list->data);
417 * gdk_display_put_event:
418 * @display: a #GdkDisplay
419 * @event: a #GdkEvent.
421 * Appends a copy of the given event onto the front of the event
422 * queue for @display.
427 gdk_display_put_event (GdkDisplay *display,
428 const GdkEvent *event)
430 g_return_if_fail (GDK_IS_DISPLAY (display));
431 g_return_if_fail (event != NULL);
433 _gdk_event_queue_append (display, gdk_event_copy (event));
434 /* If the main loop is blocking in a different thread, wake it up */
435 g_main_context_wakeup (NULL);
439 * gdk_display_pointer_ungrab:
440 * @display: a #GdkDisplay.
441 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
443 * Release any pointer grab.
447 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
451 gdk_display_pointer_ungrab (GdkDisplay *display,
454 GdkDeviceManager *device_manager;
455 GList *devices, *dev;
458 g_return_if_fail (GDK_IS_DISPLAY (display));
460 device_manager = gdk_display_get_device_manager (display);
461 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
463 /* FIXME: Should this be generic to all backends? */
464 /* FIXME: What happens with extended devices? */
465 for (dev = devices; dev; dev = dev->next)
469 if (device->source != GDK_SOURCE_MOUSE)
472 gdk_device_ungrab (device, time_);
475 g_list_free (devices);
479 * gdk_pointer_ungrab:
480 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
481 * timestamp is available.
483 * Ungrabs the pointer on the default display, if it is grabbed by this
486 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
490 gdk_pointer_ungrab (guint32 time)
492 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
496 * gdk_pointer_is_grabbed:
498 * Returns %TRUE if the pointer on the default display is currently
499 * grabbed by this application.
501 * Note that this does not take the inmplicit pointer grab on button
502 * presses into account.
504 * Return value: %TRUE if the pointer is currently grabbed by this application.
506 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
509 gdk_pointer_is_grabbed (void)
511 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
515 * gdk_display_keyboard_ungrab:
516 * @display: a #GdkDisplay.
517 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
519 * Release any keyboard grab
523 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
527 gdk_display_keyboard_ungrab (GdkDisplay *display,
530 GdkDeviceManager *device_manager;
531 GList *devices, *dev;
534 g_return_if_fail (GDK_IS_DISPLAY (display));
536 device_manager = gdk_display_get_device_manager (display);
537 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
539 /* FIXME: Should this be generic to all backends? */
540 /* FIXME: What happens with extended devices? */
541 for (dev = devices; dev; dev = dev->next)
545 if (device->source != GDK_SOURCE_KEYBOARD)
548 gdk_device_ungrab (device, time);
551 g_list_free (devices);
555 * gdk_keyboard_ungrab:
556 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
557 * timestamp is available.
559 * Ungrabs the keyboard on the default display, if it is grabbed by this
562 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
566 gdk_keyboard_ungrab (guint32 time)
568 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
574 * Emits a short beep on the default display.
579 gdk_display_beep (gdk_display_get_default ());
583 * gdk_event_send_client_message:
584 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
585 * @winid: the window to send the X ClientMessage event to.
587 * Sends an X ClientMessage event to a given window (which must be
588 * on the default #GdkDisplay.)
589 * This could be used for communicating between different applications,
590 * though the amount of data is limited to 20 bytes.
592 * Return value: non-zero on success.
595 gdk_event_send_client_message (GdkEvent *event,
596 GdkNativeWindow winid)
598 g_return_val_if_fail (event != NULL, FALSE);
600 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
605 * gdk_event_send_clientmessage_toall:
606 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
608 * Sends an X ClientMessage event to all toplevel windows on the default
611 * Toplevel windows are determined by checking for the WM_STATE property, as
612 * described in the Inter-Client Communication Conventions Manual (ICCCM).
613 * If no windows are found with the WM_STATE property set, the message is sent
614 * to all children of the root window.
617 gdk_event_send_clientmessage_toall (GdkEvent *event)
619 g_return_if_fail (event != NULL);
621 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
625 * gdk_device_get_core_pointer:
627 * Returns the core pointer device for the default display.
629 * Return value: the core pointer device; this is owned by the
630 * display and should not be freed.
632 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
633 * gdk_event_get_device() if a #GdkEvent with pointer device
634 * information is available.
637 gdk_device_get_core_pointer (void)
639 return gdk_display_get_core_pointer (gdk_display_get_default ());
643 * gdk_display_get_core_pointer:
644 * @display: a #GdkDisplay
646 * Returns the core pointer device for the given display
648 * Return value: the core pointer device; this is owned by the
649 * display and should not be freed.
653 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
654 * gdk_event_get_device() if a #GdkEvent with device
655 * information is available.
658 gdk_display_get_core_pointer (GdkDisplay *display)
660 return display->core_pointer;
664 * gdk_set_sm_client_id:
665 * @sm_client_id: the client id assigned by the session manager when the
666 * connection was opened, or %NULL to remove the property.
668 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
669 * the window manager can save the application's state using the X11R6 ICCCM
670 * session management protocol.
672 * See the X Session Management Library documentation for more information on
673 * session management and the Inter-Client Communication Conventions Manual
674 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
675 * (Both documents are part of the X Window System distribution.)
678 gdk_set_sm_client_id (const gchar* sm_client_id)
680 GSList *displays, *tmp_list;
682 g_free (gdk_sm_client_id);
683 gdk_sm_client_id = g_strdup (sm_client_id);
685 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
686 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
687 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
689 g_slist_free (displays);
693 * _gdk_get_sm_client_id:
695 * Gets the client ID set with gdk_set_sm_client_id(), if any.
697 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
698 * has never been called.
701 _gdk_get_sm_client_id (void)
703 return gdk_sm_client_id;
707 _gdk_display_enable_motion_hints (GdkDisplay *display,
710 gulong *device_serial, serial;
712 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
716 device_serial = g_new0 (gulong, 1);
717 *device_serial = G_MAXULONG;
718 g_hash_table_insert (display->motion_hint_info, device, device_serial);
721 if (*device_serial != 0)
723 serial = _gdk_windowing_window_get_next_serial (display);
724 /* We might not actually generate the next request, so
725 make sure this triggers always, this may cause it to
726 trigger slightly too early, but this is just a hint
730 if (serial < *device_serial)
731 *device_serial = serial;
736 * gdk_display_get_device_state:
737 * @display: a #GdkDisplay.
738 * @device: device to query status to.
739 * @screen: location to store the #GdkScreen the @device is on, or %NULL.
740 * @x: location to store root window X coordinate of @device, or %NULL.
741 * @y: location to store root window Y coordinate of @device, or %NULL.
742 * @mask: location to store current modifier mask for @device, or %NULL.
744 * Gets the current location and state of @device for a given display.
749 gdk_display_get_device_state (GdkDisplay *display,
754 GdkModifierType *mask)
756 GdkScreen *tmp_screen;
758 GdkModifierType tmp_mask;
760 g_return_if_fail (GDK_IS_DISPLAY (display));
761 g_return_if_fail (GDK_IS_DEVICE (device));
763 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
766 *screen = tmp_screen;
776 * gdk_display_get_window_at_device_position:
777 * @display: a #GdkDisplay.
778 * @device: #GdkDevice to query info to.
779 * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
780 * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
782 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
783 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
785 * Returns: the #GdkWindow under the device position, or %NULL.
790 gdk_display_get_window_at_device_position (GdkDisplay *display,
798 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
799 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
801 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
812 * gdk_display_set_device_hooks:
813 * @display: a #GdkDisplay.
814 * @new_hooks: a table of pointers to functions for getting quantities related to all
815 * devices position, or %NULL to restore the default table.
817 * This function allows for hooking into the operation of getting the current location of any
818 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
819 * an event recorder. Applications should never have any reason to use this facility.
821 * Returns: The previous device hook table.
825 GdkDisplayDeviceHooks *
826 gdk_display_set_device_hooks (GdkDisplay *display,
827 const GdkDisplayDeviceHooks *new_hooks)
829 const GdkDisplayDeviceHooks *result;
831 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
832 result = display->device_hooks;
835 display->device_hooks = new_hooks;
837 display->device_hooks = &default_device_hooks;
839 return (GdkDisplayDeviceHooks *) result;
843 * gdk_display_get_pointer:
844 * @display: a #GdkDisplay
845 * @screen: (allow-none): location to store the screen that the
846 * cursor is on, or %NULL.
847 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
848 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
849 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
851 * Gets the current location of the pointer and the current modifier
852 * mask for a given display.
856 * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
859 gdk_display_get_pointer (GdkDisplay *display,
863 GdkModifierType *mask)
865 g_return_if_fail (GDK_IS_DISPLAY (display));
867 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
871 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
879 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
881 /* This might need corrections, as the native window returned
882 may contain client side children */
887 window = _gdk_window_find_descendant_at (window,
890 x = floor (xx + 0.5);
891 y = floor (yy + 0.5);
901 gdk_window_real_window_get_device_position (GdkDisplay *display,
906 GdkModifierType *mask)
908 GdkWindowObject *private;
910 GdkModifierType tmp_mask;
911 gboolean normal_child;
913 private = (GdkWindowObject *) window;
915 normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
919 /* We got the coords on the impl, convert to the window */
920 tmpx -= private->abs_x;
921 tmpy -= private->abs_y;
931 return _gdk_window_find_child_at (window, tmpx, tmpy);
936 * gdk_display_get_window_at_pointer:
937 * @display: a #GdkDisplay
938 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
939 * to the window origin, or %NULL
940 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
941 & to the window origin, or %NULL
943 * Obtains the window underneath the mouse pointer, returning the location
944 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
945 * if the window under the mouse pointer is not known to GDK (for example,
946 * belongs to another application).
948 * Returns: (transfer none): the window under the mouse pointer, or %NULL
952 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
955 gdk_display_get_window_at_pointer (GdkDisplay *display,
959 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
961 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
965 multihead_get_device_state (GdkDisplay *display,
970 GdkModifierType *mask)
972 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
976 multihead_window_get_device_position (GdkDisplay *display,
981 GdkModifierType *mask)
983 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
987 multihead_window_at_device_position (GdkDisplay *display,
992 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
996 multihead_default_get_pointer (GdkDisplay *display,
1000 GdkModifierType *mask)
1002 return _gdk_windowing_get_device_state (display,
1003 display->core_pointer,
1004 screen, x, y, mask);
1008 multihead_default_window_get_pointer (GdkDisplay *display,
1012 GdkModifierType *mask)
1014 return gdk_window_real_window_get_device_position (display,
1015 display->core_pointer,
1016 window, x, y, mask);
1020 multihead_default_window_at_pointer (GdkDisplay *display,
1024 return gdk_display_real_get_window_at_device_position (display,
1025 display->core_pointer,
1030 * gdk_display_set_pointer_hooks:
1031 * @display: a #GdkDisplay
1032 * @new_hooks: a table of pointers to functions for getting
1033 * quantities related to the current pointer position,
1034 * or %NULL to restore the default table.
1036 * This function allows for hooking into the operation
1037 * of getting the current location of the pointer on a particular
1038 * display. This is only useful for such low-level tools as an
1039 * event recorder. Applications should never have any
1040 * reason to use this facility.
1042 * Return value: the previous pointer hook table
1046 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1048 GdkDisplayPointerHooks *
1049 gdk_display_set_pointer_hooks (GdkDisplay *display,
1050 const GdkDisplayPointerHooks *new_hooks)
1052 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1054 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1057 multihead_current_pointer_hooks = new_hooks;
1059 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1061 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1063 return (GdkDisplayPointerHooks *)result;
1067 singlehead_get_pointer (GdkDisplay *display,
1071 GdkModifierType *mask)
1073 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1074 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1076 *screen = default_screen;
1078 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1082 singlehead_window_get_pointer (GdkDisplay *display,
1086 GdkModifierType *mask)
1088 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1092 singlehead_window_at_pointer (GdkDisplay *display,
1096 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1098 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1103 singlehead_default_window_get_pointer (GdkWindow *window,
1106 GdkModifierType *mask)
1108 GdkDisplay *display;
1110 display = gdk_drawable_get_display (window);
1112 return gdk_window_real_window_get_device_position (display,
1113 display->core_pointer,
1114 window, x, y, mask);
1118 singlehead_default_window_at_pointer (GdkScreen *screen,
1122 GdkDisplay *display;
1124 display = gdk_screen_get_display (screen);
1126 return gdk_display_real_get_window_at_device_position (display,
1127 display->core_pointer,
1132 * gdk_set_pointer_hooks:
1133 * @new_hooks: a table of pointers to functions for getting
1134 * quantities related to the current pointer position,
1135 * or %NULL to restore the default table.
1137 * This function allows for hooking into the operation
1138 * of getting the current location of the pointer. This
1139 * is only useful for such low-level tools as an
1140 * event recorder. Applications should never have any
1141 * reason to use this facility.
1143 * This function is not multihead safe. For multihead operation,
1144 * see gdk_display_set_pointer_hooks().
1146 * Return value: the previous pointer hook table
1148 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1151 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1153 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1156 singlehead_current_pointer_hooks = new_hooks;
1158 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1160 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1161 &singlehead_pointer_hooks);
1163 return (GdkPointerHooks *)result;
1167 generate_grab_broken_event (GdkWindow *window,
1170 GdkWindow *grab_window)
1172 g_return_if_fail (window != NULL);
1174 if (!GDK_WINDOW_DESTROYED (window))
1178 event = gdk_event_new (GDK_GRAB_BROKEN);
1179 event->grab_broken.window = g_object_ref (window);
1180 event->grab_broken.send_event = FALSE;
1181 event->grab_broken.implicit = implicit;
1182 event->grab_broken.grab_window = grab_window;
1183 gdk_event_set_device (event, device);
1184 event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1186 gdk_event_put (event);
1187 gdk_event_free (event);
1192 _gdk_display_get_last_device_grab (GdkDisplay *display,
1197 l = g_hash_table_lookup (display->device_grabs, device);
1201 l = g_list_last (l);
1209 _gdk_display_add_device_grab (GdkDisplay *display,
1212 GdkWindow *native_window,
1213 GdkGrabOwnership grab_ownership,
1214 gboolean owner_events,
1215 GdkEventMask event_mask,
1216 unsigned long serial_start,
1220 GdkDeviceGrabInfo *info, *other_info;
1223 info = g_new0 (GdkDeviceGrabInfo, 1);
1225 info->window = g_object_ref (window);
1226 info->native_window = g_object_ref (native_window);
1227 info->serial_start = serial_start;
1228 info->serial_end = G_MAXULONG;
1229 info->owner_events = owner_events;
1230 info->event_mask = event_mask;
1232 info->implicit = implicit;
1233 info->ownership = grab_ownership;
1235 grabs = g_hash_table_lookup (display->device_grabs, device);
1237 /* Find the first grab that has a larger start time (if any) and insert
1238 * before that. I.E we insert after already existing grabs with same
1240 for (l = grabs; l != NULL; l = l->next)
1242 other_info = l->data;
1244 if (info->serial_start < other_info->serial_start)
1248 grabs = g_list_insert_before (grabs, l, info);
1250 /* Make sure the new grab end before next grab */
1253 other_info = l->data;
1254 info->serial_end = other_info->serial_start;
1257 /* Find any previous grab and update its end time */
1258 l = g_list_find (grabs, info);
1262 other_info = l->data;
1263 other_info->serial_end = serial_start;
1266 g_hash_table_insert (display->device_grabs, device, grabs);
1271 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1272 This function splits things into two calls if needed, converting the
1273 coordinates to the right toplevel */
1275 synthesize_crossing_events (GdkDisplay *display,
1277 GdkWindow *src_window,
1278 GdkWindow *dest_window,
1279 GdkCrossingMode crossing_mode,
1283 GdkWindow *src_toplevel, *dest_toplevel;
1284 GdkModifierType state;
1287 /* We use the native crossing events if all native */
1288 if (_gdk_native_windows)
1292 src_toplevel = gdk_window_get_toplevel (src_window);
1294 src_toplevel = NULL;
1296 dest_toplevel = gdk_window_get_toplevel (dest_window);
1298 dest_toplevel = NULL;
1300 if (src_toplevel == NULL && dest_toplevel == NULL)
1303 if (src_toplevel == NULL ||
1304 src_toplevel == dest_toplevel)
1306 /* Same toplevels */
1307 gdk_window_get_pointer (dest_toplevel,
1309 _gdk_synthesize_crossing_events (display,
1319 else if (dest_toplevel == NULL)
1321 gdk_window_get_pointer (src_toplevel,
1323 _gdk_synthesize_crossing_events (display,
1335 /* Different toplevels */
1336 gdk_window_get_pointer (src_toplevel,
1338 _gdk_synthesize_crossing_events (display,
1347 gdk_window_get_pointer (dest_toplevel,
1349 _gdk_synthesize_crossing_events (display,
1362 get_current_toplevel (GdkDisplay *display,
1366 GdkModifierType *state_out)
1368 GdkWindow *pointer_window;
1370 GdkModifierType state;
1372 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1374 if (pointer_window != NULL &&
1375 (GDK_WINDOW_DESTROYED (pointer_window) ||
1376 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1377 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1378 pointer_window = NULL;
1383 return pointer_window;
1387 switch_to_pointer_grab (GdkDisplay *display,
1389 GdkDeviceGrabInfo *grab,
1390 GdkDeviceGrabInfo *last_grab,
1394 GdkWindow *src_window, *pointer_window, *new_toplevel;
1395 GdkPointerWindowInfo *info;
1397 GdkModifierType state;
1400 /* Temporarily unset pointer to make sure we send the crossing events below */
1401 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1402 g_hash_table_steal (display->device_grabs, device);
1403 info = _gdk_display_get_pointer_info (display, device);
1407 /* New grab is in effect */
1409 /* We need to generate crossing events for the grab.
1410 * However, there are never any crossing events for implicit grabs
1411 * TODO: ... Actually, this could happen if the pointer window
1412 * doesn't have button mask so a parent gets the event...
1414 if (!grab->implicit)
1416 /* We send GRAB crossing events from the window under the pointer to the
1417 grab window. Except if there is an old grab then we start from that */
1419 src_window = last_grab->window;
1421 src_window = info->window_under_pointer;
1423 if (src_window != grab->window)
1424 synthesize_crossing_events (display, device,
1425 src_window, grab->window,
1426 GDK_CROSSING_GRAB, time, serial);
1428 /* !owner_event Grabbing a window that we're not inside, current status is
1429 now NULL (i.e. outside grabbed window) */
1430 if (!grab->owner_events && info->window_under_pointer != grab->window)
1431 _gdk_display_set_window_under_pointer (display, device, NULL);
1434 grab->activated = TRUE;
1439 new_toplevel = NULL;
1441 if (grab == NULL /* ungrab */ ||
1442 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1444 /* We force check what window we're in, and update the toplevel_under_pointer info,
1445 * as that won't get told of this change with toplevel enter events.
1447 if (info->toplevel_under_pointer)
1448 g_object_unref (info->toplevel_under_pointer);
1449 info->toplevel_under_pointer = NULL;
1451 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1454 /* w is now toplevel and x,y in toplevel coords */
1455 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1456 info->toplevel_x = x;
1457 info->toplevel_y = y;
1458 info->state = state;
1462 if (grab == NULL) /* Ungrabbed, send events */
1464 pointer_window = NULL;
1467 /* Find (possibly virtual) child window */
1469 _gdk_window_find_descendant_at (new_toplevel,
1474 if (pointer_window != last_grab->window)
1475 synthesize_crossing_events (display, device,
1476 last_grab->window, pointer_window,
1477 GDK_CROSSING_UNGRAB, time, serial);
1479 /* We're now ungrabbed, update the window_under_pointer */
1480 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1484 g_hash_table_insert (display->device_grabs, device, old_grabs);
1488 _gdk_display_device_grab_update (GdkDisplay *display,
1490 gulong current_serial)
1492 GdkDeviceGrabInfo *current_grab, *next_grab;
1496 time = display->last_event_time;
1497 grabs = g_hash_table_lookup (display->device_grabs, device);
1499 while (grabs != NULL)
1501 current_grab = grabs->data;
1503 if (current_grab->serial_start > current_serial)
1504 return; /* Hasn't started yet */
1506 if (current_grab->serial_end > current_serial)
1508 /* This one hasn't ended yet.
1509 its the currently active one or scheduled to be active */
1511 if (!current_grab->activated)
1513 if (device->source != GDK_SOURCE_KEYBOARD)
1514 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1523 /* This is the next active grab */
1524 next_grab = grabs->next->data;
1526 if (next_grab->serial_start > current_serial)
1527 next_grab = NULL; /* Actually its not yet active */
1530 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1531 (next_grab != NULL && current_grab->window != next_grab->window))
1532 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1534 current_grab->implicit,
1535 next_grab? next_grab->window : NULL);
1537 /* Remove old grab */
1538 grabs = g_list_delete_link (grabs, grabs);
1539 g_hash_table_insert (display->device_grabs, device, grabs);
1541 if (device->source != GDK_SOURCE_KEYBOARD)
1542 switch_to_pointer_grab (display, device,
1543 next_grab, current_grab,
1544 time, current_serial);
1546 free_device_grab (current_grab);
1551 grab_list_find (GList *grabs,
1554 GdkDeviceGrabInfo *grab;
1560 if (serial >= grab->serial_start && serial < grab->serial_end)
1563 grabs = grabs->next;
1570 find_device_grab (GdkDisplay *display,
1576 l = g_hash_table_lookup (display->device_grabs, device);
1577 return grab_list_find (l, serial);
1581 _gdk_display_has_device_grab (GdkDisplay *display,
1587 l = find_device_grab (display, device, serial);
1594 /* Returns true if last grab was ended
1595 * If if_child is non-NULL, end the grab only if the grabbed
1596 * window is the same as if_child or a descendant of it */
1598 _gdk_display_end_device_grab (GdkDisplay *display,
1601 GdkWindow *if_child,
1604 GdkDeviceGrabInfo *grab;
1607 l = find_device_grab (display, device, serial);
1614 (if_child == NULL ||
1615 _gdk_window_event_parent_of (if_child, grab->window)))
1617 grab->serial_end = serial;
1618 grab->implicit_ungrab = implicit;
1619 return l->next == NULL;
1625 /* Returns TRUE if device events are not blocked by any grab */
1627 _gdk_display_check_grab_ownership (GdkDisplay *display,
1631 GHashTableIter iter;
1632 gpointer key, value;
1633 GdkGrabOwnership higher_ownership, device_ownership;
1634 gboolean device_is_keyboard;
1636 g_hash_table_iter_init (&iter, display->device_grabs);
1637 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1638 device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1640 while (g_hash_table_iter_next (&iter, &key, &value))
1642 GdkDeviceGrabInfo *grab;
1648 grabs = grab_list_find (grabs, serial);
1653 /* Discard device if it's not of the same type */
1654 if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1655 (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1661 device_ownership = grab->ownership;
1664 if (grab->ownership > higher_ownership)
1665 higher_ownership = grab->ownership;
1669 if (higher_ownership > device_ownership)
1671 /* There's a higher priority ownership
1672 * going on for other device(s)
1680 GdkPointerWindowInfo *
1681 _gdk_display_get_pointer_info (GdkDisplay *display,
1684 GdkPointerWindowInfo *info;
1686 if (G_UNLIKELY (!device))
1689 info = g_hash_table_lookup (display->pointers_info, device);
1691 if (G_UNLIKELY (!info))
1693 info = g_slice_new0 (GdkPointerWindowInfo);
1694 g_hash_table_insert (display->pointers_info, device, info);
1701 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1702 GdkDisplayPointerInfoForeach func,
1705 GHashTableIter iter;
1706 gpointer key, value;
1708 g_hash_table_iter_init (&iter, display->pointers_info);
1710 while (g_hash_table_iter_next (&iter, &key, &value))
1712 GdkPointerWindowInfo *info = value;
1713 GdkDevice *device = key;
1715 (func) (display, device, info, user_data);
1720 * gdk_device_grab_info_libgtk_only:
1721 * @display: the display for which to get the grab information
1722 * @device: device to get the grab information from
1723 * @grab_window: location to store current grab window
1724 * @owner_events: location to store boolean indicating whether
1725 * the @owner_events flag to gdk_keyboard_grab() or
1726 * gdk_pointer_grab() was %TRUE.
1728 * Determines information about the current keyboard grab.
1729 * This is not public API and must not be used by applications.
1731 * Return value: %TRUE if this application currently has the
1735 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1737 GdkWindow **grab_window,
1738 gboolean *owner_events)
1740 GdkDeviceGrabInfo *info;
1742 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1743 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1745 info = _gdk_display_get_last_device_grab (display, device);
1750 *grab_window = info->window;
1752 *owner_events = info->owner_events;
1761 * gdk_display_pointer_is_grabbed:
1762 * @display: a #GdkDisplay
1764 * Test if the pointer is grabbed.
1766 * Returns: %TRUE if an active X pointer grab is in effect
1770 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1773 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1775 GdkDeviceManager *device_manager;
1776 GList *devices, *dev;
1779 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1781 device_manager = gdk_display_get_device_manager (display);
1782 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1784 for (dev = devices; dev; dev = dev->next)
1788 if (device->source == GDK_SOURCE_MOUSE &&
1789 gdk_display_device_is_grabbed (display, device))
1797 * gdk_display_device_is_grabbed:
1798 * @display: a #GdkDisplay
1799 * @device: a #GdkDevice
1801 * Returns %TRUE if there is an ongoing grab on @device for @display.
1803 * Returns: %TRUE if there is a grab in effect for @device.
1806 gdk_display_device_is_grabbed (GdkDisplay *display,
1809 GdkDeviceGrabInfo *info;
1811 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1812 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1814 /* What we're interested in is the steady state (ie last grab),
1815 because we're interested e.g. if we grabbed so that we
1816 can ungrab, even if our grab is not active just yet. */
1817 info = _gdk_display_get_last_device_grab (display, device);
1819 return (info && !info->implicit);
1823 * gdk_display_get_device_manager:
1824 * @display: a #GdkDisplay.
1826 * Returns the #GdkDeviceManager associated to @display.
1828 * Returns: A #GdkDeviceManager, or %NULL. This memory is
1829 * owned by GDK and must not be freed or unreferenced.
1834 gdk_display_get_device_manager (GdkDisplay *display)
1836 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1838 return display->device_manager;