X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk%2Fgdkdisplay.c;h=ad520b655467f084ef31fdeabb14657ecea02960;hb=60e0acfc112186384e0c284b3840a8c6499f3a32;hp=2f3050965ad5c1ef5b607a3fd9482ea6a78c3438;hpb=bda1f3558504266cde3cb2bbe247dd489bcda941;p=~andy%2Fgtk diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 2f3050965..ad520b655 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -24,7 +24,9 @@ #include "config.h" #include "gdkdisplay.h" +#include "gdkdisplayprivate.h" +#include "gdkdeviceprivate.h" #include "gdkevents.h" #include "gdkwindowimpl.h" #include "gdkinternals.h" @@ -32,7 +34,32 @@ #include "gdkscreen.h" #include -#include + + +/** + * SECTION:gdkdisplay + * @Short_description: Controls the keyboard/mouse pointer grabs and a set of GdkScreens + * @Title: GdkDisplay + * + * #GdkDisplay objects purpose are two fold: + * + * + * To grab/ungrab keyboard focus and mouse pointer + * + * + * To manage and provide information about the #GdkScreen(s) + * available for this #GdkDisplay + * + * + * + * #GdkDisplay objects are the GDK representation of the X Display which can be + * described as a workstation consisting of a keyboard a pointing + * device (such as a mouse) and one or more screens. + * It is used to open and keep track of various #GdkScreen objects currently + * instanciated by the application. It is also used to grab and release the keyboard + * and the mouse pointer. + */ + enum { OPENED, @@ -43,105 +70,10 @@ enum { static void gdk_display_dispose (GObject *object); static void gdk_display_finalize (GObject *object); -static void multihead_get_device_state (GdkDisplay *display, - GdkDevice *device, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow * multihead_window_get_device_position (GdkDisplay *display, - GdkDevice *device, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow * multihead_window_at_device_position (GdkDisplay *display, - GdkDevice *device, - gint *win_x, - gint *win_y); - -static void multihead_default_get_pointer (GdkDisplay *display, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow * multihead_default_window_get_pointer (GdkDisplay *display, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow * multihead_default_window_at_pointer (GdkDisplay *display, - gint *win_x, - gint *win_y); - - -static void singlehead_get_pointer (GdkDisplay *display, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow* singlehead_window_get_pointer (GdkDisplay *display, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow* singlehead_window_at_pointer (GdkDisplay *display, - gint *win_x, - gint *win_y); - -static GdkWindow* singlehead_default_window_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow* singlehead_default_window_at_pointer (GdkScreen *screen, - gint *win_x, - gint *win_y); -static GdkWindow *gdk_window_real_window_get_device_position (GdkDisplay *display, - GdkDevice *device, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask); -static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay *display, - GdkDevice *device, - gint *win_x, - gint *win_y); - -static guint signals[LAST_SIGNAL] = { 0 }; - -static char *gdk_sm_client_id; - -static const GdkDisplayDeviceHooks default_device_hooks = { - _gdk_windowing_get_device_state, - gdk_window_real_window_get_device_position, - gdk_display_real_get_window_at_device_position -}; - -static const GdkDisplayDeviceHooks multihead_pointer_hooks = { - multihead_get_device_state, - multihead_window_get_device_position, - multihead_window_at_device_position -}; - -static const GdkDisplayPointerHooks multihead_default_pointer_hooks = { - multihead_default_get_pointer, - multihead_default_window_get_pointer, - multihead_default_window_at_pointer -}; - -static const GdkDisplayPointerHooks singlehead_pointer_hooks = { - singlehead_get_pointer, - singlehead_window_get_pointer, - singlehead_window_at_pointer -}; -static const GdkPointerHooks singlehead_default_pointer_hooks = { - singlehead_default_window_get_pointer, - singlehead_default_window_at_pointer -}; +static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display); -static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks; -static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks; +static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT) @@ -153,6 +85,9 @@ gdk_display_class_init (GdkDisplayClass *class) object_class->finalize = gdk_display_finalize; object_class->dispose = gdk_display_dispose; + class->get_app_launch_context = gdk_display_real_get_app_launch_context; + class->window_type = GDK_TYPE_WINDOW; + /** * GdkDisplay::opened: * @display: the object on which the signal is emitted @@ -244,13 +179,9 @@ gdk_display_opened (GdkDisplay *display) static void gdk_display_init (GdkDisplay *display) { - _gdk_displays = g_slist_prepend (_gdk_displays, display); - display->double_click_time = 250; display->double_click_distance = 5; - display->device_hooks = &default_device_hooks; - display->device_grabs = g_hash_table_new (NULL, NULL); display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_free); @@ -268,28 +199,16 @@ gdk_display_init (GdkDisplay *display) static void gdk_display_dispose (GObject *object) { - GdkDisplay *display = GDK_DISPLAY_OBJECT (object); + GdkDisplay *display = GDK_DISPLAY (object); GdkDeviceManager *device_manager; - device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object)); + device_manager = gdk_display_get_device_manager (GDK_DISPLAY (object)); g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL); g_list_free (display->queued_events); display->queued_events = NULL; display->queued_tail = NULL; - _gdk_displays = g_slist_remove (_gdk_displays, object); - - if (gdk_display_get_default () == display) - { - if (_gdk_displays) - gdk_display_manager_set_default_display (gdk_display_manager_get(), - _gdk_displays->data); - else - gdk_display_manager_set_default_display (gdk_display_manager_get(), - NULL); - } - if (device_manager) { /* this is to make it drop devices which may require using the X @@ -305,7 +224,7 @@ gdk_display_dispose (GObject *object) static void gdk_display_finalize (GObject *object) { - GdkDisplay *display = GDK_DISPLAY_OBJECT (object); + GdkDisplay *display = GDK_DISPLAY (object); g_hash_table_foreach_remove (display->device_grabs, free_device_grabs_foreach, @@ -380,8 +299,8 @@ GdkEvent* gdk_display_get_event (GdkDisplay *display) { g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - - _gdk_events_queue (display); + + GDK_DISPLAY_GET_CLASS (display)->queue_events (display); return _gdk_event_unqueue (display); } @@ -468,7 +387,7 @@ gdk_display_pointer_ungrab (GdkDisplay *display, { device = dev->data; - if (device->source != GDK_SOURCE_MOUSE) + if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE) continue; gdk_device_ungrab (device, time_); @@ -544,7 +463,7 @@ gdk_display_keyboard_ungrab (GdkDisplay *display, { device = dev->data; - if (device->source != GDK_SOURCE_KEYBOARD) + if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) continue; gdk_device_ungrab (device, time); @@ -582,127 +501,26 @@ gdk_beep (void) } /** - * gdk_event_send_client_message: - * @event: the #GdkEvent to send, which should be a #GdkEventClient. - * @winid: the window to send the X ClientMessage event to. - * - * Sends an X ClientMessage event to a given window (which must be - * on the default #GdkDisplay.) - * This could be used for communicating between different applications, - * though the amount of data is limited to 20 bytes. - * - * Return value: non-zero on success. - **/ -gboolean -gdk_event_send_client_message (GdkEvent *event, - GdkNativeWindow winid) -{ - g_return_val_if_fail (event != NULL, FALSE); - - return gdk_event_send_client_message_for_display (gdk_display_get_default (), - event, winid); -} - -/** - * gdk_event_send_clientmessage_toall: - * @event: the #GdkEvent to send, which should be a #GdkEventClient. - * - * Sends an X ClientMessage event to all toplevel windows on the default - * #GdkScreen. - * - * Toplevel windows are determined by checking for the WM_STATE property, as - * described in the Inter-Client Communication Conventions Manual (ICCCM). - * If no windows are found with the WM_STATE property set, the message is sent - * to all children of the root window. - **/ -void -gdk_event_send_clientmessage_toall (GdkEvent *event) -{ - g_return_if_fail (event != NULL); - - gdk_screen_broadcast_client_message (gdk_screen_get_default (), event); -} - -/** - * gdk_device_get_core_pointer: - * - * Returns the core pointer device for the default display. - * - * Return value: the core pointer device; this is owned by the - * display and should not be freed. - * - * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or - * gdk_event_get_device() if a #GdkEvent with pointer device - * information is available. - **/ -GdkDevice * -gdk_device_get_core_pointer (void) -{ - return gdk_display_get_core_pointer (gdk_display_get_default ()); -} - -/** - * gdk_display_get_core_pointer: - * @display: a #GdkDisplay - * - * Returns the core pointer device for the given display - * - * Return value: the core pointer device; this is owned by the - * display and should not be freed. + * gdk_flush: * - * Since: 2.2 - * - * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or - * gdk_event_get_device() if a #GdkEvent with device - * information is available. - **/ -GdkDevice * -gdk_display_get_core_pointer (GdkDisplay *display) -{ - return display->core_pointer; -} - -/** - * gdk_set_sm_client_id: - * @sm_client_id: the client id assigned by the session manager when the - * connection was opened, or %NULL to remove the property. - * - * Sets the SM_CLIENT_ID property on the application's leader window so that - * the window manager can save the application's state using the X11R6 ICCCM - * session management protocol. - * - * See the X Session Management Library documentation for more information on - * session management and the Inter-Client Communication Conventions Manual - * (ICCCM) for information on the WM_CLIENT_LEADER property. - * (Both documents are part of the X Window System distribution.) - **/ + * Flushes the output buffers of all display connections and waits + * until all requests have been processed. + * This is rarely needed by applications. + */ void -gdk_set_sm_client_id (const gchar* sm_client_id) +gdk_flush (void) { - GSList *displays, *tmp_list; - - g_free (gdk_sm_client_id); - gdk_sm_client_id = g_strdup (sm_client_id); + GSList *list, *l; - displays = gdk_display_manager_list_displays (gdk_display_manager_get ()); - for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next) - _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id); + list = gdk_display_manager_list_displays (gdk_display_manager_get ()); + for (l = list; l; l = l->next) + { + GdkDisplay *display = l->data; - g_slist_free (displays); -} + GDK_DISPLAY_GET_CLASS (display)->sync (display); + } -/** - * _gdk_get_sm_client_id: - * - * Gets the client ID set with gdk_set_sm_client_id(), if any. - * - * Return value: Session ID, or %NULL if gdk_set_sm_client_id() - * has never been called. - **/ -const char * -_gdk_get_sm_client_id (void) -{ - return gdk_sm_client_id; + g_slist_free (list); } void @@ -722,7 +540,7 @@ _gdk_display_enable_motion_hints (GdkDisplay *display, if (*device_serial != 0) { - serial = _gdk_windowing_window_get_next_serial (display); + serial = _gdk_display_get_next_serial (display); /* We might not actually generate the next request, so make sure this triggers always, this may cause it to trigger slightly too early, but this is just a hint @@ -734,117 +552,10 @@ _gdk_display_enable_motion_hints (GdkDisplay *display, } } -/** - * gdk_display_get_device_state: - * @display: a #GdkDisplay. - * @device: device to query status to. - * @screen: location to store the #GdkScreen the @device is on, or %NULL. - * @x: location to store root window X coordinate of @device, or %NULL. - * @y: location to store root window Y coordinate of @device, or %NULL. - * @mask: location to store current modifier mask for @device, or %NULL. - * - * Gets the current location and state of @device for a given display. - * - * Since: 3.0 - **/ -void -gdk_display_get_device_state (GdkDisplay *display, - GdkDevice *device, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask) -{ - GdkScreen *tmp_screen; - gint tmp_x, tmp_y; - GdkModifierType tmp_mask; - - g_return_if_fail (GDK_IS_DISPLAY (display)); - g_return_if_fail (GDK_IS_DEVICE (device)); - - display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask); - - if (screen) - *screen = tmp_screen; - if (x) - *x = tmp_x; - if (y) - *y = tmp_y; - if (mask) - *mask = tmp_mask; -} - -/** - * gdk_display_get_window_at_device_position: - * @display: a #GdkDisplay. - * @device: #GdkDevice to query info to. - * @win_x: return location for the X coordinate of the device location, relative to the window origin, or %NULL. - * @win_y: return location for the Y coordinate of the device location, relative to the window origin, or %NULL. - * - * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns - * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application). - * - * Returns: the #GdkWindow under the device position, or %NULL. - * - * Since: 3.0 - **/ -GdkWindow * -gdk_display_get_window_at_device_position (GdkDisplay *display, - GdkDevice *device, - gint *win_x, - gint *win_y) -{ - gint tmp_x, tmp_y; - GdkWindow *window; - - g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); - - window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y); - - if (win_x) - *win_x = tmp_x; - if (win_y) - *win_y = tmp_y; - - return window; -} - -/** - * gdk_display_set_device_hooks: - * @display: a #GdkDisplay. - * @new_hooks: a table of pointers to functions for getting quantities related to all - * devices position, or %NULL to restore the default table. - * - * This function allows for hooking into the operation of getting the current location of any - * #GdkDevice on a particular #GdkDisplay. This is only useful for such low-level tools as - * an event recorder. Applications should never have any reason to use this facility. - * - * Returns: The previous device hook table. - * - * Since: 3.0 - **/ -GdkDisplayDeviceHooks * -gdk_display_set_device_hooks (GdkDisplay *display, - const GdkDisplayDeviceHooks *new_hooks) -{ - const GdkDisplayDeviceHooks *result; - - g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - result = display->device_hooks; - - if (new_hooks) - display->device_hooks = new_hooks; - else - display->device_hooks = &default_device_hooks; - - return (GdkDisplayDeviceHooks *) result; -} - /** * gdk_display_get_pointer: * @display: a #GdkDisplay - * @screen: (allow-none): location to store the screen that the + * @screen: (out) (allow-none): location to store the screen that the * cursor is on, or %NULL. * @x: (out) (allow-none): location to store root window X coordinate of pointer, or %NULL. * @y: (out) (allow-none): location to store root window Y coordinate of pointer, or %NULL. @@ -855,7 +566,7 @@ gdk_display_set_device_hooks (GdkDisplay *display, * * Since: 2.2 * - * Deprecated: 3.0: Use gdk_display_get_device_state() instead. + * Deprecated: 3.0: Use gdk_device_get_position() instead. **/ void gdk_display_get_pointer (GdkDisplay *display, @@ -864,74 +575,36 @@ gdk_display_get_pointer (GdkDisplay *display, gint *y, GdkModifierType *mask) { - g_return_if_fail (GDK_IS_DISPLAY (display)); - - gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask); -} - -static GdkWindow * -gdk_display_real_get_window_at_device_position (GdkDisplay *display, - GdkDevice *device, - gint *win_x, - gint *win_y) -{ - GdkWindow *window; - gint x, y; - - window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE); - - /* This might need corrections, as the native window returned - may contain client side children */ - if (window) - { - double xx, yy; - - window = _gdk_window_find_descendant_at (window, - x, y, - &xx, &yy); - x = floor (xx + 0.5); - y = floor (yy + 0.5); - } + GdkScreen *default_screen; + GdkWindow *root; + gint tmp_x, tmp_y; + GdkModifierType tmp_mask; - *win_x = x; - *win_y = y; + g_return_if_fail (GDK_IS_DISPLAY (display)); - return window; -} + if (gdk_display_is_closed (display)) + return; -static GdkWindow * -gdk_window_real_window_get_device_position (GdkDisplay *display, - GdkDevice *device, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) -{ - GdkWindowObject *private; - gint tmpx, tmpy; - GdkModifierType tmp_mask; - gboolean normal_child; + default_screen = gdk_display_get_default_screen (display); - private = (GdkWindowObject *) window; + /* We call _gdk_device_query_state() here manually instead of + * gdk_device_get_position() because we care about the modifier mask */ - normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_device_state (window, - device, - &tmpx, &tmpy, - &tmp_mask); - /* We got the coords on the impl, convert to the window */ - tmpx -= private->abs_x; - tmpy -= private->abs_y; + _gdk_device_query_state (display->core_pointer, + gdk_screen_get_root_window (default_screen), + &root, NULL, + &tmp_x, &tmp_y, + NULL, NULL, + &tmp_mask); + if (screen) + *screen = gdk_window_get_screen (root); if (x) - *x = tmpx; + *x = tmp_x; if (y) - *y = tmpy; + *y = tmp_y; if (mask) *mask = tmp_mask; - - if (normal_child) - return _gdk_window_find_child_at (window, tmpx, tmpy); - return NULL; } /** @@ -951,7 +624,7 @@ gdk_window_real_window_get_device_position (GdkDisplay *display, * * Since: 2.2 * - * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead. + * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead. **/ GdkWindow * gdk_display_get_window_at_pointer (GdkDisplay *display, @@ -960,209 +633,7 @@ gdk_display_get_window_at_pointer (GdkDisplay *display, { g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - return gdk_display_get_window_at_device_position (display, display->core_pointer, win_x, win_y); -} - -static void -multihead_get_device_state (GdkDisplay *display, - GdkDevice *device, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask) -{ - multihead_current_pointer_hooks->get_pointer (display, screen, x, y, mask); -} - -static GdkWindow * -multihead_window_get_device_position (GdkDisplay *display, - GdkDevice *device, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) -{ - return multihead_current_pointer_hooks->window_get_pointer (display, window, x, y, mask); -} - -static GdkWindow * -multihead_window_at_device_position (GdkDisplay *display, - GdkDevice *device, - gint *win_x, - gint *win_y) -{ - return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y); -} - -static void -multihead_default_get_pointer (GdkDisplay *display, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask) -{ - return _gdk_windowing_get_device_state (display, - display->core_pointer, - screen, x, y, mask); -} - -static GdkWindow * -multihead_default_window_get_pointer (GdkDisplay *display, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) -{ - return gdk_window_real_window_get_device_position (display, - display->core_pointer, - window, x, y, mask); -} - -static GdkWindow * -multihead_default_window_at_pointer (GdkDisplay *display, - gint *win_x, - gint *win_y) -{ - return gdk_display_real_get_window_at_device_position (display, - display->core_pointer, - win_x, win_y); -} - -/** - * gdk_display_set_pointer_hooks: - * @display: a #GdkDisplay - * @new_hooks: a table of pointers to functions for getting - * quantities related to the current pointer position, - * or %NULL to restore the default table. - * - * This function allows for hooking into the operation - * of getting the current location of the pointer on a particular - * display. This is only useful for such low-level tools as an - * event recorder. Applications should never have any - * reason to use this facility. - * - * Return value: the previous pointer hook table - * - * Since: 2.2 - * - * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead. - **/ -GdkDisplayPointerHooks * -gdk_display_set_pointer_hooks (GdkDisplay *display, - const GdkDisplayPointerHooks *new_hooks) -{ - const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks; - - g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - - if (new_hooks) - multihead_current_pointer_hooks = new_hooks; - else - multihead_current_pointer_hooks = &multihead_default_pointer_hooks; - - gdk_display_set_device_hooks (display, &multihead_pointer_hooks); - - return (GdkDisplayPointerHooks *)result; -} - -static void -singlehead_get_pointer (GdkDisplay *display, - GdkScreen **screen, - gint *x, - gint *y, - GdkModifierType *mask) -{ - GdkScreen *default_screen = gdk_display_get_default_screen (display); - GdkWindow *root_window = gdk_screen_get_root_window (default_screen); - - *screen = default_screen; - - singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask); -} - -static GdkWindow* -singlehead_window_get_pointer (GdkDisplay *display, - GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) -{ - return singlehead_current_pointer_hooks->get_pointer (window, x, y, mask); -} - -static GdkWindow* -singlehead_window_at_pointer (GdkDisplay *display, - gint *win_x, - gint *win_y) -{ - GdkScreen *default_screen = gdk_display_get_default_screen (display); - - return singlehead_current_pointer_hooks->window_at_pointer (default_screen, - win_x, win_y); -} - -static GdkWindow* -singlehead_default_window_get_pointer (GdkWindow *window, - gint *x, - gint *y, - GdkModifierType *mask) -{ - GdkDisplay *display; - - display = gdk_window_get_display (window); - - return gdk_window_real_window_get_device_position (display, - display->core_pointer, - window, x, y, mask); -} - -static GdkWindow* -singlehead_default_window_at_pointer (GdkScreen *screen, - gint *win_x, - gint *win_y) -{ - GdkDisplay *display; - - display = gdk_screen_get_display (screen); - - return gdk_display_real_get_window_at_device_position (display, - display->core_pointer, - win_x, win_y); -} - -/** - * gdk_set_pointer_hooks: - * @new_hooks: a table of pointers to functions for getting - * quantities related to the current pointer position, - * or %NULL to restore the default table. - * - * This function allows for hooking into the operation - * of getting the current location of the pointer. This - * is only useful for such low-level tools as an - * event recorder. Applications should never have any - * reason to use this facility. - * - * This function is not multihead safe. For multihead operation, - * see gdk_display_set_pointer_hooks(). - * - * Return value: the previous pointer hook table - * - * Deprecated: 3.0: Use gdk_display_set_device_hooks() instead. - **/ -GdkPointerHooks * -gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks) -{ - const GdkPointerHooks *result = singlehead_current_pointer_hooks; - - if (new_hooks) - singlehead_current_pointer_hooks = new_hooks; - else - singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks; - - gdk_display_set_pointer_hooks (gdk_display_get_default (), - &singlehead_pointer_hooks); - - return (GdkPointerHooks *)result; + return gdk_device_get_window_at_position (display->core_pointer, win_x, win_y); } static void @@ -1183,7 +654,7 @@ generate_grab_broken_event (GdkWindow *window, event->grab_broken.implicit = implicit; event->grab_broken.grab_window = grab_window; gdk_event_set_device (event, device); - event->grab_broken.keyboard = (device->source == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE; + event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE; gdk_event_put (event); gdk_event_free (event); @@ -1276,6 +747,7 @@ _gdk_display_add_device_grab (GdkDisplay *display, static void synthesize_crossing_events (GdkDisplay *display, GdkDevice *device, + GdkDevice *source_device, GdkWindow *src_window, GdkWindow *dest_window, GdkCrossingMode crossing_mode, @@ -1311,7 +783,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, src_window, dest_window, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1325,7 +797,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, src_window, NULL, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1340,7 +812,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, src_window, NULL, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1351,7 +823,7 @@ synthesize_crossing_events (GdkDisplay *display, _gdk_synthesize_crossing_events (display, NULL, dest_window, - device, + device, source_device, crossing_mode, x, y, state, time, @@ -1371,7 +843,7 @@ get_current_toplevel (GdkDisplay *display, int x, y; GdkModifierType state; - pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE); + pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE); if (pointer_window != NULL && (GDK_WINDOW_DESTROYED (pointer_window) || @@ -1382,12 +854,14 @@ get_current_toplevel (GdkDisplay *display, *x_out = x; *y_out = y; *state_out = state; + return pointer_window; } static void switch_to_pointer_grab (GdkDisplay *display, GdkDevice *device, + GdkDevice *source_device, GdkDeviceGrabInfo *grab, GdkDeviceGrabInfo *last_grab, guint32 time, @@ -1397,7 +871,7 @@ switch_to_pointer_grab (GdkDisplay *display, GdkPointerWindowInfo *info; GList *old_grabs; GdkModifierType state; - int x, y; + int x = 0, y = 0; /* Temporarily unset pointer to make sure we send the crossing events below */ old_grabs = g_hash_table_lookup (display->device_grabs, device); @@ -1423,7 +897,7 @@ switch_to_pointer_grab (GdkDisplay *display, src_window = info->window_under_pointer; if (src_window != grab->window) - synthesize_crossing_events (display, device, + synthesize_crossing_events (display, device, source_device, src_window, grab->window, GDK_CROSSING_GRAB, time, serial); @@ -1450,7 +924,14 @@ switch_to_pointer_grab (GdkDisplay *display, g_object_unref (info->toplevel_under_pointer); info->toplevel_under_pointer = NULL; - new_toplevel = get_current_toplevel (display, device, &x, &y, &state); + /* Ungrabbed slave devices don't have a position by + * itself, rather depend on its master pointer, so + * it doesn't make sense to track any position for + * these after the grab + */ + if (grab || gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE) + new_toplevel = get_current_toplevel (display, device, &x, &y, &state); + if (new_toplevel) { /* w is now toplevel and x,y in toplevel coords */ @@ -1474,7 +955,7 @@ switch_to_pointer_grab (GdkDisplay *display, } if (pointer_window != last_grab->window) - synthesize_crossing_events (display, device, + synthesize_crossing_events (display, device, source_device, last_grab->window, pointer_window, GDK_CROSSING_UNGRAB, time, serial); @@ -1489,6 +970,7 @@ switch_to_pointer_grab (GdkDisplay *display, void _gdk_display_device_grab_update (GdkDisplay *display, GdkDevice *device, + GdkDevice *source_device, gulong current_serial) { GdkDeviceGrabInfo *current_grab, *next_grab; @@ -1512,8 +994,8 @@ _gdk_display_device_grab_update (GdkDisplay *display, if (!current_grab->activated) { - if (device->source != GDK_SOURCE_KEYBOARD) - switch_to_pointer_grab (display, device, current_grab, NULL, time, current_serial); + if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) + switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial); } break; @@ -1540,8 +1022,8 @@ _gdk_display_device_grab_update (GdkDisplay *display, grabs = g_list_delete_link (grabs, grabs); g_hash_table_insert (display->device_grabs, device, grabs); - if (device->source != GDK_SOURCE_KEYBOARD) - switch_to_pointer_grab (display, device, + if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD) + switch_to_pointer_grab (display, device, source_device, next_grab, current_grab, time, current_serial); @@ -1637,7 +1119,7 @@ _gdk_display_check_grab_ownership (GdkDisplay *display, g_hash_table_iter_init (&iter, display->device_grabs); higher_ownership = device_ownership = GDK_OWNERSHIP_NONE; - device_is_keyboard = (device->source == GDK_SOURCE_KEYBOARD); + device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD); while (g_hash_table_iter_next (&iter, &key, &value)) { @@ -1653,8 +1135,8 @@ _gdk_display_check_grab_ownership (GdkDisplay *display, continue; /* Discard device if it's not of the same type */ - if ((device_is_keyboard && dev->source != GDK_SOURCE_KEYBOARD) || - (!device_is_keyboard && dev->source == GDK_SOURCE_KEYBOARD)) + if ((device_is_keyboard && gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) || + (!device_is_keyboard && gdk_device_get_source (dev) == GDK_SOURCE_KEYBOARD)) continue; grab = grabs->data; @@ -1722,8 +1204,8 @@ _gdk_display_pointer_info_foreach (GdkDisplay *display, * gdk_device_grab_info_libgtk_only: * @display: the display for which to get the grab information * @device: device to get the grab information from - * @grab_window: location to store current grab window - * @owner_events: location to store boolean indicating whether + * @grab_window: (out) (transfer none): location to store current grab window + * @owner_events: (out): location to store boolean indicating whether * the @owner_events flag to gdk_keyboard_grab() or * gdk_pointer_grab() was %TRUE. * @@ -1787,7 +1269,7 @@ gdk_display_pointer_is_grabbed (GdkDisplay *display) { device = dev->data; - if (device->source == GDK_SOURCE_MOUSE && + if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE && gdk_display_device_is_grabbed (display, device)) return TRUE; } @@ -1827,7 +1309,7 @@ gdk_display_device_is_grabbed (GdkDisplay *display, * * Returns the #GdkDeviceManager associated to @display. * - * Returns: A #GdkDeviceManager, or %NULL. This memory is + * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is * owned by GDK and must not be freed or unreferenced. * * Since: 3.0 @@ -1839,3 +1321,771 @@ gdk_display_get_device_manager (GdkDisplay *display) return display->device_manager; } + +/** + * gdk_display_get_name: + * @display: a #GdkDisplay + * + * Gets the name of the display. + * + * Returns: a string representing the display name. This string is owned + * by GDK and should not be modified or freed. + * + * Since: 2.2 + */ +G_CONST_RETURN gchar * +gdk_display_get_name (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_name (display); +} + +gchar * +gdk_get_display (void) +{ + return g_strdup (gdk_display_get_name (gdk_display_get_default ())); +} + +/** + * gdk_display_get_n_screens: + * @display: a #GdkDisplay + * + * Gets the number of screen managed by the @display. + * + * Returns: number of screens. + * + * Since: 2.2 + */ +gint +gdk_display_get_n_screens (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_n_screens (display); +} + +/** + * gdk_display_get_screen: + * @display: a #GdkDisplay + * @screen_num: the screen number + * + * Returns a screen object for one of the screens of the display. + * + * Returns: (transfer none): the #GdkScreen object + * + * Since: 2.2 + */ +GdkScreen * +gdk_display_get_screen (GdkDisplay *display, + gint screen_num) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_screen (display, screen_num); +} + +/** + * gdk_display_get_default_screen: + * @display: a #GdkDisplay + * + * Get the default #GdkScreen for @display. + * + * Returns: (transfer none): the default #GdkScreen object for @display + * + * Since: 2.2 + */ +GdkScreen * +gdk_display_get_default_screen (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_default_screen (display); +} + +/** + * gdk_display_beep: + * @display: a #GdkDisplay + * + * Emits a short beep on @display + * + * Since: 2.2 + */ +void +gdk_display_beep (GdkDisplay *display) +{ + GDK_DISPLAY_GET_CLASS(display)->beep (display); +} + +/** + * gdk_display_sync: + * @display: a #GdkDisplay + * + * Flushes any requests queued for the windowing system and waits until all + * requests have been handled. This is often used for making sure that the + * display is synchronized with the current state of the program. Calling + * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors + * generated from earlier requests are handled before the error trap is + * removed. + * + * This is most useful for X11. On windowing systems where requests are + * handled synchronously, this function will do nothing. + * + * Since: 2.2 + */ +void +gdk_display_sync (GdkDisplay *display) +{ + GDK_DISPLAY_GET_CLASS(display)->sync (display); +} + +/** + * gdk_display_flush: + * @display: a #GdkDisplay + * + * Flushes any requests queued for the windowing system; this happens automatically + * when the main loop blocks waiting for new events, but if your application + * is drawing without returning control to the main loop, you may need + * to call this function explicitely. A common case where this function + * needs to be called is when an application is executing drawing commands + * from a thread other than the thread where the main loop is running. + * + * This is most useful for X11. On windowing systems where requests are + * handled synchronously, this function will do nothing. + * + * Since: 2.4 + */ +void +gdk_display_flush (GdkDisplay *display) +{ + GDK_DISPLAY_GET_CLASS(display)->flush (display); +} + +/** + * gdk_display_get_default_group: + * @display: a #GdkDisplay + * + * Returns the default group leader window for all toplevel windows + * on @display. This window is implicitly created by GDK. + * See gdk_window_set_group(). + * + * Return value: (transfer none): The default group leader window + * for @display + * + * Since: 2.4 + **/ +GdkWindow * +gdk_display_get_default_group (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_default_group (display); +} + +/** + * gdk_display_supports_selection_notification: + * @display: a #GdkDisplay + * + * Returns whether #GdkEventOwnerChange events will be + * sent when the owner of a selection changes. + * + * Return value: whether #GdkEventOwnerChange events will + * be sent. + * + * Since: 2.6 + **/ +gboolean +gdk_display_supports_selection_notification (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->supports_selection_notification (display); +} + +/** + * gdk_display_request_selection_notification: + * @display: a #GdkDisplay + * @selection: the #GdkAtom naming the selection for which + * ownership change notification is requested + * + * Request #GdkEventOwnerChange events for ownership changes + * of the selection named by the given atom. + * + * Return value: whether #GdkEventOwnerChange events will + * be sent. + * + * Since: 2.6 + **/ +gboolean +gdk_display_request_selection_notification (GdkDisplay *display, + GdkAtom selection) + +{ + return GDK_DISPLAY_GET_CLASS(display)->request_selection_notification (display, selection); +} + +/** + * gdk_display_supports_clipboard_persistence + * @display: a #GdkDisplay + * + * Returns whether the speicifed display supports clipboard + * persistance; i.e. if it's possible to store the clipboard data after an + * application has quit. On X11 this checks if a clipboard daemon is + * running. + * + * Returns: %TRUE if the display supports clipboard persistance. + * + * Since: 2.6 + */ +gboolean +gdk_display_supports_clipboard_persistence (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->supports_clipboard_persistence (display); +} + +/** + * gdk_display_store_clipboard + * @display: a #GdkDisplay + * @clipboard_window: a #GdkWindow belonging to the clipboard owner + * @time_: a timestamp + * @targets: (array length=n_targets): an array of targets + * that should be saved, or %NULL + * if all available targets should be saved. + * @n_targets: length of the @targets array + * + * Issues a request to the clipboard manager to store the + * clipboard data. On X11, this is a special program that works + * according to the freedesktop clipboard specification, available at + * + * http://www.freedesktop.org/Standards/clipboard-manager-spec. + * + * Since: 2.6 + */ +void +gdk_display_store_clipboard (GdkDisplay *display, + GdkWindow *clipboard_window, + guint32 time_, + const GdkAtom *targets, + gint n_targets) +{ + GDK_DISPLAY_GET_CLASS(display)->store_clipboard (display, clipboard_window, time_, targets, n_targets); +} + +/** + * gdk_display_supports_shapes: + * @display: a #GdkDisplay + * + * Returns %TRUE if gdk_window_shape_combine_mask() can + * be used to create shaped windows on @display. + * + * Returns: %TRUE if shaped windows are supported + * + * Since: 2.10 + */ +gboolean +gdk_display_supports_shapes (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->supports_shapes (display); +} + +/** + * gdk_display_supports_input_shapes: + * @display: a #GdkDisplay + * + * Returns %TRUE if gdk_window_input_shape_combine_mask() can + * be used to modify the input shape of windows on @display. + * + * Returns: %TRUE if windows with modified input shape are supported + * + * Since: 2.10 + */ +gboolean +gdk_display_supports_input_shapes (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->supports_input_shapes (display); +} + +/** + * gdk_display_supports_composite: + * @display: a #GdkDisplay + * + * Returns %TRUE if gdk_window_set_composited() can be used + * to redirect drawing on the window using compositing. + * + * Currently this only works on X11 with XComposite and + * XDamage extensions available. + * + * Returns: %TRUE if windows may be composited. + * + * Since: 2.12 + */ +gboolean +gdk_display_supports_composite (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->supports_composite (display); +} + +/** + * gdk_display_list_devices: + * @display: a #GdkDisplay + * + * Returns the list of available input devices attached to @display. + * The list is statically allocated and should not be freed. + * + * Return value: (transfer none) (element-type GdkDevice): + * a list of #GdkDevice + * + * Since: 2.2 + * + * Deprecated: 3.0: Use gdk_device_manager_list_devices() instead. + **/ +GList * +gdk_display_list_devices (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->list_devices (display); +} + +static GdkAppLaunchContext * +gdk_display_real_get_app_launch_context (GdkDisplay *display) +{ + GdkAppLaunchContext *ctx; + + ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT, + "display", display, + NULL); + + return ctx; +} + +/** + * gdk_display_get_app_launch_context: + * @display: a #GdkDisplay + * + * Returns a #GdkAppLaunchContext suitable for launching + * applications on the given display. + * + * Returns: (transfer full): a new #GdkAppLaunchContext for @display. + * Free with g_object_unref() when done + * + * Since: 3.0 + */ +GdkAppLaunchContext * +gdk_display_get_app_launch_context (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS(display)->get_app_launch_context (display); +} + +/** + * gdk_display_open: + * @display_name: the name of the display to open + * + * Opens a display. + * + * Return value: (transfer none): a #GdkDisplay, or %NULL + * if the display could not be opened + * + * Since: 2.2 + */ +GdkDisplay * +gdk_display_open (const gchar *display_name) +{ + return gdk_display_manager_open_display (gdk_display_manager_get (), display_name); +} + +/** + * gdk_display_has_pending: + * @display: a #GdkDisplay + * + * Returns whether the display has events that are waiting + * to be processed. + * + * Returns: %TRUE if there are events ready to be processed. + * + * Since: 3.0 + */ +gboolean +gdk_display_has_pending (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS (display)->has_pending (display); +} + +/** + * gdk_display_supports_cursor_alpha: + * @display: a #GdkDisplay + * + * Returns %TRUE if cursors can use an 8bit alpha channel + * on @display. Otherwise, cursors are restricted to bilevel + * alpha (i.e. a mask). + * + * Returns: whether cursors can have alpha channels. + * + * Since: 2.4 + */ +gboolean +gdk_display_supports_cursor_alpha (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_alpha (display); +} + +/** + * gdk_display_supports_cursor_color: + * @display: a #GdkDisplay + * + * Returns %TRUE if multicolored cursors are supported + * on @display. Otherwise, cursors have only a forground + * and a background color. + * + * Returns: whether cursors can have multiple colors. + * + * Since: 2.4 + */ +gboolean +gdk_display_supports_cursor_color (GdkDisplay *display) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + return GDK_DISPLAY_GET_CLASS (display)->supports_cursor_color (display); +} + +/** + * gdk_display_get_default_cursor_size: + * @display: a #GdkDisplay + * + * Returns the default size to use for cursors on @display. + * + * Returns: the default cursor size. + * + * Since: 2.4 + */ +guint +gdk_display_get_default_cursor_size (GdkDisplay *display) +{ + guint width, height; + + g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE); + + GDK_DISPLAY_GET_CLASS (display)->get_default_cursor_size (display, + &width, + &height); + + return MIN (width, height); +} + +/** + * gdk_display_get_maximal_cursor_size: + * @display: a #GdkDisplay + * @width: (out): the return location for the maximal cursor width + * @height: (out): the return location for the maximal cursor height + * + * Gets the maximal size to use for cursors on @display. + * + * Since: 2.4 + */ +void +gdk_display_get_maximal_cursor_size (GdkDisplay *display, + guint *width, + guint *height) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + GDK_DISPLAY_GET_CLASS (display)->get_maximal_cursor_size (display, + width, + height); +} + +/** + * gdk_display_warp_pointer: + * @display: a #GdkDisplay + * @screen: the screen of @display to warp the pointer to + * @x: the x coordinate of the destination + * @y: the y coordinate of the destination + * + * Warps the pointer of @display to the point @x,@y on + * the screen @screen, unless the pointer is confined + * to a window by a grab, in which case it will be moved + * as far as allowed by the grab. Warping the pointer + * creates events as if the user had moved the mouse + * instantaneously to the destination. + * + * Note that the pointer should normally be under the + * control of the user. This function was added to cover + * some rare use cases like keyboard navigation support + * for the color picker in the #GtkColorSelectionDialog. + * + * Since: 2.8 + * + * Deprecated: 3.0: Use gdk_device_warp() instead. + */ +void +gdk_display_warp_pointer (GdkDisplay *display, + GdkScreen *screen, + gint x, + gint y) +{ + gdk_device_warp (display->core_pointer, + screen, + x, y); +} + +gulong +_gdk_display_get_next_serial (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS (display)->get_next_serial (display); +} + + +/** + * gdk_notify_startup_complete: + * + * Indicates to the GUI environment that the application has finished + * loading. If the applications opens windows, this function is + * normally called after opening the application's initial set of + * windows. + * + * GTK+ will call this function automatically after opening the first + * #GtkWindow unless gtk_window_set_auto_startup_notification() is called + * to disable that feature. + * + * Since: 2.2 + **/ +void +gdk_notify_startup_complete (void) +{ + gdk_notify_startup_complete_with_id (NULL); +} + +/** + * gdk_notify_startup_complete_with_id: + * @startup_id: a startup-notification identifier, for which + * notification process should be completed + * + * Indicates to the GUI environment that the application has + * finished loading, using a given identifier. + * + * GTK+ will call this function automatically for #GtkWindow + * with custom startup-notification identifier unless + * gtk_window_set_auto_startup_notification() is called to + * disable that feature. + * + * Since: 2.12 + */ +void +gdk_notify_startup_complete_with_id (const gchar* startup_id) +{ + GdkDisplay *display; + + display = gdk_display_get_default (); + if (display) + gdk_display_notify_startup_complete (display, startup_id); +} + +/** + * gdk_display_notify_startup_complete: + * @display: a #GdkDisplay + * @startup_id: a startup-notification identifier, for which + * notification process should be completed + * + * Indicates to the GUI environment that the application has + * finished loading, using a given identifier. + * + * GTK+ will call this function automatically for #GtkWindow + * with custom startup-notification identifier unless + * gtk_window_set_auto_startup_notification() is called to + * disable that feature. + * + * Since: 3.0 + */ +void +gdk_display_notify_startup_complete (GdkDisplay *display, + const gchar *startup_id) +{ + GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id); +} + +void +_gdk_display_event_data_copy (GdkDisplay *display, + const GdkEvent *event, + GdkEvent *new_event) +{ + GDK_DISPLAY_GET_CLASS (display)->event_data_copy (display, event, new_event); +} + +void +_gdk_display_event_data_free (GdkDisplay *display, + GdkEvent *event) +{ + GDK_DISPLAY_GET_CLASS (display)->event_data_free (display, event); +} + +void +_gdk_display_create_window_impl (GdkDisplay *display, + GdkWindow *window, + GdkWindow *real_parent, + GdkScreen *screen, + GdkEventMask event_mask, + GdkWindowAttr *attributes, + gint attributes_mask) +{ + GDK_DISPLAY_GET_CLASS (display)->create_window_impl (display, + window, + real_parent, + screen, + event_mask, + attributes, + attributes_mask); +} + +GdkWindow * +_gdk_display_create_window (GdkDisplay *display) +{ + return g_object_new (GDK_DISPLAY_GET_CLASS (display)->window_type, NULL); +} + +/** + * gdk_keymap_get_for_display: + * @display: the #GdkDisplay. + * + * Returns the #GdkKeymap attached to @display. + * + * Return value: (transfer none): the #GdkKeymap attached to @display. + * + * Since: 2.2 + */ +GdkKeymap* +gdk_keymap_get_for_display (GdkDisplay *display) +{ + return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display); +} + +typedef struct _GdkGlobalErrorTrap GdkGlobalErrorTrap; + +struct _GdkGlobalErrorTrap +{ + GSList *displays; +}; + +static GQueue gdk_error_traps = G_QUEUE_INIT; + +/** + * gdk_error_trap_push: + * + * This function allows X errors to be trapped instead of the normal + * behavior of exiting the application. It should only be used if it + * is not possible to avoid the X error in any other way. Errors are + * ignored on all #GdkDisplay currently known to the + * #GdkDisplayManager. If you don't care which error happens and just + * want to ignore everything, pop with gdk_error_trap_pop_ignored(). + * If you need the error code, use gdk_error_trap_pop() which may have + * to block and wait for the error to arrive from the X server. + * + * This API exists on all platforms but only does anything on X. + * + * You can use gdk_x11_display_error_trap_push() to ignore errors + * on only a single display. + * +* + * Trapping an X error + * + * gdk_error_trap_push (); + * + * // ... Call the X function which may cause an error here ... + * + * + * if (gdk_error_trap_pop ()) + * { + * // ... Handle the error here ... + * } + * + * + */ +void +gdk_error_trap_push (void) +{ + GdkDisplayManager *manager; + GdkDisplayClass *class; + GdkGlobalErrorTrap *trap; + GSList *l; + + manager = gdk_display_manager_get (); + class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager)); + + if (class->push_error_trap == NULL) + return; + + trap = g_slice_new (GdkGlobalErrorTrap); + trap->displays = gdk_display_manager_list_displays (manager); + + g_slist_foreach (trap->displays, (GFunc) g_object_ref, NULL); + for (l = trap->displays; l != NULL; l = l->next) + { + class->push_error_trap (l->data); + } + + g_queue_push_head (&gdk_error_traps, trap); +} + +static gint +gdk_error_trap_pop_internal (gboolean need_code) +{ + GdkDisplayManager *manager; + GdkDisplayClass *class; + GdkGlobalErrorTrap *trap; + gint result; + GSList *l; + + manager = gdk_display_manager_get (); + class = GDK_DISPLAY_GET_CLASS (gdk_display_manager_get_default_display (manager)); + + if (class->pop_error_trap == NULL) + return 0; + + trap = g_queue_pop_head (&gdk_error_traps); + + g_return_val_if_fail (trap != NULL, 0); + + result = 0; + for (l = trap->displays; l != NULL; l = l->next) + { + gint code = 0; + + code = class->pop_error_trap (l->data, !need_code); + + /* we use the error on the last display listed, why not. */ + if (code != 0) + result = code; + } + + g_slist_free_full (trap->displays, g_object_unref); + g_slice_free (GdkGlobalErrorTrap, trap); + + return result; +} + +/** + * gdk_error_trap_pop_ignored: + * + * Removes an error trap pushed with gdk_error_trap_push(), but + * without bothering to wait and see whether an error occurred. If an + * error arrives later asynchronously that was triggered while the + * trap was pushed, that error will be ignored. + * + * Since: 3.0 + */ +void +gdk_error_trap_pop_ignored (void) +{ + gdk_error_trap_pop_internal (FALSE); +} + +/** + * gdk_error_trap_pop: + * + * Removes an error trap pushed with gdk_error_trap_push(). + * May block until an error has been definitively received + * or not received from the X server. gdk_error_trap_pop_ignored() + * is preferred if you don't need to know whether an error + * occurred, because it never has to block. If you don't + * need the return value of gdk_error_trap_pop(), use + * gdk_error_trap_pop_ignored(). + * + * Prior to GDK 3.0, this function would not automatically + * sync for you, so you had to gdk_flush() if your last + * call to Xlib was not a blocking round trip. + * + * Return value: X error code or 0 on success + */ +gint +gdk_error_trap_pop (void) +{ + return gdk_error_trap_pop_internal (TRUE); +}