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_get_event:
343 * @display: a #GdkDisplay
345 * Gets the next #GdkEvent to be processed for @display, fetching events from the
346 * windowing system if necessary.
348 * Return value: the next #GdkEvent to be processed, or %NULL if no events
349 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
354 gdk_display_get_event (GdkDisplay *display)
356 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
358 _gdk_events_queue (display);
359 return _gdk_event_unqueue (display);
363 * gdk_display_peek_event:
364 * @display: a #GdkDisplay
366 * Gets a copy of the first #GdkEvent in the @display's event queue, without
367 * removing the event from the queue. (Note that this function will
368 * not get more events from the windowing system. It only checks the events
369 * that have already been moved to the GDK event queue.)
371 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
372 * if no events are in the queue. The returned #GdkEvent should be freed with
378 gdk_display_peek_event (GdkDisplay *display)
382 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
384 tmp_list = _gdk_event_queue_find_first (display);
387 return gdk_event_copy (tmp_list->data);
393 * gdk_display_put_event:
394 * @display: a #GdkDisplay
395 * @event: a #GdkEvent.
397 * Appends a copy of the given event onto the front of the event
398 * queue for @display.
403 gdk_display_put_event (GdkDisplay *display,
404 const GdkEvent *event)
406 g_return_if_fail (GDK_IS_DISPLAY (display));
407 g_return_if_fail (event != NULL);
409 _gdk_event_queue_append (display, gdk_event_copy (event));
410 /* If the main loop is blocking in a different thread, wake it up */
411 g_main_context_wakeup (NULL);
415 * gdk_display_pointer_ungrab:
416 * @display: a #GdkDisplay.
417 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
419 * Release any pointer grab.
423 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
427 gdk_display_pointer_ungrab (GdkDisplay *display,
430 GdkDeviceManager *device_manager;
431 GList *devices, *dev;
434 g_return_if_fail (GDK_IS_DISPLAY (display));
436 device_manager = gdk_display_get_device_manager (display);
437 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
439 /* FIXME: Should this be generic to all backends? */
440 /* FIXME: What happens with extended devices? */
441 for (dev = devices; dev; dev = dev->next)
445 if (device->source != GDK_SOURCE_MOUSE)
448 gdk_device_ungrab (device, time_);
451 g_list_free (devices);
455 * gdk_pointer_ungrab:
456 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
457 * timestamp is available.
459 * Ungrabs the pointer on the default display, if it is grabbed by this
462 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
466 gdk_pointer_ungrab (guint32 time)
468 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
472 * gdk_pointer_is_grabbed:
474 * Returns %TRUE if the pointer on the default display is currently
475 * grabbed by this application.
477 * Note that this does not take the inmplicit pointer grab on button
478 * presses into account.
480 * Return value: %TRUE if the pointer is currently grabbed by this application.
482 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
485 gdk_pointer_is_grabbed (void)
487 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
491 * gdk_display_keyboard_ungrab:
492 * @display: a #GdkDisplay.
493 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
495 * Release any keyboard grab
499 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
503 gdk_display_keyboard_ungrab (GdkDisplay *display,
506 GdkDeviceManager *device_manager;
507 GList *devices, *dev;
510 g_return_if_fail (GDK_IS_DISPLAY (display));
512 device_manager = gdk_display_get_device_manager (display);
513 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
515 /* FIXME: Should this be generic to all backends? */
516 /* FIXME: What happens with extended devices? */
517 for (dev = devices; dev; dev = dev->next)
521 if (device->source != GDK_SOURCE_KEYBOARD)
524 gdk_device_ungrab (device, time);
527 g_list_free (devices);
531 * gdk_keyboard_ungrab:
532 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
533 * timestamp is available.
535 * Ungrabs the keyboard on the default display, if it is grabbed by this
538 * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
542 gdk_keyboard_ungrab (guint32 time)
544 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
550 * Emits a short beep on the default display.
555 gdk_display_beep (gdk_display_get_default ());
559 * gdk_event_send_client_message:
560 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
561 * @winid: the window to send the X ClientMessage event to.
563 * Sends an X ClientMessage event to a given window (which must be
564 * on the default #GdkDisplay.)
565 * This could be used for communicating between different applications,
566 * though the amount of data is limited to 20 bytes.
568 * Return value: non-zero on success.
571 gdk_event_send_client_message (GdkEvent *event,
572 GdkNativeWindow winid)
574 g_return_val_if_fail (event != NULL, FALSE);
576 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
581 * gdk_event_send_clientmessage_toall:
582 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
584 * Sends an X ClientMessage event to all toplevel windows on the default
587 * Toplevel windows are determined by checking for the WM_STATE property, as
588 * described in the Inter-Client Communication Conventions Manual (ICCCM).
589 * If no windows are found with the WM_STATE property set, the message is sent
590 * to all children of the root window.
593 gdk_event_send_clientmessage_toall (GdkEvent *event)
595 g_return_if_fail (event != NULL);
597 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
601 * gdk_device_get_core_pointer:
603 * Returns the core pointer device for the default display.
605 * Return value: the core pointer device; this is owned by the
606 * display and should not be freed.
608 * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
609 * gdk_event_get_device() if a #GdkEvent with pointer device
610 * information is available.
613 gdk_device_get_core_pointer (void)
615 return gdk_display_get_core_pointer (gdk_display_get_default ());
619 * gdk_display_get_core_pointer:
620 * @display: a #GdkDisplay
622 * Returns the core pointer device for the given display
624 * Return value: the core pointer device; this is owned by the
625 * display and should not be freed.
629 * Deprecated: 3.0: Use gdk_display_get_client_pointer() instead, or
630 * gdk_event_get_device() if a #GdkEvent with device
631 * information is available.
634 gdk_display_get_core_pointer (GdkDisplay *display)
636 return display->core_pointer;
640 * gdk_set_sm_client_id:
641 * @sm_client_id: the client id assigned by the session manager when the
642 * connection was opened, or %NULL to remove the property.
644 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
645 * the window manager can save the application's state using the X11R6 ICCCM
646 * session management protocol.
648 * See the X Session Management Library documentation for more information on
649 * session management and the Inter-Client Communication Conventions Manual
650 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
651 * (Both documents are part of the X Window System distribution.)
654 gdk_set_sm_client_id (const gchar* sm_client_id)
656 GSList *displays, *tmp_list;
658 g_free (gdk_sm_client_id);
659 gdk_sm_client_id = g_strdup (sm_client_id);
661 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
662 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
663 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
665 g_slist_free (displays);
669 * _gdk_get_sm_client_id:
671 * Gets the client ID set with gdk_set_sm_client_id(), if any.
673 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
674 * has never been called.
677 _gdk_get_sm_client_id (void)
679 return gdk_sm_client_id;
683 _gdk_display_enable_motion_hints (GdkDisplay *display,
686 gulong *device_serial, serial;
688 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
692 device_serial = g_new0 (gulong, 1);
693 *device_serial = G_MAXULONG;
694 g_hash_table_insert (display->motion_hint_info, device, device_serial);
697 if (*device_serial != 0)
699 serial = _gdk_windowing_window_get_next_serial (display);
700 /* We might not actually generate the next request, so
701 make sure this triggers always, this may cause it to
702 trigger slightly too early, but this is just a hint
706 if (serial < *device_serial)
707 *device_serial = serial;
712 * gdk_display_get_device_state:
713 * @display: a #GdkDisplay.
714 * @device: device to query status to.
715 * @screen: location to store the #GdkScreen the @device is on, or %NULL.
716 * @x: location to store root window X coordinate of @device, or %NULL.
717 * @y: location to store root window Y coordinate of @device, or %NULL.
718 * @mask: location to store current modifier mask for @device, or %NULL.
720 * Gets the current location and state of @device for a given display.
725 gdk_display_get_device_state (GdkDisplay *display,
730 GdkModifierType *mask)
732 GdkScreen *tmp_screen;
734 GdkModifierType tmp_mask;
736 g_return_if_fail (GDK_IS_DISPLAY (display));
737 g_return_if_fail (GDK_IS_DEVICE (device));
739 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
742 *screen = tmp_screen;
752 * gdk_display_get_window_at_device_position:
753 * @display: a #GdkDisplay.
754 * @device: #GdkDevice to query info to.
755 * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
756 * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
758 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
759 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
761 * Returns: the #GdkWindow under the device position, or %NULL.
766 gdk_display_get_window_at_device_position (GdkDisplay *display,
774 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
775 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
777 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
788 * gdk_display_set_device_hooks:
789 * @display: a #GdkDisplay.
790 * @new_hooks: a table of pointers to functions for getting quantities related to all
791 * devices position, or %NULL to restore the default table.
793 * This function allows for hooking into the operation of getting the current location of any
794 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
795 * an event recorder. Applications should never have any reason to use this facility.
797 * Returns: The previous device hook table.
801 GdkDisplayDeviceHooks *
802 gdk_display_set_device_hooks (GdkDisplay *display,
803 const GdkDisplayDeviceHooks *new_hooks)
805 const GdkDisplayDeviceHooks *result;
807 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
808 result = display->device_hooks;
811 display->device_hooks = new_hooks;
813 display->device_hooks = &default_device_hooks;
815 return (GdkDisplayDeviceHooks *) result;
819 * gdk_display_get_pointer:
820 * @display: a #GdkDisplay
821 * @screen: (allow-none): location to store the screen that the
822 * cursor is on, or %NULL.
823 * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL.
824 * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL.
825 * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
827 * Gets the current location of the pointer and the current modifier
828 * mask for a given display.
832 * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
835 gdk_display_get_pointer (GdkDisplay *display,
839 GdkModifierType *mask)
841 g_return_if_fail (GDK_IS_DISPLAY (display));
843 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
847 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
855 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
857 /* This might need corrections, as the native window returned
858 may contain client side children */
863 window = _gdk_window_find_descendant_at (window,
866 x = floor (xx + 0.5);
867 y = floor (yy + 0.5);
877 gdk_window_real_window_get_device_position (GdkDisplay *display,
882 GdkModifierType *mask)
884 GdkWindowObject *private;
886 GdkModifierType tmp_mask;
887 gboolean normal_child;
889 private = (GdkWindowObject *) window;
891 normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
895 /* We got the coords on the impl, convert to the window */
896 tmpx -= private->abs_x;
897 tmpy -= private->abs_y;
907 return _gdk_window_find_child_at (window, tmpx, tmpy);
912 * gdk_display_get_window_at_pointer:
913 * @display: a #GdkDisplay
914 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
915 * to the window origin, or %NULL
916 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
917 & to the window origin, or %NULL
919 * Obtains the window underneath the mouse pointer, returning the location
920 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
921 * if the window under the mouse pointer is not known to GDK (for example,
922 * belongs to another application).
924 * Returns: (transfer none): the window under the mouse pointer, or %NULL
928 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
931 gdk_display_get_window_at_pointer (GdkDisplay *display,
935 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
937 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
941 multihead_get_device_state (GdkDisplay *display,
946 GdkModifierType *mask)
948 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
952 multihead_window_get_device_position (GdkDisplay *display,
957 GdkModifierType *mask)
959 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
963 multihead_window_at_device_position (GdkDisplay *display,
968 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
972 multihead_default_get_pointer (GdkDisplay *display,
976 GdkModifierType *mask)
978 return _gdk_windowing_get_device_state (display,
979 display->core_pointer,
984 multihead_default_window_get_pointer (GdkDisplay *display,
988 GdkModifierType *mask)
990 return gdk_window_real_window_get_device_position (display,
991 display->core_pointer,
996 multihead_default_window_at_pointer (GdkDisplay *display,
1000 return gdk_display_real_get_window_at_device_position (display,
1001 display->core_pointer,
1006 * gdk_display_set_pointer_hooks:
1007 * @display: a #GdkDisplay
1008 * @new_hooks: a table of pointers to functions for getting
1009 * quantities related to the current pointer position,
1010 * or %NULL to restore the default table.
1012 * This function allows for hooking into the operation
1013 * of getting the current location of the pointer on a particular
1014 * display. This is only useful for such low-level tools as an
1015 * event recorder. Applications should never have any
1016 * reason to use this facility.
1018 * Return value: the previous pointer hook table
1022 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1024 GdkDisplayPointerHooks *
1025 gdk_display_set_pointer_hooks (GdkDisplay *display,
1026 const GdkDisplayPointerHooks *new_hooks)
1028 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1030 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1033 multihead_current_pointer_hooks = new_hooks;
1035 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1037 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1039 return (GdkDisplayPointerHooks *)result;
1043 singlehead_get_pointer (GdkDisplay *display,
1047 GdkModifierType *mask)
1049 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1050 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1052 *screen = default_screen;
1054 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1058 singlehead_window_get_pointer (GdkDisplay *display,
1062 GdkModifierType *mask)
1064 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1068 singlehead_window_at_pointer (GdkDisplay *display,
1072 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1074 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1079 singlehead_default_window_get_pointer (GdkWindow *window,
1082 GdkModifierType *mask)
1084 GdkDisplay *display;
1086 display = gdk_drawable_get_display (window);
1088 return gdk_window_real_window_get_device_position (display,
1089 display->core_pointer,
1090 window, x, y, mask);
1094 singlehead_default_window_at_pointer (GdkScreen *screen,
1098 GdkDisplay *display;
1100 display = gdk_screen_get_display (screen);
1102 return gdk_display_real_get_window_at_device_position (display,
1103 display->core_pointer,
1108 * gdk_set_pointer_hooks:
1109 * @new_hooks: a table of pointers to functions for getting
1110 * quantities related to the current pointer position,
1111 * or %NULL to restore the default table.
1113 * This function allows for hooking into the operation
1114 * of getting the current location of the pointer. This
1115 * is only useful for such low-level tools as an
1116 * event recorder. Applications should never have any
1117 * reason to use this facility.
1119 * This function is not multihead safe. For multihead operation,
1120 * see gdk_display_set_pointer_hooks().
1122 * Return value: the previous pointer hook table
1124 * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead.
1127 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1129 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1132 singlehead_current_pointer_hooks = new_hooks;
1134 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1136 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1137 &singlehead_pointer_hooks);
1139 return (GdkPointerHooks *)result;
1143 generate_grab_broken_event (GdkWindow *window,
1146 GdkWindow *grab_window)
1148 g_return_if_fail (window != NULL);
1150 if (!GDK_WINDOW_DESTROYED (window))
1154 event = gdk_event_new (GDK_GRAB_BROKEN);
1155 event->grab_broken.window = g_object_ref (window);
1156 event->grab_broken.send_event = FALSE;
1157 event->grab_broken.implicit = implicit;
1158 event->grab_broken.grab_window = grab_window;
1159 gdk_event_set_device (event, device);
1160 event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1162 gdk_event_put (event);
1163 gdk_event_free (event);
1168 _gdk_display_get_last_device_grab (GdkDisplay *display,
1173 l = g_hash_table_lookup (display->device_grabs, device);
1177 l = g_list_last (l);
1185 _gdk_display_add_device_grab (GdkDisplay *display,
1188 GdkWindow *native_window,
1189 GdkGrabOwnership grab_ownership,
1190 gboolean owner_events,
1191 GdkEventMask event_mask,
1192 unsigned long serial_start,
1196 GdkDeviceGrabInfo *info, *other_info;
1199 info = g_new0 (GdkDeviceGrabInfo, 1);
1201 info->window = g_object_ref (window);
1202 info->native_window = g_object_ref (native_window);
1203 info->serial_start = serial_start;
1204 info->serial_end = G_MAXULONG;
1205 info->owner_events = owner_events;
1206 info->event_mask = event_mask;
1208 info->implicit = implicit;
1209 info->ownership = grab_ownership;
1211 grabs = g_hash_table_lookup (display->device_grabs, device);
1213 /* Find the first grab that has a larger start time (if any) and insert
1214 * before that. I.E we insert after already existing grabs with same
1216 for (l = grabs; l != NULL; l = l->next)
1218 other_info = l->data;
1220 if (info->serial_start < other_info->serial_start)
1224 grabs = g_list_insert_before (grabs, l, info);
1226 /* Make sure the new grab end before next grab */
1229 other_info = l->data;
1230 info->serial_end = other_info->serial_start;
1233 /* Find any previous grab and update its end time */
1234 l = g_list_find (grabs, info);
1238 other_info = l->data;
1239 other_info->serial_end = serial_start;
1242 g_hash_table_insert (display->device_grabs, device, grabs);
1247 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1248 This function splits things into two calls if needed, converting the
1249 coordinates to the right toplevel */
1251 synthesize_crossing_events (GdkDisplay *display,
1253 GdkWindow *src_window,
1254 GdkWindow *dest_window,
1255 GdkCrossingMode crossing_mode,
1259 GdkWindow *src_toplevel, *dest_toplevel;
1260 GdkModifierType state;
1263 /* We use the native crossing events if all native */
1264 if (_gdk_native_windows)
1268 src_toplevel = gdk_window_get_toplevel (src_window);
1270 src_toplevel = NULL;
1272 dest_toplevel = gdk_window_get_toplevel (dest_window);
1274 dest_toplevel = NULL;
1276 if (src_toplevel == NULL && dest_toplevel == NULL)
1279 if (src_toplevel == NULL ||
1280 src_toplevel == dest_toplevel)
1282 /* Same toplevels */
1283 gdk_window_get_pointer (dest_toplevel,
1285 _gdk_synthesize_crossing_events (display,
1295 else if (dest_toplevel == NULL)
1297 gdk_window_get_pointer (src_toplevel,
1299 _gdk_synthesize_crossing_events (display,
1311 /* Different toplevels */
1312 gdk_window_get_pointer (src_toplevel,
1314 _gdk_synthesize_crossing_events (display,
1323 gdk_window_get_pointer (dest_toplevel,
1325 _gdk_synthesize_crossing_events (display,
1338 get_current_toplevel (GdkDisplay *display,
1342 GdkModifierType *state_out)
1344 GdkWindow *pointer_window;
1346 GdkModifierType state;
1348 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1350 if (pointer_window != NULL &&
1351 (GDK_WINDOW_DESTROYED (pointer_window) ||
1352 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1353 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1354 pointer_window = NULL;
1359 return pointer_window;
1363 switch_to_pointer_grab (GdkDisplay *display,
1365 GdkDeviceGrabInfo *grab,
1366 GdkDeviceGrabInfo *last_grab,
1370 GdkWindow *src_window, *pointer_window, *new_toplevel;
1371 GdkPointerWindowInfo *info;
1373 GdkModifierType state;
1376 /* Temporarily unset pointer to make sure we send the crossing events below */
1377 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1378 g_hash_table_steal (display->device_grabs, device);
1379 info = _gdk_display_get_pointer_info (display, device);
1383 /* New grab is in effect */
1385 /* We need to generate crossing events for the grab.
1386 * However, there are never any crossing events for implicit grabs
1387 * TODO: ... Actually, this could happen if the pointer window
1388 * doesn't have button mask so a parent gets the event...
1390 if (!grab->implicit)
1392 /* We send GRAB crossing events from the window under the pointer to the
1393 grab window. Except if there is an old grab then we start from that */
1395 src_window = last_grab->window;
1397 src_window = info->window_under_pointer;
1399 if (src_window != grab->window)
1400 synthesize_crossing_events (display, device,
1401 src_window, grab->window,
1402 GDK_CROSSING_GRAB, time, serial);
1404 /* !owner_event Grabbing a window that we're not inside, current status is
1405 now NULL (i.e. outside grabbed window) */
1406 if (!grab->owner_events && info->window_under_pointer != grab->window)
1407 _gdk_display_set_window_under_pointer (display, device, NULL);
1410 grab->activated = TRUE;
1415 new_toplevel = NULL;
1417 if (grab == NULL /* ungrab */ ||
1418 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1420 /* We force check what window we're in, and update the toplevel_under_pointer info,
1421 * as that won't get told of this change with toplevel enter events.
1423 if (info->toplevel_under_pointer)
1424 g_object_unref (info->toplevel_under_pointer);
1425 info->toplevel_under_pointer = NULL;
1427 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1430 /* w is now toplevel and x,y in toplevel coords */
1431 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1432 info->toplevel_x = x;
1433 info->toplevel_y = y;
1434 info->state = state;
1438 if (grab == NULL) /* Ungrabbed, send events */
1440 pointer_window = NULL;
1443 /* Find (possibly virtual) child window */
1445 _gdk_window_find_descendant_at (new_toplevel,
1450 if (pointer_window != last_grab->window)
1451 synthesize_crossing_events (display, device,
1452 last_grab->window, pointer_window,
1453 GDK_CROSSING_UNGRAB, time, serial);
1455 /* We're now ungrabbed, update the window_under_pointer */
1456 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1460 g_hash_table_insert (display->device_grabs, device, old_grabs);
1464 _gdk_display_device_grab_update (GdkDisplay *display,
1466 gulong current_serial)
1468 GdkDeviceGrabInfo *current_grab, *next_grab;
1472 time = display->last_event_time;
1473 grabs = g_hash_table_lookup (display->device_grabs, device);
1475 while (grabs != NULL)
1477 current_grab = grabs->data;
1479 if (current_grab->serial_start > current_serial)
1480 return; /* Hasn't started yet */
1482 if (current_grab->serial_end > current_serial)
1484 /* This one hasn't ended yet.
1485 its the currently active one or scheduled to be active */
1487 if (!current_grab->activated)
1489 if (device->source != GDK_SOURCE_KEYBOARD)
1490 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1499 /* This is the next active grab */
1500 next_grab = grabs->next->data;
1502 if (next_grab->serial_start > current_serial)
1503 next_grab = NULL; /* Actually its not yet active */
1506 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1507 (next_grab != NULL && current_grab->window != next_grab->window))
1508 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1510 current_grab->implicit,
1511 next_grab? next_grab->window : NULL);
1513 /* Remove old grab */
1514 grabs = g_list_delete_link (grabs, grabs);
1515 g_hash_table_insert (display->device_grabs, device, grabs);
1517 if (device->source != GDK_SOURCE_KEYBOARD)
1518 switch_to_pointer_grab (display, device,
1519 next_grab, current_grab,
1520 time, current_serial);
1522 free_device_grab (current_grab);
1527 grab_list_find (GList *grabs,
1530 GdkDeviceGrabInfo *grab;
1536 if (serial >= grab->serial_start && serial < grab->serial_end)
1539 grabs = grabs->next;
1546 find_device_grab (GdkDisplay *display,
1552 l = g_hash_table_lookup (display->device_grabs, device);
1553 return grab_list_find (l, serial);
1557 _gdk_display_has_device_grab (GdkDisplay *display,
1563 l = find_device_grab (display, device, serial);
1570 /* Returns true if last grab was ended
1571 * If if_child is non-NULL, end the grab only if the grabbed
1572 * window is the same as if_child or a descendant of it */
1574 _gdk_display_end_device_grab (GdkDisplay *display,
1577 GdkWindow *if_child,
1580 GdkDeviceGrabInfo *grab;
1583 l = find_device_grab (display, device, serial);
1590 (if_child == NULL ||
1591 _gdk_window_event_parent_of (if_child, grab->window)))
1593 grab->serial_end = serial;
1594 grab->implicit_ungrab = implicit;
1595 return l->next == NULL;
1601 /* Returns TRUE if device events are not blocked by any grab */
1603 _gdk_display_check_grab_ownership (GdkDisplay *display,
1607 GHashTableIter iter;
1608 gpointer key, value;
1609 GdkGrabOwnership higher_ownership, device_ownership;
1610 gboolean device_is_keyboard;
1612 g_hash_table_iter_init (&iter, display->device_grabs);
1613 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1614 device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1616 while (g_hash_table_iter_next (&iter, &key, &value))
1618 GdkDeviceGrabInfo *grab;
1624 grabs = grab_list_find (grabs, serial);
1629 /* Discard device if it's not of the same type */
1630 if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1631 (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1637 device_ownership = grab->ownership;
1640 if (grab->ownership > higher_ownership)
1641 higher_ownership = grab->ownership;
1645 if (higher_ownership > device_ownership)
1647 /* There's a higher priority ownership
1648 * going on for other device(s)
1656 GdkPointerWindowInfo *
1657 _gdk_display_get_pointer_info (GdkDisplay *display,
1660 GdkPointerWindowInfo *info;
1662 if (G_UNLIKELY (!device))
1665 info = g_hash_table_lookup (display->pointers_info, device);
1667 if (G_UNLIKELY (!info))
1669 info = g_slice_new0 (GdkPointerWindowInfo);
1670 g_hash_table_insert (display->pointers_info, device, info);
1677 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1678 GdkDisplayPointerInfoForeach func,
1681 GHashTableIter iter;
1682 gpointer key, value;
1684 g_hash_table_iter_init (&iter, display->pointers_info);
1686 while (g_hash_table_iter_next (&iter, &key, &value))
1688 GdkPointerWindowInfo *info = value;
1689 GdkDevice *device = key;
1691 (func) (display, device, info, user_data);
1696 * gdk_device_grab_info_libgtk_only:
1697 * @display: the display for which to get the grab information
1698 * @device: device to get the grab information from
1699 * @grab_window: location to store current grab window
1700 * @owner_events: location to store boolean indicating whether
1701 * the @owner_events flag to gdk_keyboard_grab() or
1702 * gdk_pointer_grab() was %TRUE.
1704 * Determines information about the current keyboard grab.
1705 * This is not public API and must not be used by applications.
1707 * Return value: %TRUE if this application currently has the
1711 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1713 GdkWindow **grab_window,
1714 gboolean *owner_events)
1716 GdkDeviceGrabInfo *info;
1718 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1719 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1721 info = _gdk_display_get_last_device_grab (display, device);
1726 *grab_window = info->window;
1728 *owner_events = info->owner_events;
1737 * gdk_display_pointer_is_grabbed:
1738 * @display: a #GdkDisplay
1740 * Test if the pointer is grabbed.
1742 * Returns: %TRUE if an active X pointer grab is in effect
1746 * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
1749 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1751 GdkDeviceManager *device_manager;
1752 GList *devices, *dev;
1755 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1757 device_manager = gdk_display_get_device_manager (display);
1758 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1760 for (dev = devices; dev; dev = dev->next)
1764 if (device->source == GDK_SOURCE_MOUSE &&
1765 gdk_display_device_is_grabbed (display, device))
1773 * gdk_display_device_is_grabbed:
1774 * @display: a #GdkDisplay
1775 * @device: a #GdkDevice
1777 * Returns %TRUE if there is an ongoing grab on @device for @display.
1779 * Returns: %TRUE if there is a grab in effect for @device.
1782 gdk_display_device_is_grabbed (GdkDisplay *display,
1785 GdkDeviceGrabInfo *info;
1787 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1788 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1790 /* What we're interested in is the steady state (ie last grab),
1791 because we're interested e.g. if we grabbed so that we
1792 can ungrab, even if our grab is not active just yet. */
1793 info = _gdk_display_get_last_device_grab (display, device);
1795 return (info && !info->implicit);
1799 * gdk_display_get_device_manager:
1800 * @display: a #GdkDisplay.
1802 * Returns the #GdkDeviceManager associated to @display.
1804 * Returns: A #GdkDeviceManager, or %NULL. This memory is
1805 * owned by GDK and must not be freed or unreferenced.
1810 gdk_display_get_device_manager (GdkDisplay *display)
1812 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1814 return display->device_manager;