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
160 g_signal_new (g_intern_static_string ("opened"),
161 G_OBJECT_CLASS_TYPE (object_class),
164 g_cclosure_marshal_VOID__VOID,
168 * GdkDisplay::closed:
169 * @display: the object on which the signal is emitted
170 * @is_error: %TRUE if the display was closed due to an error
172 * The ::closed signal is emitted when the connection to the windowing
173 * system for @display is closed.
178 g_signal_new (g_intern_static_string ("closed"),
179 G_OBJECT_CLASS_TYPE (object_class),
181 G_STRUCT_OFFSET (GdkDisplayClass, closed),
183 _gdk_marshal_VOID__BOOLEAN,
190 free_pointer_info (GdkPointerWindowInfo *info)
192 g_object_unref (info->toplevel_under_pointer);
193 g_slice_free (GdkPointerWindowInfo, info);
197 free_device_grab (GdkDeviceGrabInfo *info)
199 g_object_unref (info->window);
200 g_object_unref (info->native_window);
205 free_device_grabs_foreach (gpointer key,
211 g_list_foreach (list, (GFunc) free_device_grab, NULL);
218 device_removed_cb (GdkDeviceManager *device_manager,
222 g_hash_table_remove (display->multiple_click_info, device);
223 g_hash_table_remove (display->device_grabs, device);
224 g_hash_table_remove (display->pointers_info, device);
226 /* FIXME: change core pointer and remove from device list */
230 gdk_display_opened (GdkDisplay *display)
232 GdkDeviceManager *device_manager;
234 device_manager = gdk_display_get_device_manager (display);
236 g_signal_connect (device_manager, "device-removed",
237 G_CALLBACK (device_removed_cb), display);
241 gdk_display_init (GdkDisplay *display)
243 _gdk_displays = g_slist_prepend (_gdk_displays, display);
245 display->double_click_time = 250;
246 display->double_click_distance = 5;
248 display->device_hooks = &default_device_hooks;
250 display->device_grabs = g_hash_table_new (NULL, NULL);
251 display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
252 (GDestroyNotify) g_free);
254 display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
255 (GDestroyNotify) free_pointer_info);
257 display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
258 (GDestroyNotify) g_free);
260 g_signal_connect (display, "opened",
261 G_CALLBACK (gdk_display_opened), NULL);
265 gdk_display_dispose (GObject *object)
267 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
268 GdkDeviceManager *device_manager;
270 device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
272 g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
273 g_list_free (display->queued_events);
274 display->queued_events = NULL;
275 display->queued_tail = NULL;
277 _gdk_displays = g_slist_remove (_gdk_displays, object);
279 if (gdk_display_get_default() == display)
282 gdk_display_manager_set_default_display (gdk_display_manager_get(),
283 _gdk_displays->data);
285 gdk_display_manager_set_default_display (gdk_display_manager_get(),
290 g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, object);
292 G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
296 gdk_display_finalize (GObject *object)
298 GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
300 g_hash_table_foreach_remove (display->device_grabs,
301 free_device_grabs_foreach,
303 g_hash_table_destroy (display->device_grabs);
305 g_hash_table_destroy (display->pointers_info);
306 g_hash_table_destroy (display->multiple_click_info);
308 if (display->device_manager)
309 g_object_unref (display->device_manager);
311 G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
316 * @display: a #GdkDisplay
318 * Closes the connection to the windowing system for the given display,
319 * and cleans up associated resources.
324 gdk_display_close (GdkDisplay *display)
326 g_return_if_fail (GDK_IS_DISPLAY (display));
328 if (!display->closed)
330 display->closed = TRUE;
332 g_signal_emit (display, signals[CLOSED], 0, FALSE);
333 g_object_run_dispose (G_OBJECT (display));
335 g_object_unref (display);
340 * gdk_display_get_event:
341 * @display: a #GdkDisplay
343 * Gets the next #GdkEvent to be processed for @display, fetching events from the
344 * windowing system if necessary.
346 * Return value: the next #GdkEvent to be processed, or %NULL if no events
347 * are pending. The returned #GdkEvent should be freed with gdk_event_free().
352 gdk_display_get_event (GdkDisplay *display)
354 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
356 _gdk_events_queue (display);
357 return _gdk_event_unqueue (display);
361 * gdk_display_peek_event:
362 * @display: a #GdkDisplay
364 * Gets a copy of the first #GdkEvent in the @display's event queue, without
365 * removing the event from the queue. (Note that this function will
366 * not get more events from the windowing system. It only checks the events
367 * that have already been moved to the GDK event queue.)
369 * Return value: a copy of the first #GdkEvent on the event queue, or %NULL
370 * if no events are in the queue. The returned #GdkEvent should be freed with
376 gdk_display_peek_event (GdkDisplay *display)
380 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
382 tmp_list = _gdk_event_queue_find_first (display);
385 return gdk_event_copy (tmp_list->data);
391 * gdk_display_put_event:
392 * @display: a #GdkDisplay
393 * @event: a #GdkEvent.
395 * Appends a copy of the given event onto the front of the event
396 * queue for @display.
401 gdk_display_put_event (GdkDisplay *display,
402 const GdkEvent *event)
404 g_return_if_fail (GDK_IS_DISPLAY (display));
405 g_return_if_fail (event != NULL);
407 _gdk_event_queue_append (display, gdk_event_copy (event));
408 /* If the main loop is blocking in a different thread, wake it up */
409 g_main_context_wakeup (NULL);
413 * gdk_display_pointer_ungrab:
414 * @display: a #GdkDisplay.
415 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
417 * Release any pointer grab.
421 * Deprecated: 3.0. Use gdk_device_ungrab(), together with gdk_device_grab()
425 gdk_display_pointer_ungrab (GdkDisplay *display,
428 GdkDeviceManager *device_manager;
429 GList *devices, *dev;
432 g_return_if_fail (GDK_IS_DISPLAY (display));
434 device_manager = gdk_display_get_device_manager (display);
435 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
437 /* FIXME: Should this be generic to all backends? */
438 /* FIXME: What happens with extended devices? */
439 for (dev = devices; dev; dev = dev->next)
443 if (device->source != GDK_SOURCE_MOUSE)
446 gdk_device_ungrab (device, time_);
449 g_list_free (devices);
453 * gdk_pointer_ungrab:
454 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
455 * timestamp is available.
457 * Ungrabs the pointer on the default display, if it is grabbed by this
460 * Deprecated: 3.0. Use gdk_device_ungrab(), together with gdk_device_grab()
464 gdk_pointer_ungrab (guint32 time)
466 gdk_display_pointer_ungrab (gdk_display_get_default (), time);
470 * gdk_pointer_is_grabbed:
472 * Returns %TRUE if the pointer on the default display is currently
473 * grabbed by this application.
475 * Note that this does not take the inmplicit pointer grab on button
476 * presses into account.
478 * Return value: %TRUE if the pointer is currently grabbed by this application.
480 * Deprecated: 3.0. Use gdk_display_device_is_grabbed() instead.
483 gdk_pointer_is_grabbed (void)
485 return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
489 * gdk_display_keyboard_ungrab:
490 * @display: a #GdkDisplay.
491 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
493 * Release any keyboard grab
497 * Deprecated: 3.0. Use gdk_device_ungrab(), together with gdk_device_grab()
501 gdk_display_keyboard_ungrab (GdkDisplay *display,
504 GdkDeviceManager *device_manager;
505 GList *devices, *dev;
508 g_return_if_fail (GDK_IS_DISPLAY (display));
510 device_manager = gdk_display_get_device_manager (display);
511 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
513 /* FIXME: Should this be generic to all backends? */
514 /* FIXME: What happens with extended devices? */
515 for (dev = devices; dev; dev = dev->next)
519 if (device->source != GDK_SOURCE_KEYBOARD)
522 gdk_device_ungrab (device, time);
525 g_list_free (devices);
529 * gdk_keyboard_ungrab:
530 * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
531 * timestamp is available.
533 * Ungrabs the keyboard on the default display, if it is grabbed by this
536 * Deprecated: 3.0. Use gdk_device_ungrab(), together with gdk_device_grab()
540 gdk_keyboard_ungrab (guint32 time)
542 gdk_display_keyboard_ungrab (gdk_display_get_default (), time);
548 * Emits a short beep on the default display.
553 gdk_display_beep (gdk_display_get_default ());
557 * gdk_event_send_client_message:
558 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
559 * @winid: the window to send the X ClientMessage event to.
561 * Sends an X ClientMessage event to a given window (which must be
562 * on the default #GdkDisplay.)
563 * This could be used for communicating between different applications,
564 * though the amount of data is limited to 20 bytes.
566 * Return value: non-zero on success.
569 gdk_event_send_client_message (GdkEvent *event,
570 GdkNativeWindow winid)
572 g_return_val_if_fail (event != NULL, FALSE);
574 return gdk_event_send_client_message_for_display (gdk_display_get_default (),
579 * gdk_event_send_clientmessage_toall:
580 * @event: the #GdkEvent to send, which should be a #GdkEventClient.
582 * Sends an X ClientMessage event to all toplevel windows on the default
585 * Toplevel windows are determined by checking for the WM_STATE property, as
586 * described in the Inter-Client Communication Conventions Manual (ICCCM).
587 * If no windows are found with the WM_STATE property set, the message is sent
588 * to all children of the root window.
591 gdk_event_send_clientmessage_toall (GdkEvent *event)
593 g_return_if_fail (event != NULL);
595 gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
599 * gdk_device_get_core_pointer:
601 * Returns the core pointer device for the default display.
603 * Return value: the core pointer device; this is owned by the
604 * display and should not be freed.
606 * Deprecated: 3.0. Use gdk_display_get_device_manager() instead, or
607 * gdk_event_get_device() if a #GdkEvent with pointer device
608 * information is available.
611 gdk_device_get_core_pointer (void)
613 return gdk_display_get_core_pointer (gdk_display_get_default ());
617 * gdk_display_get_core_pointer:
618 * @display: a #GdkDisplay
620 * Returns the core pointer device for the given display
622 * Return value: the core pointer device; this is owned by the
623 * display and should not be freed.
627 * Deprecated: 3.0. Use gdk_display_get_device_manager() instead, or
628 * gdk_event_get_device() if a #GdkEvent with device
629 * information is available.
632 gdk_display_get_core_pointer (GdkDisplay *display)
634 return display->core_pointer;
638 * gdk_set_sm_client_id:
639 * @sm_client_id: the client id assigned by the session manager when the
640 * connection was opened, or %NULL to remove the property.
642 * Sets the <literal>SM_CLIENT_ID</literal> property on the application's leader window so that
643 * the window manager can save the application's state using the X11R6 ICCCM
644 * session management protocol.
646 * See the X Session Management Library documentation for more information on
647 * session management and the Inter-Client Communication Conventions Manual
648 * (ICCCM) for information on the <literal>WM_CLIENT_LEADER</literal> property.
649 * (Both documents are part of the X Window System distribution.)
652 gdk_set_sm_client_id (const gchar* sm_client_id)
654 GSList *displays, *tmp_list;
656 g_free (gdk_sm_client_id);
657 gdk_sm_client_id = g_strdup (sm_client_id);
659 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
660 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
661 _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
663 g_slist_free (displays);
667 * _gdk_get_sm_client_id:
669 * Gets the client ID set with gdk_set_sm_client_id(), if any.
671 * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
672 * has never been called.
675 _gdk_get_sm_client_id (void)
677 return gdk_sm_client_id;
681 _gdk_display_enable_motion_hints (GdkDisplay *display,
684 gulong *device_serial, serial;
686 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
690 device_serial = g_new0 (gulong, 1);
691 *device_serial = G_MAXULONG;
692 g_hash_table_insert (display->motion_hint_info, device, device_serial);
695 if (*device_serial != 0)
697 serial = _gdk_windowing_window_get_next_serial (display);
698 /* We might not actually generate the next request, so
699 make sure this triggers always, this may cause it to
700 trigger slightly too early, but this is just a hint
704 if (serial < *device_serial)
705 *device_serial = serial;
710 * gdk_display_get_device_state:
711 * @display: a #GdkDisplay.
712 * @device: device to query status to.
713 * @screen: location to store the #GdkScreen the @device is on, or %NULL.
714 * @x: location to store root window X coordinate of @device, or %NULL.
715 * @y: location to store root window Y coordinate of @device, or %NULL.
716 * @mask: location to store current modifier mask for @device, or %NULL.
718 * Gets the current location and state of @device for a given display.
723 gdk_display_get_device_state (GdkDisplay *display,
728 GdkModifierType *mask)
730 GdkScreen *tmp_screen;
732 GdkModifierType tmp_mask;
734 g_return_if_fail (GDK_IS_DISPLAY (display));
735 g_return_if_fail (GDK_IS_DEVICE (device));
737 display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
740 *screen = tmp_screen;
750 * gdk_display_get_window_at_device_position:
751 * @display: a #GdkDisplay.
752 * @device: #GdkDevice to query info to.
753 * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL.
754 * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL.
756 * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
757 * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
759 * Returns: the #GdkWindow under the device position, or %NULL.
764 gdk_display_get_window_at_device_position (GdkDisplay *display,
772 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
773 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
775 window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
786 * gdk_display_set_device_hooks:
787 * @display: a #GdkDisplay.
788 * @new_hooks: a table of pointers to functions for getting quantities related to all
789 * devices position, or %NULL to restore the default table.
791 * This function allows for hooking into the operation of getting the current location of any
792 * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as
793 * an event recorder. Applications should never have any reason to use this facility.
795 * Returns: The previous device hook table.
799 GdkDisplayDeviceHooks *
800 gdk_display_set_device_hooks (GdkDisplay *display,
801 const GdkDisplayDeviceHooks *new_hooks)
803 const GdkDisplayDeviceHooks *result;
805 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
806 result = display->device_hooks;
809 display->device_hooks = new_hooks;
811 display->device_hooks = &default_device_hooks;
813 return (GdkDisplayDeviceHooks *) result;
817 * gdk_display_get_pointer:
818 * @display: a #GdkDisplay
819 * @screen: (allow-none): location to store the screen that the
820 * cursor is on, or %NULL.
821 * @x: (allow-none): (out): location to store root window X coordinate of pointer, or %NULL.
822 * @y: (allow-none): (out): location to store root window Y coordinate of pointer, or %NULL.
823 * @mask: (allow-none): (out): location to store current modifier mask, or %NULL
825 * Gets the current location of the pointer and the current modifier
826 * mask for a given display.
830 * Deprecated: 3.0. Use gdk_display_get_device_state() instead.
833 gdk_display_get_pointer (GdkDisplay *display,
837 GdkModifierType *mask)
839 g_return_if_fail (GDK_IS_DISPLAY (display));
841 gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
845 gdk_display_real_get_window_at_device_position (GdkDisplay *display,
853 window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
855 /* This might need corrections, as the native window returned
856 may contain client side children */
861 window = _gdk_window_find_descendant_at (window,
864 x = floor (xx + 0.5);
865 y = floor (yy + 0.5);
875 gdk_window_real_window_get_device_position (GdkDisplay *display,
880 GdkModifierType *mask)
882 GdkWindowObject *private;
884 GdkModifierType tmp_mask;
885 gboolean normal_child;
887 private = (GdkWindowObject *) window;
889 normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window,
893 /* We got the coords on the impl, convert to the window */
894 tmpx -= private->abs_x;
895 tmpy -= private->abs_y;
905 return _gdk_window_find_child_at (window, tmpx, tmpy);
910 * gdk_display_get_window_at_pointer:
911 * @display: a #GdkDisplay
912 * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
913 * to the window origin, or %NULL
914 * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
915 & to the window origin, or %NULL
917 * Obtains the window underneath the mouse pointer, returning the location
918 * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
919 * if the window under the mouse pointer is not known to GDK (for example,
920 * belongs to another application).
922 * Returns: (transfer none): the window under the mouse pointer, or %NULL
926 * Deprecated: 3.0. Use gdk_display_get_window_at_device_position() instead.
929 gdk_display_get_window_at_pointer (GdkDisplay *display,
933 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
935 return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y);
939 multihead_get_device_state (GdkDisplay *display,
944 GdkModifierType *mask)
946 multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask);
950 multihead_window_get_device_position (GdkDisplay *display,
955 GdkModifierType *mask)
957 return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask);
961 multihead_window_at_device_position (GdkDisplay *display,
966 return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
970 multihead_default_get_pointer (GdkDisplay *display,
974 GdkModifierType *mask)
976 return _gdk_windowing_get_device_state (display,
977 display->core_pointer,
982 multihead_default_window_get_pointer (GdkDisplay *display,
986 GdkModifierType *mask)
988 return gdk_window_real_window_get_device_position (display,
989 display->core_pointer,
994 multihead_default_window_at_pointer (GdkDisplay *display,
998 return gdk_display_real_get_window_at_device_position (display,
999 display->core_pointer,
1004 * gdk_display_set_pointer_hooks:
1005 * @display: a #GdkDisplay
1006 * @new_hooks: a table of pointers to functions for getting
1007 * quantities related to the current pointer position,
1008 * or %NULL to restore the default table.
1010 * This function allows for hooking into the operation
1011 * of getting the current location of the pointer on a particular
1012 * display. This is only useful for such low-level tools as an
1013 * event recorder. Applications should never have any
1014 * reason to use this facility.
1016 * Return value: the previous pointer hook table
1020 * Deprecated: 3.0. Use gdk_display_set_device_hooks() instead.
1022 GdkDisplayPointerHooks *
1023 gdk_display_set_pointer_hooks (GdkDisplay *display,
1024 const GdkDisplayPointerHooks *new_hooks)
1026 const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
1028 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1031 multihead_current_pointer_hooks = new_hooks;
1033 multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
1035 gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
1037 return (GdkDisplayPointerHooks *)result;
1041 singlehead_get_pointer (GdkDisplay *display,
1045 GdkModifierType *mask)
1047 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1048 GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
1050 *screen = default_screen;
1052 singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
1056 singlehead_window_get_pointer (GdkDisplay *display,
1060 GdkModifierType *mask)
1062 return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask);
1066 singlehead_window_at_pointer (GdkDisplay *display,
1070 GdkScreen *default_screen = gdk_display_get_default_screen (display);
1072 return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
1077 singlehead_default_window_get_pointer (GdkWindow *window,
1080 GdkModifierType *mask)
1082 GdkDisplay *display;
1084 display = gdk_drawable_get_display (window);
1086 return gdk_window_real_window_get_device_position (display,
1087 display->core_pointer,
1088 window, x, y, mask);
1092 singlehead_default_window_at_pointer (GdkScreen *screen,
1096 GdkDisplay *display;
1098 display = gdk_screen_get_display (screen);
1100 return gdk_display_real_get_window_at_device_position (display,
1101 display->core_pointer,
1106 * gdk_set_pointer_hooks:
1107 * @new_hooks: a table of pointers to functions for getting
1108 * quantities related to the current pointer position,
1109 * or %NULL to restore the default table.
1111 * This function allows for hooking into the operation
1112 * of getting the current location of the pointer. This
1113 * is only useful for such low-level tools as an
1114 * event recorder. Applications should never have any
1115 * reason to use this facility.
1117 * This function is not multihead safe. For multihead operation,
1118 * see gdk_display_set_pointer_hooks().
1120 * Return value: the previous pointer hook table
1122 * Deprecated: 3.0. Use gdk_display_set_device_hooks() instead.
1125 gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
1127 const GdkPointerHooks *result = singlehead_current_pointer_hooks;
1130 singlehead_current_pointer_hooks = new_hooks;
1132 singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
1134 gdk_display_set_pointer_hooks (gdk_display_get_default (),
1135 &singlehead_pointer_hooks);
1137 return (GdkPointerHooks *)result;
1141 generate_grab_broken_event (GdkWindow *window,
1144 GdkWindow *grab_window)
1146 g_return_if_fail (window != NULL);
1148 if (!GDK_WINDOW_DESTROYED (window))
1152 event = gdk_event_new (GDK_GRAB_BROKEN);
1153 event->grab_broken.window = g_object_ref (window);
1154 event->grab_broken.send_event = FALSE;
1155 event->grab_broken.implicit = implicit;
1156 event->grab_broken.grab_window = grab_window;
1157 gdk_event_set_device (event, device);
1158 event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
1160 gdk_event_put (event);
1161 gdk_event_free (event);
1166 _gdk_display_get_last_device_grab (GdkDisplay *display,
1171 l = g_hash_table_lookup (display->device_grabs, device);
1175 l = g_list_last (l);
1183 _gdk_display_add_device_grab (GdkDisplay *display,
1186 GdkWindow *native_window,
1187 GdkGrabOwnership grab_ownership,
1188 gboolean owner_events,
1189 GdkEventMask event_mask,
1190 unsigned long serial_start,
1194 GdkDeviceGrabInfo *info, *other_info;
1197 info = g_new0 (GdkDeviceGrabInfo, 1);
1199 info->window = g_object_ref (window);
1200 info->native_window = g_object_ref (native_window);
1201 info->serial_start = serial_start;
1202 info->serial_end = G_MAXULONG;
1203 info->owner_events = owner_events;
1204 info->event_mask = event_mask;
1206 info->implicit = implicit;
1207 info->ownership = grab_ownership;
1209 grabs = g_hash_table_lookup (display->device_grabs, device);
1211 /* Find the first grab that has a larger start time (if any) and insert
1212 * before that. I.E we insert after already existing grabs with same
1214 for (l = grabs; l != NULL; l = l->next)
1216 other_info = l->data;
1218 if (info->serial_start < other_info->serial_start)
1222 grabs = g_list_insert_before (grabs, l, info);
1224 /* Make sure the new grab end before next grab */
1227 other_info = l->data;
1228 info->serial_end = other_info->serial_start;
1231 /* Find any previous grab and update its end time */
1232 l = g_list_find (grabs, info);
1236 other_info = l->data;
1237 other_info->serial_end = serial_start;
1240 g_hash_table_insert (display->device_grabs, device, grabs);
1245 /* _gdk_synthesize_crossing_events only works inside one toplevel.
1246 This function splits things into two calls if needed, converting the
1247 coordinates to the right toplevel */
1249 synthesize_crossing_events (GdkDisplay *display,
1251 GdkWindow *src_window,
1252 GdkWindow *dest_window,
1253 GdkCrossingMode crossing_mode,
1257 GdkWindow *src_toplevel, *dest_toplevel;
1258 GdkModifierType state;
1261 /* We use the native crossing events if all native */
1262 if (_gdk_native_windows)
1266 src_toplevel = gdk_window_get_toplevel (src_window);
1268 src_toplevel = NULL;
1270 dest_toplevel = gdk_window_get_toplevel (dest_window);
1272 dest_toplevel = NULL;
1274 if (src_toplevel == NULL && dest_toplevel == NULL)
1277 if (src_toplevel == NULL ||
1278 src_toplevel == dest_toplevel)
1280 /* Same toplevels */
1281 gdk_window_get_pointer (dest_toplevel,
1283 _gdk_synthesize_crossing_events (display,
1293 else if (dest_toplevel == NULL)
1295 gdk_window_get_pointer (src_toplevel,
1297 _gdk_synthesize_crossing_events (display,
1309 /* Different toplevels */
1310 gdk_window_get_pointer (src_toplevel,
1312 _gdk_synthesize_crossing_events (display,
1321 gdk_window_get_pointer (dest_toplevel,
1323 _gdk_synthesize_crossing_events (display,
1336 get_current_toplevel (GdkDisplay *display,
1340 GdkModifierType *state_out)
1342 GdkWindow *pointer_window;
1344 GdkModifierType state;
1346 pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
1348 if (pointer_window != NULL &&
1349 (GDK_WINDOW_DESTROYED (pointer_window) ||
1350 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
1351 GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
1352 pointer_window = NULL;
1357 return pointer_window;
1361 switch_to_pointer_grab (GdkDisplay *display,
1363 GdkDeviceGrabInfo *grab,
1364 GdkDeviceGrabInfo *last_grab,
1368 GdkWindow *src_window, *pointer_window, *new_toplevel;
1369 GdkPointerWindowInfo *info;
1371 GdkModifierType state;
1374 /* Temporarily unset pointer to make sure we send the crossing events below */
1375 old_grabs = g_hash_table_lookup (display->device_grabs, device);
1376 g_hash_table_steal (display->device_grabs, device);
1377 info = _gdk_display_get_pointer_info (display, device);
1381 /* New grab is in effect */
1383 /* We need to generate crossing events for the grab.
1384 * However, there are never any crossing events for implicit grabs
1385 * TODO: ... Actually, this could happen if the pointer window
1386 * doesn't have button mask so a parent gets the event...
1388 if (!grab->implicit)
1390 /* We send GRAB crossing events from the window under the pointer to the
1391 grab window. Except if there is an old grab then we start from that */
1393 src_window = last_grab->window;
1395 src_window = info->window_under_pointer;
1397 if (src_window != grab->window)
1398 synthesize_crossing_events (display, device,
1399 src_window, grab->window,
1400 GDK_CROSSING_GRAB, time, serial);
1402 /* !owner_event Grabbing a window that we're not inside, current status is
1403 now NULL (i.e. outside grabbed window) */
1404 if (!grab->owner_events && info->window_under_pointer != grab->window)
1405 _gdk_display_set_window_under_pointer (display, device, NULL);
1408 grab->activated = TRUE;
1413 new_toplevel = NULL;
1415 if (grab == NULL /* ungrab */ ||
1416 (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
1418 /* We force check what window we're in, and update the toplevel_under_pointer info,
1419 * as that won't get told of this change with toplevel enter events.
1421 if (info->toplevel_under_pointer)
1422 g_object_unref (info->toplevel_under_pointer);
1423 info->toplevel_under_pointer = NULL;
1425 new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
1428 /* w is now toplevel and x,y in toplevel coords */
1429 info->toplevel_under_pointer = g_object_ref (new_toplevel);
1430 info->toplevel_x = x;
1431 info->toplevel_y = y;
1432 info->state = state;
1436 if (grab == NULL) /* Ungrabbed, send events */
1438 pointer_window = NULL;
1441 /* Find (possibly virtual) child window */
1443 _gdk_window_find_descendant_at (new_toplevel,
1448 if (pointer_window != last_grab->window)
1449 synthesize_crossing_events (display, device,
1450 last_grab->window, pointer_window,
1451 GDK_CROSSING_UNGRAB, time, serial);
1453 /* We're now ungrabbed, update the window_under_pointer */
1454 _gdk_display_set_window_under_pointer (display, device, pointer_window);
1458 g_hash_table_insert (display->device_grabs, device, old_grabs);
1462 _gdk_display_device_grab_update (GdkDisplay *display,
1464 gulong current_serial)
1466 GdkDeviceGrabInfo *current_grab, *next_grab;
1470 time = display->last_event_time;
1471 grabs = g_hash_table_lookup (display->device_grabs, device);
1473 while (grabs != NULL)
1475 current_grab = grabs->data;
1477 if (current_grab->serial_start > current_serial)
1478 return; /* Hasn't started yet */
1480 if (current_grab->serial_end > current_serial)
1482 /* This one hasn't ended yet.
1483 its the currently active one or scheduled to be active */
1485 if (!current_grab->activated)
1487 if (device->source != GDK_SOURCE_KEYBOARD)
1488 switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial);
1497 /* This is the next active grab */
1498 next_grab = grabs->next->data;
1500 if (next_grab->serial_start > current_serial)
1501 next_grab = NULL; /* Actually its not yet active */
1504 if ((next_grab == NULL && current_grab->implicit_ungrab) ||
1505 (next_grab != NULL && current_grab->window != next_grab->window))
1506 generate_grab_broken_event (GDK_WINDOW (current_grab->window),
1508 current_grab->implicit,
1509 next_grab? next_grab->window : NULL);
1511 /* Remove old grab */
1512 grabs = g_list_delete_link (grabs, grabs);
1513 g_hash_table_insert (display->device_grabs, device, grabs);
1515 if (device->source != GDK_SOURCE_KEYBOARD)
1516 switch_to_pointer_grab (display, device,
1517 next_grab, current_grab,
1518 time, current_serial);
1520 free_device_grab (current_grab);
1525 grab_list_find (GList *grabs,
1528 GdkDeviceGrabInfo *grab;
1534 if (serial >= grab->serial_start && serial < grab->serial_end)
1537 grabs = grabs->next;
1544 find_device_grab (GdkDisplay *display,
1550 l = g_hash_table_lookup (display->device_grabs, device);
1551 return grab_list_find (l, serial);
1555 _gdk_display_has_device_grab (GdkDisplay *display,
1561 l = find_device_grab (display, device, serial);
1568 /* Returns true if last grab was ended
1569 * If if_child is non-NULL, end the grab only if the grabbed
1570 * window is the same as if_child or a descendant of it */
1572 _gdk_display_end_device_grab (GdkDisplay *display,
1575 GdkWindow *if_child,
1578 GdkDeviceGrabInfo *grab;
1581 l = find_device_grab (display, device, serial);
1588 (if_child == NULL ||
1589 _gdk_window_event_parent_of (if_child, grab->window)))
1591 grab->serial_end = serial;
1592 grab->implicit_ungrab = implicit;
1593 return l->next == NULL;
1599 /* Returns TRUE if device events are not blocked by any grab */
1601 _gdk_display_check_grab_ownership (GdkDisplay *display,
1605 GHashTableIter iter;
1606 gpointer key, value;
1607 GdkGrabOwnership higher_ownership, device_ownership;
1608 gboolean device_is_keyboard;
1610 g_hash_table_iter_init (&iter, display->device_grabs);
1611 higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
1612 device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD);
1614 while (g_hash_table_iter_next (&iter, &key, &value))
1616 GdkDeviceGrabInfo *grab;
1622 grabs = grab_list_find (grabs, serial);
1627 /* Discard device if it's not of the same type */
1628 if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) ||
1629 (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD))
1635 device_ownership = grab->ownership;
1638 if (grab->ownership > higher_ownership)
1639 higher_ownership = grab->ownership;
1643 if (higher_ownership > device_ownership)
1645 /* There's a higher priority ownership
1646 * going on for other device(s)
1654 GdkPointerWindowInfo *
1655 _gdk_display_get_pointer_info (GdkDisplay *display,
1658 GdkPointerWindowInfo *info;
1660 if (G_UNLIKELY (!device))
1663 info = g_hash_table_lookup (display->pointers_info, device);
1665 if (G_UNLIKELY (!info))
1667 info = g_slice_new0 (GdkPointerWindowInfo);
1668 g_hash_table_insert (display->pointers_info, device, info);
1675 _gdk_display_pointer_info_foreach (GdkDisplay *display,
1676 GdkDisplayPointerInfoForeach func,
1679 GHashTableIter iter;
1680 gpointer key, value;
1682 g_hash_table_iter_init (&iter, display->pointers_info);
1684 while (g_hash_table_iter_next (&iter, &key, &value))
1686 GdkPointerWindowInfo *info = value;
1687 GdkDevice *device = key;
1689 (func) (display, device, info, user_data);
1694 * gdk_device_grab_info_libgtk_only:
1695 * @display: the display for which to get the grab information
1696 * @device: device to get the grab information from
1697 * @grab_window: location to store current grab window
1698 * @owner_events: location to store boolean indicating whether
1699 * the @owner_events flag to gdk_keyboard_grab() or
1700 * gdk_pointer_grab() was %TRUE.
1702 * Determines information about the current keyboard grab.
1703 * This is not public API and must not be used by applications.
1705 * Return value: %TRUE if this application currently has the
1709 gdk_device_grab_info_libgtk_only (GdkDisplay *display,
1711 GdkWindow **grab_window,
1712 gboolean *owner_events)
1714 GdkDeviceGrabInfo *info;
1716 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
1717 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1719 info = _gdk_display_get_last_device_grab (display, device);
1724 *grab_window = info->window;
1726 *owner_events = info->owner_events;
1735 * gdk_display_pointer_is_grabbed:
1736 * @display: a #GdkDisplay
1738 * Test if the pointer is grabbed.
1740 * Returns: %TRUE if an active X pointer grab is in effect
1744 * Deprecated: 3.0. Use gdk_display_device_is_grabbed() instead.
1747 gdk_display_pointer_is_grabbed (GdkDisplay *display)
1749 GdkDeviceManager *device_manager;
1750 GList *devices, *dev;
1753 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1755 device_manager = gdk_display_get_device_manager (display);
1756 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
1758 for (dev = devices; dev; dev = dev->next)
1762 if (device->source == GDK_SOURCE_MOUSE &&
1763 gdk_display_device_is_grabbed (display, device))
1771 * gdk_display_device_is_grabbed:
1772 * @display: a #GdkDisplay
1773 * @device: a #GdkDevice
1775 * Returns %TRUE if there is an ongoing grab on @device for @display.
1777 * Returns: %TRUE if there is a grab in effect for @device.
1780 gdk_display_device_is_grabbed (GdkDisplay *display,
1783 GdkDeviceGrabInfo *info;
1785 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
1786 g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
1788 /* What we're interested in is the steady state (ie last grab),
1789 because we're interested e.g. if we grabbed so that we
1790 can ungrab, even if our grab is not active just yet. */
1791 info = _gdk_display_get_last_device_grab (display, device);
1793 return (info && !info->implicit);
1797 * gdk_display_get_device_manager:
1798 * @display: a #GdkDisplay.
1800 * Returns the #GdkDeviceManager associated to @display.
1802 * Returns: A #GdkDeviceManager, or %NULL. This memory is
1803 * owned by GDK and must not be freed or unreferenced.
1808 gdk_display_get_device_manager (GdkDisplay *display)
1810 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1812 return display->device_manager;
1815 #define __GDK_DISPLAY_C__
1816 #include "gdkaliasdef.c"