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.
26 #include "gdkdisplay.h"
28 #include "gdkevents.h"
29 #include "gdkwindowimpl.h"
30 #include "gdkinternals.h"
31 #include "gdkmarshalers.h"
32 #include "gdkscreen.h"
40 * @Short_description: Controls the keyboard/mouse pointer grabs and a set of <type>GdkScreen</type>s
43 * #GdkDisplay objects purpose are two fold:
46 * To grab/ungrab keyboard focus and mouse pointer
49 * To manage and provide information about the #GdkScreen(s)
50 * available for this #GdkDisplay
54 * #GdkDisplay objects are the GDK representation of the X Display which can be
55 * described as <emphasis>a workstation consisting of a keyboard a pointing
56 * device (such as a mouse) and one or more screens</emphasis>.
57 * It is used to open and keep track of various #GdkScreen objects currently
58 * instanciated by the application. It is also used to grab and release the keyboard
59 * and the mouse pointer.
69 static void gdk_display_dispose (GObject *object);
70 static void gdk_display_finalize (GObject *object);
72 static void multihead_get_device_state (GdkDisplay *display,
77 GdkModifierType *mask);
78 static GdkWindow * multihead_window_get_device_position (GdkDisplay *display,
83 GdkModifierType *mask);
84 static GdkWindow * multihead_window_at_device_position (GdkDisplay *display,
89 static void multihead_default_get_pointer (GdkDisplay *display,
93 GdkModifierType *mask);
94 static GdkWindow * multihead_default_window_get_pointer (GdkDisplay *display,
98 GdkModifierType *mask);
99 static GdkWindow * multihead_default_window_at_pointer (GdkDisplay *display,
104 static void singlehead_get_pointer (GdkDisplay *display,
108 GdkModifierType *mask);
109 static GdkWindow* singlehead_window_get_pointer (GdkDisplay *display,
113 GdkModifierType *mask);
114 static GdkWindow* singlehead_window_at_pointer (GdkDisplay *display,
118 static GdkWindow* singlehead_default_window_get_pointer (GdkWindow *window,
121 GdkModifierType *mask);
122 static GdkWindow* singlehead_default_window_at_pointer (GdkScreen *screen,
125 static GdkWindow *gdk_window_real_window_get_device_position (GdkDisplay *display,
130 GdkModifierType *mask);
131 static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay *display,
136 static guint signals[LAST_SIGNAL] = { 0 };
138 static char *gdk_sm_client_id;
140 static const GdkDisplayDeviceHooks default_device_hooks = {
141 _gdk_windowing_get_device_state,
142 gdk_window_real_window_get_device_position,
143 gdk_display_real_get_window_at_device_position
146 static const GdkDisplayDeviceHooks multihead_pointer_hooks = {
147 multihead_get_device_state,
148 multihead_window_get_device_position,
149 multihead_window_at_device_position
152 static const GdkDisplayPointerHooks multihead_default_pointer_hooks = {
153 multihead_default_get_pointer,
154 multihead_default_window_get_pointer,
155 multihead_default_window_at_pointer
158 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
159 singlehead_get_pointer,
160 singlehead_window_get_pointer,
161 singlehead_window_at_pointer
164 static const GdkPointerHooks singlehead_default_pointer_hooks = {
165 singlehead_default_window_get_pointer,
166 singlehead_default_window_at_pointer
169 static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
170 static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
172 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
175 gdk_display_class_init (GdkDisplayClass *class)
177 GObjectClass *object_class = G_OBJECT_CLASS (class);
179 object_class->finalize = gdk_display_finalize;
180 object_class->dispose = gdk_display_dispose;
183 * GdkDisplay::opened:
184 * @display: the object on which the signal is emitted
186 * The ::opened signal is emitted when the connection to the windowing
187 * system for @display is opened.
190 g_signal_new (g_intern_static_string ("opened"),
191 G_OBJECT_CLASS_TYPE (object_class),
194 g_cclosure_marshal_VOID__VOID,
198 * GdkDisplay::closed:
199 * @display: the object on which the signal is emitted
200 * @is_error: %TRUE if the display was closed due to an error
202 * The ::closed signal is emitted when the connection to the windowing
203 * system for @display is closed.
208 g_signal_new (g_intern_static_string ("closed"),
209 G_OBJECT_CLASS_TYPE (object_class),
211 G_STRUCT_OFFSET (GdkDisplayClass, closed),
213 _gdk_marshal_VOID__BOOLEAN,
220 free_pointer_info (GdkPointerWindowInfo *info)
222 g_object_unref (info->toplevel_under_pointer);
223 g_slice_free (GdkPointerWindowInfo, info);
227 free_device_grab (GdkDeviceGrabInfo *info)
229 g_object_unref (info->window);
230 g_object_unref (info->native_window);
235 free_device_grabs_foreach (gpointer key,
241 g_list_foreach (list, (GFunc) free_device_grab, NULL);
248 device_removed_cb (GdkDeviceManager *device_manager,
252 g_hash_table_remove (display->multiple_click_info, device);
253 g_hash_table_remove (display->device_grabs, device);
254 g_hash_table_remove (display->pointers_info, device);
256 /* FIXME: change core pointer and remove from device list */
260 gdk_display_opened (GdkDisplay *display)
262 GdkDeviceManager *device_manager;
264 device_manager = gdk_display_get_device_manager (display);
266 g_signal_connect (device_manager, "device-removed",
267 G_CALLBACK (device_removed_cb), display);
271 gdk_display_init (GdkDisplay *display)
273 _gdk_displays = g_slist_prepend (_gdk_displays, display);
275 display->double_click_time = 250;
276 display->double_click_distance = 5;
278 display->device_hooks = &default_device_hooks;
280 display->device_grabs = g_hash_table_new (NULL, NULL);
281 display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
282 (GDestroyNotify) g_free);
284 display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
285 (GDestroyNotify) free_pointer_info);
287 display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
288 (GDestroyNotify) g_free);
290 g_signal_connect (display, "opened",
291 G_CALLBACK (gdk_display_opened), NULL);
295 gdk_display_dispose (GObject *object)
297 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
298 GdkDeviceManager *device_manager;
300 device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
302 g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
303 g_list_free (display->queued_events);
304 display->queued_events = NULL;
305 display->queued_tail = NULL;
307 _gdk_displays = g_slist_remove (_gdk_displays, object);
309 if (gdk_display_get_default () == display)
312 gdk_display_manager_set_default_display (gdk_display_manager_get(),
313 _gdk_displays->data);
315 gdk_display_manager_set_default_display (gdk_display_manager_get(),
321 /* this is to make it drop devices which may require using the X
322 * display and therefore can't be cleaned up in finalize.
323 * It will also disconnect device_removed_cb
325 g_object_run_dispose (G_OBJECT (display->device_manager));
328 G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
332 gdk_display_finalize (GObject *object)
334 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
336 g_hash_table_foreach_remove (display->device_grabs,
337 free_device_grabs_foreach,
339 g_hash_table_destroy (display->device_grabs);
341 g_hash_table_destroy (display->pointers_info);
342 g_hash_table_destroy (display->multiple_click_info);
344 if (display->device_manager)
345 g_object_unref (display->device_manager);
347 G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
352 * @display: a #GdkDisplay
354 * Closes the connection to the windowing system for the given display,
355 * and cleans up associated resources.
360 gdk_display_close (GdkDisplay *display)
362 g_return_if_fail (GDK_IS_DISPLAY (display));
364 if (!display->closed)
366 display->closed = TRUE;
368 g_signal_emit (display, signals[CLOSED], 0, FALSE);
369 g_object_run_dispose (G_OBJECT (display));
371 g_object_unref (display);
376 * gdk_display_is_closed:
377 * @display: a #GdkDisplay
379 * Finds out if the display has been closed.
381 * Returns: %TRUE if the display is closed.
386 gdk_display_is_closed (GdkDisplay *display)
388 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
390 return display->closed;
394 * gdk_display_get_event:
395 * @display: a #GdkDisplay
397 * Gets the next #GdkEvent to be processed for @display, fetching events from the
398 * windowing system if necessary.
400 * Return value: the next #GdkEvent to be processed, or %NULL if no events
401 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
406 gdk_display_get_event (GdkDisplay *display)
408 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
410 _gdk_events_queue (display);
411 return _gdk_event_unqueue (display);
415 * gdk_display_peek_event:
416 * @display: a #GdkDisplay
418 * Gets a copy of the first #GdkEvent in the @display's event queue, without
419 * removing the event from the queue. (Note that this function will
420 * not get more events from the windowing system. It only checks the events
421 * that have already been moved to the GDK event queue.)
423 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
424 * if no events are in the queue. The returned #GdkEvent should be freed with
430 gdk_display_peek_event (GdkDisplay *display)
434 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
436 tmp_list = _gdk_event_queue_find_first (display);
439 return gdk_event_copy (tmp_list->data);
445 * gdk_display_put_event:
446 * @display: a #GdkDisplay
447 * @event: a #GdkEvent.
449 * Appends a copy of the given event onto the front of the event
450 * queue for @display.
455 gdk_display_put_event (GdkDisplay *display,
456 const GdkEvent *event)
458 g_return_if_fail (GDK_IS_DISPLAY (display));
459 g_return_if_fail (event != NULL);
461 _gdk_event_queue_append (display, gdk_event_copy (event));
462 /* If the main loop is blocking in a different thread, wake it up */
463 g_main_context_wakeup (NULL);
467 * gdk_display_pointer_ungrab:
468 * @display: a #GdkDisplay.
469 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
471 * Release any pointer grab.
475 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
479 gdk_display_pointer_ungrab (GdkDisplay *display,
482 GdkDeviceManager *device_manager;
483 GList *devices, *dev;
486 g_return_if_fail (GDK_IS_DISPLAY (display));
488 device_manager = gdk_display_get_device_manager (display);
489 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
491 /* FIXME: Should this be generic to all backends? */
492 /* FIXME: What happens with extended devices? */
493 for (dev = devices; dev; dev = dev->next)
497 if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
500 gdk_device_ungrab (device, time_);
503 g_list_free (devices);
507 * gdk_pointer_ungrab:
508 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
509 * timestamp is available.
511 * Ungrabs the pointer on the default display, if it is grabbed by this
514 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
518 gdk_pointer_ungrab (guint32 time)
520 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
524 * gdk_pointer_is_grabbed:
526 * Returns %TRUE if the pointer on the default display is currently
527 * grabbed by this application.
529 * Note that this does not take the inmplicit pointer grab on button
530 * presses into account.
532 * Return value: %TRUE if the pointer is currently grabbed by this application.
534 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
537 gdk_pointer_is_grabbed (void)
539 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
543 * gdk_display_keyboard_ungrab:
544 * @display: a #GdkDisplay.
545 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
547 * Release any keyboard grab
551 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
555 gdk_display_keyboard_ungrab (GdkDisplay *display,
558 GdkDeviceManager *device_manager;
559 GList *devices, *dev;
562 g_return_if_fail (GDK_IS_DISPLAY (display));
564 device_manager = gdk_display_get_device_manager (display);
565 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
567 /* FIXME: Should this be generic to all backends? */
568 /* FIXME: What happens with extended devices? */
569 for (dev = devices; dev; dev = dev->next)
573 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
576 gdk_device_ungrab (device, time);
579 g_list_free (devices);
583 * gdk_keyboard_ungrab:
584 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
585 * timestamp is available.
587 * Ungrabs the keyboard on the default display, if it is grabbed by this
590 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
594 gdk_keyboard_ungrab (guint32 time)
596 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
602 * Emits a short beep on the default display.
607 gdk_display_beep (gdk_display_get_default ());
611 * gdk_event_send_client_message:
612 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
613 * @winid: the window to send the X ClientMessage event to.
615 * Sends an X ClientMessage event to a given window (which must be
616 * on the default #GdkDisplay.)
617 * This could be used for communicating between different applications,
618 * though the amount of data is limited to 20 bytes.
620 * Return value: non-zero on success.
623 gdk_event_send_client_message (GdkEvent *event,
624 GdkNativeWindow winid)
626 g_return_val_if_fail (event != NULL, FALSE);
628 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
633 * gdk_event_send_clientmessage_toall:
634 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
636 * Sends an X ClientMessage event to all toplevel windows on the default
639 * Toplevel windows are determined by checking for the WM_STATE property, as
640 * described in the Inter-Client Communication Conventions Manual (ICCCM).
641 * If no windows are found with the WM_STATE property set, the message is sent
642 * to all children of the root window.
645 gdk_event_send_clientmessage_toall (GdkEvent *event)
647 g_return_if_fail (event != NULL);
649 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
653 * gdk_device_get_core_pointer:
655 * Returns the core pointer device for the default display.
657 * Return value: (transfer none): the core pointer device; this is owned
658 * by the display and should not be freed.
660 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
661 * gdk_event_get_device() if a #GdkEvent with pointer device
662 * information is available.
665 gdk_device_get_core_pointer (void)
667 return gdk_display_get_core_pointer (gdk_display_get_default ());
671 * gdk_display_get_core_pointer:
672 * @display: a #GdkDisplay
674 * Returns the core pointer device for the given display
676 * Return value: (transfer none): the core pointer device; this is owned by the
677 * display and should not be freed.
681 * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
682 * gdk_event_get_device() if a #GdkEvent with device
683 * information is available.
686 gdk_display_get_core_pointer (GdkDisplay *display)
688 return display->core_pointer;
692 * gdk_set_sm_client_id:
693 * @sm_client_id: the client id assigned by the session manager when the
694 * connection was opened, or %NULL to remove the property.
696 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
697 * the window manager can save the application's state using the X11R6 ICCCM
698 * session management protocol.
700 * See the X Session Management Library documentation for more information on
701 * session management and the Inter-Client Communication Conventions Manual
702 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
703 * (Both documents are part of the X Window System distribution.)
706 gdk_set_sm_client_id (const gchar* sm_client_id)
708 GSList *displays, *tmp_list;
710 g_free (gdk_sm_client_id);
711 gdk_sm_client_id = g_strdup (sm_client_id);
713 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
714 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
715 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
717 g_slist_free (displays);
721 * _gdk_get_sm_client_id:
723 * Gets the client ID set with gdk_set_sm_client_id(), if any.
725 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
726 * has never been called.
729 _gdk_get_sm_client_id (void)
731 return gdk_sm_client_id;
735 _gdk_display_enable_motion_hints (GdkDisplay *display,
738 gulong *device_serial, serial;
740 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
744 device_serial = g_new0 (gulong, 1);
745 *device_serial = G_MAXULONG;
746 g_hash_table_insert (display->motion_hint_info, device, device_serial);
749 if (*device_serial != 0)
751 serial = _gdk_windowing_window_get_next_serial (display);
752 /* We might not actually generate the next request, so
753 make sure this triggers always, this may cause it to
754 trigger slightly too early, but this is just a hint
758 if (serial < *device_serial)
759 *device_serial = serial;
764 * gdk_display_get_device_state:
765 * @display: a #GdkDisplay.
766 * @device: device to query status to.
767 * @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
768 * the @device is on, or %NULL.
769 * @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
770 * @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
771 * @mask: (out) (allow-none): location to store current modifier mask for @device, or %NULL.
773 * Gets the current location and state of @device for a given display.
778 gdk_display_get_device_state (GdkDisplay *display,
783 GdkModifierType *mask)
785 GdkScreen *tmp_screen;
787 GdkModifierType tmp_mask;
789 g_return_if_fail (GDK_IS_DISPLAY (display));
790 g_return_if_fail (GDK_IS_DEVICE (device));
792 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
795 *screen = tmp_screen;
805 * gdk_display_get_window_at_device_position:
806 * @display: a #GdkDisplay.
807 * @device: #GdkDevice to query info to.
808 * @win_x: (out) (allow-none): return location for the X coordinate of the device location,
809 * relative to the window origin, or %NULL.
810 * @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
811 * relative to the window origin, or %NULL.
813 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
814 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
816 * Returns: (transfer none): the #GdkWindow under the device position, or %NULL.
821 gdk_display_get_window_at_device_position (GdkDisplay *display,
829 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
830 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
832 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
843 * gdk_display_set_device_hooks:
844 * @display: a #GdkDisplay.
845 * @new_hooks: (allow-none): a table of pointers to functions for getting quantities related
846 * to all devices position, or %NULL to restore the default table.
848 * This function allows for hooking into the operation of getting the current location of any
849 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
850 * an event recorder. Applications should never have any reason to use this facility.
852 * Returns: (transfer none): The previous device hook table.
856 GdkDisplayDeviceHooks *
857 gdk_display_set_device_hooks (GdkDisplay *display,
858 const GdkDisplayDeviceHooks *new_hooks)
860 const GdkDisplayDeviceHooks *result;
862 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
863 result = display->device_hooks;
866 display->device_hooks = new_hooks;
868 display->device_hooks = &default_device_hooks;
870 return (GdkDisplayDeviceHooks *) result;
874 * gdk_display_get_pointer:
875 * @display: a #GdkDisplay
876 * @screen: (allow-none): location to store the screen that the
877 * cursor is on, or %NULL.
878 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
879 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
880 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
882 * Gets the current location of the pointer and the current modifier
883 * mask for a given display.
887 * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
890 gdk_display_get_pointer (GdkDisplay *display,
894 GdkModifierType *mask)
896 g_return_if_fail (GDK_IS_DISPLAY (display));
898 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
902 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
910 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
912 /* This might need corrections, as the native window returned
913 may contain client side children */
918 window = _gdk_window_find_descendant_at (window,
921 x = floor (xx + 0.5);
922 y = floor (yy + 0.5);
932 gdk_window_real_window_get_device_position (GdkDisplay *display,
937 GdkModifierType *mask)
940 GdkModifierType tmp_mask;
941 gboolean normal_child;
943 normal_child = GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_device_state (window,
947 /* We got the coords on the impl, convert to the window */
948 tmpx -= window->abs_x;
949 tmpy -= window->abs_y;
959 return _gdk_window_find_child_at (window, tmpx, tmpy);
964 * gdk_display_get_window_at_pointer:
965 * @display: a #GdkDisplay
966 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
967 * to the window origin, or %NULL
968 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
969 & to the window origin, or %NULL
971 * Obtains the window underneath the mouse pointer, returning the location
972 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
973 * if the window under the mouse pointer is not known to GDK (for example,
974 * belongs to another application).
976 * Returns: (transfer none): the window under the mouse pointer, or %NULL
980 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
983 gdk_display_get_window_at_pointer (GdkDisplay *display,
987 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
989 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
993 multihead_get_device_state (GdkDisplay *display,
998 GdkModifierType *mask)
1000 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
1004 multihead_window_get_device_position (GdkDisplay *display,
1009 GdkModifierType *mask)
1011 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
1015 multihead_window_at_device_position (GdkDisplay *display,
1020 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
1024 multihead_default_get_pointer (GdkDisplay *display,
1028 GdkModifierType *mask)
1030 return _gdk_windowing_get_device_state (display,
1031 display->core_pointer,
1032 screen, x, y, mask);
1036 multihead_default_window_get_pointer (GdkDisplay *display,
1040 GdkModifierType *mask)
1042 return gdk_window_real_window_get_device_position (display,
1043 display->core_pointer,
1044 window, x, y, mask);
1048 multihead_default_window_at_pointer (GdkDisplay *display,
1052 return gdk_display_real_get_window_at_device_position (display,
1053 display->core_pointer,
1058 * gdk_display_set_pointer_hooks:
1059 * @display: a #GdkDisplay
1060 * @new_hooks: (allow-none): a table of pointers to functions for getting
1061 * quantities related to the current pointer position,
1062 * or %NULL to restore the default table.
1064 * This function allows for hooking into the operation
1065 * of getting the current location of the pointer on a particular
1066 * display. This is only useful for such low-level tools as an
1067 * event recorder. Applications should never have any
1068 * reason to use this facility.
1070 * Return value: (transfer none): the previous pointer hook table
1074 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1076 GdkDisplayPointerHooks *
1077 gdk_display_set_pointer_hooks (GdkDisplay *display,
1078 const GdkDisplayPointerHooks *new_hooks)
1080 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1082 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1085 multihead_current_pointer_hooks = new_hooks;
1087 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1089 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1091 return (GdkDisplayPointerHooks *)result;
1095 singlehead_get_pointer (GdkDisplay *display,
1099 GdkModifierType *mask)
1101 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1102 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1104 *screen = default_screen;
1106 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1110 singlehead_window_get_pointer (GdkDisplay *display,
1114 GdkModifierType *mask)
1116 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1120 singlehead_window_at_pointer (GdkDisplay *display,
1124 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1126 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1131 singlehead_default_window_get_pointer (GdkWindow *window,
1134 GdkModifierType *mask)
1136 GdkDisplay *display;
1138 display = gdk_window_get_display (window);
1140 return gdk_window_real_window_get_device_position (display,
1141 display->core_pointer,
1142 window, x, y, mask);
1146 singlehead_default_window_at_pointer (GdkScreen *screen,
1150 GdkDisplay *display;
1152 display = gdk_screen_get_display (screen);
1154 return gdk_display_real_get_window_at_device_position (display,
1155 display->core_pointer,
1160 * gdk_set_pointer_hooks:
1161 * @new_hooks: (allow-none): a table of pointers to functions for getting
1162 * quantities related to the current pointer position,
1163 * or %NULL to restore the default table.
1165 * This function allows for hooking into the operation
1166 * of getting the current location of the pointer. This
1167 * is only useful for such low-level tools as an
1168 * event recorder. Applications should never have any
1169 * reason to use this facility.
1171 * This function is not multihead safe. For multihead operation,
1172 * see gdk_display_set_pointer_hooks().
1174 * Return value: the previous pointer hook table
1176 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1179 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1181 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1184 singlehead_current_pointer_hooks = new_hooks;
1186 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1188 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1189 &singlehead_pointer_hooks);
1191 return (GdkPointerHooks *)result;
1195 generate_grab_broken_event (GdkWindow *window,
1198 GdkWindow *grab_window)
1200 g_return_if_fail (window != NULL);
1202 if (!GDK_WINDOW_DESTROYED (window))
1206 event = gdk_event_new (GDK_GRAB_BROKEN);
1207 event->grab_broken.window = g_object_ref (window);
1208 event->grab_broken.send_event = FALSE;
1209 event->grab_broken.implicit = implicit;
1210 event->grab_broken.grab_window = grab_window;
1211 gdk_event_set_device (event, device);
1212 event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1214 gdk_event_put (event);
1215 gdk_event_free (event);
1220 _gdk_display_get_last_device_grab (GdkDisplay *display,
1225 l = g_hash_table_lookup (display->device_grabs, device);
1229 l = g_list_last (l);
1237 _gdk_display_add_device_grab (GdkDisplay *display,
1240 GdkWindow *native_window,
1241 GdkGrabOwnership grab_ownership,
1242 gboolean owner_events,
1243 GdkEventMask event_mask,
1244 unsigned long serial_start,
1248 GdkDeviceGrabInfo *info, *other_info;
1251 info = g_new0 (GdkDeviceGrabInfo, 1);
1253 info->window = g_object_ref (window);
1254 info->native_window = g_object_ref (native_window);
1255 info->serial_start = serial_start;
1256 info->serial_end = G_MAXULONG;
1257 info->owner_events = owner_events;
1258 info->event_mask = event_mask;
1260 info->implicit = implicit;
1261 info->ownership = grab_ownership;
1263 grabs = g_hash_table_lookup (display->device_grabs, device);
1265 /* Find the first grab that has a larger start time (if any) and insert
1266 * before that. I.E we insert after already existing grabs with same
1268 for (l = grabs; l != NULL; l = l->next)
1270 other_info = l->data;
1272 if (info->serial_start < other_info->serial_start)
1276 grabs = g_list_insert_before (grabs, l, info);
1278 /* Make sure the new grab end before next grab */
1281 other_info = l->data;
1282 info->serial_end = other_info->serial_start;
1285 /* Find any previous grab and update its end time */
1286 l = g_list_find (grabs, info);
1290 other_info = l->data;
1291 other_info->serial_end = serial_start;
1294 g_hash_table_insert (display->device_grabs, device, grabs);
1299 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1300 This function splits things into two calls if needed, converting the
1301 coordinates to the right toplevel */
1303 synthesize_crossing_events (GdkDisplay *display,
1305 GdkDevice *source_device,
1306 GdkWindow *src_window,
1307 GdkWindow *dest_window,
1308 GdkCrossingMode crossing_mode,
1312 GdkWindow *src_toplevel, *dest_toplevel;
1313 GdkModifierType state;
1316 /* We use the native crossing events if all native */
1317 if (_gdk_native_windows)
1321 src_toplevel = gdk_window_get_toplevel (src_window);
1323 src_toplevel = NULL;
1325 dest_toplevel = gdk_window_get_toplevel (dest_window);
1327 dest_toplevel = NULL;
1329 if (src_toplevel == NULL && dest_toplevel == NULL)
1332 if (src_toplevel == NULL ||
1333 src_toplevel == dest_toplevel)
1335 /* Same toplevels */
1336 gdk_window_get_pointer (dest_toplevel,
1338 _gdk_synthesize_crossing_events (display,
1341 device, source_device,
1348 else if (dest_toplevel == NULL)
1350 gdk_window_get_pointer (src_toplevel,
1352 _gdk_synthesize_crossing_events (display,
1355 device, source_device,
1364 /* Different toplevels */
1365 gdk_window_get_pointer (src_toplevel,
1367 _gdk_synthesize_crossing_events (display,
1370 device, source_device,
1376 gdk_window_get_pointer (dest_toplevel,
1378 _gdk_synthesize_crossing_events (display,
1381 device, source_device,
1391 get_current_toplevel (GdkDisplay *display,
1395 GdkModifierType *state_out)
1397 GdkWindow *pointer_window;
1399 GdkModifierType state;
1401 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1403 if (pointer_window != NULL &&
1404 (GDK_WINDOW_DESTROYED (pointer_window) ||
1405 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1406 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1407 pointer_window = NULL;
1412 return pointer_window;
1416 switch_to_pointer_grab (GdkDisplay *display,
1418 GdkDevice *source_device,
1419 GdkDeviceGrabInfo *grab,
1420 GdkDeviceGrabInfo *last_grab,
1424 GdkWindow *src_window, *pointer_window, *new_toplevel;
1425 GdkPointerWindowInfo *info;
1427 GdkModifierType state;
1430 /* Temporarily unset pointer to make sure we send the crossing events below */
1431 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1432 g_hash_table_steal (display->device_grabs, device);
1433 info = _gdk_display_get_pointer_info (display, device);
1437 /* New grab is in effect */
1439 /* We need to generate crossing events for the grab.
1440 * However, there are never any crossing events for implicit grabs
1441 * TODO: ... Actually, this could happen if the pointer window
1442 * doesn't have button mask so a parent gets the event...
1444 if (!grab->implicit)
1446 /* We send GRAB crossing events from the window under the pointer to the
1447 grab window. Except if there is an old grab then we start from that */
1449 src_window = last_grab->window;
1451 src_window = info->window_under_pointer;
1453 if (src_window != grab->window)
1454 synthesize_crossing_events (display, device, source_device,
1455 src_window, grab->window,
1456 GDK_CROSSING_GRAB, time, serial);
1458 /* !owner_event Grabbing a window that we're not inside, current status is
1459 now NULL (i.e. outside grabbed window) */
1460 if (!grab->owner_events && info->window_under_pointer != grab->window)
1461 _gdk_display_set_window_under_pointer (display, device, NULL);
1464 grab->activated = TRUE;
1469 new_toplevel = NULL;
1471 if (grab == NULL /* ungrab */ ||
1472 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1474 /* We force check what window we're in, and update the toplevel_under_pointer info,
1475 * as that won't get told of this change with toplevel enter events.
1477 if (info->toplevel_under_pointer)
1478 g_object_unref (info->toplevel_under_pointer);
1479 info->toplevel_under_pointer = NULL;
1481 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1484 /* w is now toplevel and x,y in toplevel coords */
1485 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1486 info->toplevel_x = x;
1487 info->toplevel_y = y;
1488 info->state = state;
1492 if (grab == NULL) /* Ungrabbed, send events */
1494 pointer_window = NULL;
1497 /* Find (possibly virtual) child window */
1499 _gdk_window_find_descendant_at (new_toplevel,
1504 if (pointer_window != last_grab->window)
1505 synthesize_crossing_events (display, device, source_device,
1506 last_grab->window, pointer_window,
1507 GDK_CROSSING_UNGRAB, time, serial);
1509 /* We're now ungrabbed, update the window_under_pointer */
1510 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1514 g_hash_table_insert (display->device_grabs, device, old_grabs);
1518 _gdk_display_device_grab_update (GdkDisplay *display,
1520 GdkDevice *source_device,
1521 gulong current_serial)
1523 GdkDeviceGrabInfo *current_grab, *next_grab;
1527 time = display->last_event_time;
1528 grabs = g_hash_table_lookup (display->device_grabs, device);
1530 while (grabs != NULL)
1532 current_grab = grabs->data;
1534 if (current_grab->serial_start > current_serial)
1535 return; /* Hasn't started yet */
1537 if (current_grab->serial_end > current_serial)
1539 /* This one hasn't ended yet.
1540 its the currently active one or scheduled to be active */
1542 if (!current_grab->activated)
1544 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1545 switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
1554 /* This is the next active grab */
1555 next_grab = grabs->next->data;
1557 if (next_grab->serial_start > current_serial)
1558 next_grab = NULL; /* Actually its not yet active */
1561 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1562 (next_grab != NULL && current_grab->window != next_grab->window))
1563 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1565 current_grab->implicit,
1566 next_grab? next_grab->window : NULL);
1568 /* Remove old grab */
1569 grabs = g_list_delete_link (grabs, grabs);
1570 g_hash_table_insert (display->device_grabs, device, grabs);
1572 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1573 switch_to_pointer_grab (display, device, source_device,
1574 next_grab, current_grab,
1575 time, current_serial);
1577 free_device_grab (current_grab);
1582 grab_list_find (GList *grabs,
1585 GdkDeviceGrabInfo *grab;
1591 if (serial >= grab->serial_start && serial < grab->serial_end)
1594 grabs = grabs->next;
1601 find_device_grab (GdkDisplay *display,
1607 l = g_hash_table_lookup (display->device_grabs, device);
1608 return grab_list_find (l, serial);
1612 _gdk_display_has_device_grab (GdkDisplay *display,
1618 l = find_device_grab (display, device, serial);
1625 /* Returns true if last grab was ended
1626 * If if_child is non-NULL, end the grab only if the grabbed
1627 * window is the same as if_child or a descendant of it */
1629 _gdk_display_end_device_grab (GdkDisplay *display,
1632 GdkWindow *if_child,
1635 GdkDeviceGrabInfo *grab;
1638 l = find_device_grab (display, device, serial);
1645 (if_child == NULL ||
1646 _gdk_window_event_parent_of (if_child, grab->window)))
1648 grab->serial_end = serial;
1649 grab->implicit_ungrab = implicit;
1650 return l->next == NULL;
1656 /* Returns TRUE if device events are not blocked by any grab */
1658 _gdk_display_check_grab_ownership (GdkDisplay *display,
1662 GHashTableIter iter;
1663 gpointer key, value;
1664 GdkGrabOwnership higher_ownership, device_ownership;
1665 gboolean device_is_keyboard;
1667 g_hash_table_iter_init (&iter, display->device_grabs);
1668 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1669 device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1671 while (g_hash_table_iter_next (&iter, &key, &value))
1673 GdkDeviceGrabInfo *grab;
1679 grabs = grab_list_find (grabs, serial);
1684 /* Discard device if it's not of the same type */
1685 if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) ||
1686 (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD))
1692 device_ownership = grab->ownership;
1695 if (grab->ownership > higher_ownership)
1696 higher_ownership = grab->ownership;
1700 if (higher_ownership > device_ownership)
1702 /* There's a higher priority ownership
1703 * going on for other device(s)
1711 GdkPointerWindowInfo *
1712 _gdk_display_get_pointer_info (GdkDisplay *display,
1715 GdkPointerWindowInfo *info;
1717 if (G_UNLIKELY (!device))
1720 info = g_hash_table_lookup (display->pointers_info, device);
1722 if (G_UNLIKELY (!info))
1724 info = g_slice_new0 (GdkPointerWindowInfo);
1725 g_hash_table_insert (display->pointers_info, device, info);
1732 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1733 GdkDisplayPointerInfoForeach func,
1736 GHashTableIter iter;
1737 gpointer key, value;
1739 g_hash_table_iter_init (&iter, display->pointers_info);
1741 while (g_hash_table_iter_next (&iter, &key, &value))
1743 GdkPointerWindowInfo *info = value;
1744 GdkDevice *device = key;
1746 (func) (display, device, info, user_data);
1751 * gdk_device_grab_info_libgtk_only:
1752 * @display: the display for which to get the grab information
1753 * @device: device to get the grab information from
1754 * @grab_window: (out) (transfer none): location to store current grab window
1755 * @owner_events: (out): location to store boolean indicating whether
1756 * the @owner_events flag to gdk_keyboard_grab() or
1757 * gdk_pointer_grab() was %TRUE.
1759 * Determines information about the current keyboard grab.
1760 * This is not public API and must not be used by applications.
1762 * Return value: %TRUE if this application currently has the
1766 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1768 GdkWindow **grab_window,
1769 gboolean *owner_events)
1771 GdkDeviceGrabInfo *info;
1773 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1774 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1776 info = _gdk_display_get_last_device_grab (display, device);
1781 *grab_window = info->window;
1783 *owner_events = info->owner_events;
1792 * gdk_display_pointer_is_grabbed:
1793 * @display: a #GdkDisplay
1795 * Test if the pointer is grabbed.
1797 * Returns: %TRUE if an active X pointer grab is in effect
1801 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1804 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1806 GdkDeviceManager *device_manager;
1807 GList *devices, *dev;
1810 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1812 device_manager = gdk_display_get_device_manager (display);
1813 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1815 for (dev = devices; dev; dev = dev->next)
1819 if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
1820 gdk_display_device_is_grabbed (display, device))
1828 * gdk_display_device_is_grabbed:
1829 * @display: a #GdkDisplay
1830 * @device: a #GdkDevice
1832 * Returns %TRUE if there is an ongoing grab on @device for @display.
1834 * Returns: %TRUE if there is a grab in effect for @device.
1837 gdk_display_device_is_grabbed (GdkDisplay *display,
1840 GdkDeviceGrabInfo *info;
1842 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1843 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1845 /* What we're interested in is the steady state (ie last grab),
1846 because we're interested e.g. if we grabbed so that we
1847 can ungrab, even if our grab is not active just yet. */
1848 info = _gdk_display_get_last_device_grab (display, device);
1850 return (info && !info->implicit);
1854 * gdk_display_get_device_manager:
1855 * @display: a #GdkDisplay.
1857 * Returns the #GdkDeviceManager associated to @display.
1859 * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is
1860 * owned by GDK and must not be freed or unreferenced.
1865 gdk_display_get_device_manager (GdkDisplay *display)
1867 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1869 return display->device_manager;