*/
#include "config.h"
-#include <math.h>
-#include <glib.h>
-#include "gdk.h" /* gdk_event_send_client_message() */
+
#include "gdkdisplay.h"
+#include "gdkdisplayprivate.h"
+
+#include "gdkdeviceprivate.h"
+#include "gdkevents.h"
#include "gdkwindowimpl.h"
#include "gdkinternals.h"
#include "gdkmarshalers.h"
#include "gdkscreen.h"
-#include "gdkalias.h"
-enum {
- CLOSED,
- LAST_SIGNAL
-};
+#include <glib.h>
-static void gdk_display_dispose (GObject *object);
-static void gdk_display_finalize (GObject *object);
-
-
-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_pointer (GdkDisplay *display,
- GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask);
-static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y);
-static guint signals[LAST_SIGNAL] = { 0 };
+/**
+ * SECTION:gdkdisplay
+ * @Short_description: Controls the keyboard/mouse pointer grabs and a set of <type>GdkScreen</type>s
+ * @Title: GdkDisplay
+ *
+ * #GdkDisplay objects purpose are two fold:
+ * <itemizedlist>
+ * <listitem><para>
+ * To grab/ungrab keyboard focus and mouse pointer
+ * </para></listitem>
+ * <listitem><para>
+ * To manage and provide information about the #GdkScreen(s)
+ * available for this #GdkDisplay
+ * </para></listitem>
+ * </itemizedlist>
+ *
+ * #GdkDisplay objects are the GDK representation of the X Display which can be
+ * described as <emphasis>a workstation consisting of a keyboard a pointing
+ * device (such as a mouse) and one or more screens</emphasis>.
+ * 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.
+ */
-static char *gdk_sm_client_id;
-static const GdkDisplayPointerHooks default_pointer_hooks = {
- _gdk_windowing_get_pointer,
- gdk_window_real_window_get_pointer,
- gdk_display_real_get_window_at_pointer
+enum {
+ OPENED,
+ CLOSED,
+ LAST_SIGNAL
};
-static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
- singlehead_get_pointer,
- singlehead_window_get_pointer,
- singlehead_window_at_pointer
-};
+static void gdk_display_dispose (GObject *object);
+static void gdk_display_finalize (GObject *object);
-static const GdkPointerHooks singlehead_default_pointer_hooks = {
- singlehead_default_window_get_pointer,
- singlehead_default_window_at_pointer
-};
-static const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
+static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
+
+static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
gdk_display_class_init (GdkDisplayClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (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
+ *
+ * The ::opened signal is emitted when the connection to the windowing
+ * system for @display is opened.
+ */
+ signals[OPENED] =
+ g_signal_new (g_intern_static_string ("opened"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
/**
* GdkDisplay::closed:
* @display: the object on which the signal is emitted
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkDisplayClass, closed),
NULL, NULL,
- gdk_marshal_VOID__BOOLEAN,
+ _gdk_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
1,
G_TYPE_BOOLEAN);
}
static void
-gdk_display_init (GdkDisplay *display)
+free_pointer_info (GdkPointerWindowInfo *info)
+{
+ g_object_unref (info->toplevel_under_pointer);
+ g_slice_free (GdkPointerWindowInfo, info);
+}
+
+static void
+free_device_grab (GdkDeviceGrabInfo *info)
+{
+ g_object_unref (info->window);
+ g_object_unref (info->native_window);
+ g_free (info);
+}
+
+static gboolean
+free_device_grabs_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList *list = value;
+
+ g_list_foreach (list, (GFunc) free_device_grab, NULL);
+ g_list_free (list);
+
+ return TRUE;
+}
+
+static void
+device_removed_cb (GdkDeviceManager *device_manager,
+ GdkDevice *device,
+ GdkDisplay *display)
+{
+ g_hash_table_remove (display->multiple_click_info, device);
+ g_hash_table_remove (display->device_grabs, device);
+ g_hash_table_remove (display->pointers_info, device);
+
+ /* FIXME: change core pointer and remove from device list */
+}
+
+static void
+gdk_display_opened (GdkDisplay *display)
{
- _gdk_displays = g_slist_prepend (_gdk_displays, display);
+ GdkDeviceManager *device_manager;
- display->button_click_time[0] = display->button_click_time[1] = 0;
- display->button_window[0] = display->button_window[1] = NULL;
- display->button_number[0] = display->button_number[1] = -1;
- display->button_x[0] = display->button_x[1] = 0;
- display->button_y[0] = display->button_y[1] = 0;
+ device_manager = gdk_display_get_device_manager (display);
+ g_signal_connect (device_manager, "device-removed",
+ G_CALLBACK (device_removed_cb), display);
+}
+
+static void
+gdk_display_init (GdkDisplay *display)
+{
display->double_click_time = 250;
display->double_click_distance = 5;
- display->pointer_hooks = &default_pointer_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);
+
+ display->pointers_info = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) free_pointer_info);
+
+ display->multiple_click_info = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) g_free);
+
+ g_signal_connect (display, "opened",
+ G_CALLBACK (gdk_display_opened), NULL);
}
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));
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 (device_manager)
{
- 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);
+ /* this is to make it drop devices which may require using the X
+ * display and therefore can't be cleaned up in finalize.
+ * It will also disconnect device_removed_cb
+ */
+ g_object_run_dispose (G_OBJECT (display->device_manager));
}
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
static void
gdk_display_finalize (GObject *object)
{
+ GdkDisplay *display = GDK_DISPLAY (object);
+
+ g_hash_table_foreach_remove (display->device_grabs,
+ free_device_grabs_foreach,
+ NULL);
+ g_hash_table_destroy (display->device_grabs);
+
+ g_hash_table_destroy (display->pointers_info);
+ g_hash_table_destroy (display->multiple_click_info);
+
+ if (display->device_manager)
+ g_object_unref (display->device_manager);
+
G_OBJECT_CLASS (gdk_display_parent_class)->finalize (object);
}
}
}
+/**
+ * gdk_display_is_closed:
+ * @display: a #GdkDisplay
+ *
+ * Finds out if the display has been closed.
+ *
+ * Returns: %TRUE if the display is closed.
+ *
+ * Since: 2.22
+ */
+gboolean
+gdk_display_is_closed (GdkDisplay *display)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return display->closed;
+}
+
/**
* gdk_display_get_event:
* @display: a #GdkDisplay
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);
}
g_main_context_wakeup (NULL);
}
+/**
+ * gdk_display_pointer_ungrab:
+ * @display: a #GdkDisplay.
+ * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
+ *
+ * Release any pointer grab.
+ *
+ * Since: 2.2
+ *
+ * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
+ * instead.
+ */
+void
+gdk_display_pointer_ungrab (GdkDisplay *display,
+ guint32 time_)
+{
+ GdkDeviceManager *device_manager;
+ GList *devices, *dev;
+ GdkDevice *device;
+
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ device_manager = gdk_display_get_device_manager (display);
+ devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+ /* FIXME: Should this be generic to all backends? */
+ /* FIXME: What happens with extended devices? */
+ for (dev = devices; dev; dev = dev->next)
+ {
+ device = dev->data;
+
+ if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
+ continue;
+
+ gdk_device_ungrab (device, time_);
+ }
+
+ g_list_free (devices);
+}
+
/**
* gdk_pointer_ungrab:
* @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
*
* Ungrabs the pointer on the default display, if it is grabbed by this
* application.
+ *
+ * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
+ * instead.
**/
void
gdk_pointer_ungrab (guint32 time)
*
* Note that this does not take the inmplicit pointer grab on button
* presses into account.
-
- * Return value: %TRUE if the pointer is currently grabbed by this application.*
+ *
+ * Return value: %TRUE if the pointer is currently grabbed by this application.
+ *
+ * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
**/
gboolean
gdk_pointer_is_grabbed (void)
return gdk_display_pointer_is_grabbed (gdk_display_get_default ());
}
+/**
+ * gdk_display_keyboard_ungrab:
+ * @display: a #GdkDisplay.
+ * @time_: a timestap (e.g #GDK_CURRENT_TIME).
+ *
+ * Release any keyboard grab
+ *
+ * Since: 2.2
+ *
+ * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
+ * instead.
+ */
+void
+gdk_display_keyboard_ungrab (GdkDisplay *display,
+ guint32 time)
+{
+ GdkDeviceManager *device_manager;
+ GList *devices, *dev;
+ GdkDevice *device;
+
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ device_manager = gdk_display_get_device_manager (display);
+ devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+ /* FIXME: Should this be generic to all backends? */
+ /* FIXME: What happens with extended devices? */
+ for (dev = devices; dev; dev = dev->next)
+ {
+ device = dev->data;
+
+ if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
+ continue;
+
+ gdk_device_ungrab (device, time);
+ }
+
+ g_list_free (devices);
+}
+
/**
* gdk_keyboard_ungrab:
* @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
*
* Ungrabs the keyboard on the default display, if it is grabbed by this
* application.
+ *
+ * Deprecated: 3.0: Use gdk_device_ungrab(), together with gdk_device_grab()
+ * instead.
**/
void
gdk_keyboard_ungrab (guint32 time)
}
/**
- * 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.
+ * gdk_flush:
*
- * 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.
- **/
+ * Flushes the output buffers of all display connections and waits
+ * until all requests have been processed.
+ * This is rarely needed by applications.
+ */
void
-gdk_event_send_clientmessage_toall (GdkEvent *event)
+gdk_flush (void)
{
- g_return_if_fail (event != NULL);
+ GSList *list, *l;
- gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
-}
+ list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+ for (l = list; l; l = l->next)
+ {
+ GdkDisplay *display = l->data;
-/**
- * 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.
- **/
-GdkDevice *
-gdk_device_get_core_pointer (void)
-{
- return gdk_display_get_core_pointer (gdk_display_get_default ());
-}
+ GDK_DISPLAY_GET_CLASS (display)->sync (display);
+ }
-/**
- * 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.
- *
- * Since: 2.2
- **/
-GdkDevice *
-gdk_display_get_core_pointer (GdkDisplay *display)
-{
- return display->core_pointer;
+ g_slist_free (list);
}
-/**
- * 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 <literal>SM_CLIENT_ID</literal> 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 <literal>WM_CLIENT_LEADER</literal> property.
- * (Both documents are part of the X Window System distribution.)
- **/
void
-gdk_set_sm_client_id (const gchar* sm_client_id)
+_gdk_display_enable_motion_hints (GdkDisplay *display,
+ GdkDevice *device)
{
- GSList *displays, *tmp_list;
-
- g_free (gdk_sm_client_id);
- gdk_sm_client_id = g_strdup (sm_client_id);
+ gulong *device_serial, serial;
- 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);
+ device_serial = g_hash_table_lookup (display->motion_hint_info, device);
- g_slist_free (displays);
-}
+ if (!device_serial)
+ {
+ device_serial = g_new0 (gulong, 1);
+ *device_serial = G_MAXULONG;
+ g_hash_table_insert (display->motion_hint_info, device, device_serial);
+ }
-/**
- * _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;
+ if (*device_serial != 0)
+ {
+ 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
+ anyway. */
+ if (serial > 0)
+ serial--;
+ if (serial < *device_serial)
+ *device_serial = serial;
+ }
}
/**
* gdk_display_get_pointer:
* @display: a #GdkDisplay
- * @screen: location to store the screen that the
+ * @screen: (out) (allow-none): location to store the screen that the
* cursor is on, or %NULL.
- * @x: location to store root window X coordinate of pointer, or %NULL.
- * @y: location to store root window Y coordinate of pointer, or %NULL.
- * @mask: location to store current modifier mask, 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.
+ * @mask: (out) (allow-none): location to store current modifier mask, or %NULL
+ *
* Gets the current location of the pointer and the current modifier
* mask for a given display.
*
* Since: 2.2
+ *
+ * Deprecated: 3.0: Use gdk_device_get_position() instead.
**/
void
gdk_display_get_pointer (GdkDisplay *display,
gint *y,
GdkModifierType *mask)
{
- GdkScreen *tmp_screen;
+ GdkScreen *default_screen;
+ GdkWindow *root;
gint tmp_x, tmp_y;
GdkModifierType tmp_mask;
-
+
g_return_if_fail (GDK_IS_DISPLAY (display));
- display->pointer_hooks->get_pointer (display, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
+ if (gdk_display_is_closed (display))
+ return;
+
+ default_screen = gdk_display_get_default_screen (display);
+
+ /* We call _gdk_device_query_state() here manually instead of
+ * gdk_device_get_position() because we care about the modifier mask */
+
+ _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 = tmp_screen;
+ *screen = gdk_window_get_screen (root);
if (x)
*x = tmp_x;
if (y)
*mask = tmp_mask;
}
-static GdkWindow *
-gdk_display_real_get_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y)
-{
- GdkWindow *window;
- gint x, y;
-
- window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
-
- /* 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);
- }
-
- *win_x = x;
- *win_y = y;
-
- return window;
-}
-
-static GdkWindow *
-gdk_window_real_window_get_pointer (GdkDisplay *display,
- GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- GdkWindowObject *private;
- GdkWindow *pointer_window;
- gint tmpx, tmpy;
- GdkModifierType tmp_mask;
-
- private = (GdkWindowObject *) window;
-
- pointer_window = _gdk_windowing_window_get_pointer (display,
- window,
- &tmpx, &tmpy,
- mask);
- /* We got the coords on the impl, conver to the window */
- tmpx -= private->abs_x;
- tmpy -= private->abs_y;
-
- if (x)
- *x = tmpx;
- if (y)
- *y = tmpy;
-
- /* We need to recalculate the true child window with the pointer in it
- due to possible client side child windows */
- if (pointer_window != NULL)
- {
- /* First get the pointer coords relative to pointer_window */
- _gdk_windowing_window_get_pointer (display,
- pointer_window,
- &tmpx, &tmpy,
- &tmp_mask);
- /* Then convert that to a client side window */
- pointer_window = _gdk_window_find_descendant_at (pointer_window,
- tmpx, tmpy,
- NULL, NULL);
- }
-
- return pointer_window;
-}
-
/**
* gdk_display_get_window_at_pointer:
* @display: a #GdkDisplay
- * @win_x: return location for x coordinate of the pointer location relative
+ * @win_x: (out) (allow-none): return location for x coordinate of the pointer location relative
* to the window origin, or %NULL
- * @win_y: return location for y coordinate of the pointer location relative
+ * @win_y: (out) (allow-none): return location for y coordinate of the pointer location relative
& to the window origin, or %NULL
- *
+ *
* Obtains the window underneath the mouse pointer, returning the location
- * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
+ * of the pointer in that window in @win_x, @win_y for @screen. Returns %NULL
* if the window under the mouse pointer is not known to GDK (for example,
* belongs to another application).
- *
- * Returns: the window under the mouse pointer, or %NULL
+ *
+ * Returns: (transfer none): the window under the mouse pointer, or %NULL
*
* Since: 2.2
+ *
+ * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead.
**/
GdkWindow *
gdk_display_get_window_at_pointer (GdkDisplay *display,
gint *win_x,
gint *win_y)
{
- gint tmp_x, tmp_y;
- GdkWindow *window;
-
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
- window = display->pointer_hooks->window_at_pointer (display, &tmp_x, &tmp_y);
-
- if (win_x)
- *win_x = tmp_x;
- if (win_y)
- *win_y = tmp_y;
-
- return window;
+ return gdk_device_get_window_at_position (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
- **/
-GdkDisplayPointerHooks *
-gdk_display_set_pointer_hooks (GdkDisplay *display,
- const GdkDisplayPointerHooks *new_hooks)
+static void
+generate_grab_broken_event (GdkWindow *window,
+ GdkDevice *device,
+ gboolean implicit,
+ GdkWindow *grab_window)
{
- const GdkDisplayPointerHooks *result;
-
- g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
- result = display->pointer_hooks;
-
- if (new_hooks)
- display->pointer_hooks = new_hooks;
- else
- display->pointer_hooks = &default_pointer_hooks;
+ g_return_if_fail (window != NULL);
- return (GdkDisplayPointerHooks *)result;
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkEvent *event;
+
+ event = gdk_event_new (GDK_GRAB_BROKEN);
+ event->grab_broken.window = g_object_ref (window);
+ event->grab_broken.send_event = FALSE;
+ event->grab_broken.implicit = implicit;
+ event->grab_broken.grab_window = grab_window;
+ gdk_event_set_device (event, device);
+ event->grab_broken.keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) ? TRUE : FALSE;
+
+ gdk_event_put (event);
+ gdk_event_free (event);
+ }
}
-static void
-singlehead_get_pointer (GdkDisplay *display,
- GdkScreen **screen,
- gint *x,
- gint *y,
- GdkModifierType *mask)
+GdkDeviceGrabInfo *
+_gdk_display_get_last_device_grab (GdkDisplay *display,
+ GdkDevice *device)
{
- GdkScreen *default_screen = gdk_display_get_default_screen (display);
- GdkWindow *root_window = gdk_screen_get_root_window (default_screen);
+ GList *l;
- *screen = default_screen;
+ l = g_hash_table_lookup (display->device_grabs, device);
- singlehead_current_pointer_hooks->get_pointer (root_window, x, y, mask);
-}
+ if (l)
+ {
+ l = g_list_last (l);
+ return l->data;
+ }
-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);
+ return NULL;
}
-static GdkWindow*
-singlehead_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y)
+GdkDeviceGrabInfo *
+_gdk_display_add_device_grab (GdkDisplay *display,
+ GdkDevice *device,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ GdkGrabOwnership grab_ownership,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ unsigned long serial_start,
+ guint32 time,
+ gboolean implicit)
{
- GdkScreen *default_screen = gdk_display_get_default_screen (display);
+ GdkDeviceGrabInfo *info, *other_info;
+ GList *grabs, *l;
+
+ info = g_new0 (GdkDeviceGrabInfo, 1);
+
+ info->window = g_object_ref (window);
+ info->native_window = g_object_ref (native_window);
+ info->serial_start = serial_start;
+ info->serial_end = G_MAXULONG;
+ info->owner_events = owner_events;
+ info->event_mask = event_mask;
+ info->time = time;
+ info->implicit = implicit;
+ info->ownership = grab_ownership;
+
+ grabs = g_hash_table_lookup (display->device_grabs, device);
+
+ /* Find the first grab that has a larger start time (if any) and insert
+ * before that. I.E we insert after already existing grabs with same
+ * start time */
+ for (l = grabs; l != NULL; l = l->next)
+ {
+ other_info = l->data;
- return singlehead_current_pointer_hooks->window_at_pointer (default_screen,
- win_x, win_y);
-}
+ if (info->serial_start < other_info->serial_start)
+ break;
+ }
-static GdkWindow*
-singlehead_default_window_get_pointer (GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
- window, x, y, mask);
-}
+ grabs = g_list_insert_before (grabs, l, info);
-static GdkWindow*
-singlehead_default_window_at_pointer (GdkScreen *screen,
- gint *win_x,
- gint *win_y)
-{
- return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
- win_x, win_y);
-}
+ /* Make sure the new grab end before next grab */
+ if (l)
+ {
+ other_info = l->data;
+ info->serial_end = other_info->serial_start;
+ }
-/**
- * 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
- **/
-GdkPointerHooks *
-gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
-{
- const GdkPointerHooks *result = singlehead_current_pointer_hooks;
+ /* Find any previous grab and update its end time */
+ l = g_list_find (grabs, info);
+ l = l->prev;
+ if (l)
+ {
+ other_info = l->data;
+ other_info->serial_end = serial_start;
+ }
- if (new_hooks)
- singlehead_current_pointer_hooks = new_hooks;
- else
- singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
+ g_hash_table_insert (display->device_grabs, device, grabs);
- gdk_display_set_pointer_hooks (gdk_display_get_default (),
- &singlehead_pointer_hooks);
-
- return (GdkPointerHooks *)result;
+ return info;
}
+/* _gdk_synthesize_crossing_events only works inside one toplevel.
+ This function splits things into two calls if needed, converting the
+ coordinates to the right toplevel */
static void
-generate_grab_broken_event (GdkWindow *window,
- gboolean keyboard,
- gboolean implicit,
- GdkWindow *grab_window)
+synthesize_crossing_events (GdkDisplay *display,
+ GdkDevice *device,
+ GdkDevice *source_device,
+ GdkWindow *src_window,
+ GdkWindow *dest_window,
+ GdkCrossingMode crossing_mode,
+ guint32 time,
+ gulong serial)
{
- g_return_if_fail (window != NULL);
+ GdkWindow *src_toplevel, *dest_toplevel;
+ GdkModifierType state;
+ int x, y;
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GdkEvent event;
- event.type = GDK_GRAB_BROKEN;
- event.grab_broken.window = window;
- event.grab_broken.send_event = 0;
- event.grab_broken.keyboard = keyboard;
- event.grab_broken.implicit = implicit;
- event.grab_broken.grab_window = grab_window;
- gdk_event_put (&event);
- }
-}
+ /* We use the native crossing events if all native */
+ if (_gdk_native_windows)
+ return;
+
+ if (src_window)
+ src_toplevel = gdk_window_get_toplevel (src_window);
+ else
+ src_toplevel = NULL;
+ if (dest_window)
+ dest_toplevel = gdk_window_get_toplevel (dest_window);
+ else
+ dest_toplevel = NULL;
-void
-_gdk_display_set_has_pointer_grab (GdkDisplay *display,
- GdkWindow *window,
- GdkWindow *native_window,
- gboolean owner_events,
- GdkEventMask event_mask,
- unsigned long serial,
- guint32 time,
- gboolean implicit)
-{
- GdkWindow *src_toplevel, *dest_toplevel, *src_window;
+ if (src_toplevel == NULL && dest_toplevel == NULL)
+ return;
- if (display->pointer_grab.window != NULL &&
- display->pointer_grab.window != window)
+ if (src_toplevel == NULL ||
+ src_toplevel == dest_toplevel)
{
- generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
- FALSE, display->pointer_grab.implicit,
- window);
+ /* Same toplevels */
+ gdk_window_get_pointer (dest_toplevel,
+ &x, &y, &state);
+ _gdk_synthesize_crossing_events (display,
+ src_window,
+ dest_window,
+ device, source_device,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
}
-
- /* We need to generate crossing events for the grab.
- * However, there are never any crossing events for implicit grabs
- * TODO: ... Actually, this could happen if the pointer window doesn't have button mask so a parent gets the event...
- */
- if (!implicit)
+ else if (dest_toplevel == NULL)
+ {
+ gdk_window_get_pointer (src_toplevel,
+ &x, &y, &state);
+ _gdk_synthesize_crossing_events (display,
+ src_window,
+ NULL,
+ device, source_device,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
+ }
+ else
{
- int x, y;
- GdkModifierType state;
+ /* Different toplevels */
+ gdk_window_get_pointer (src_toplevel,
+ &x, &y, &state);
+ _gdk_synthesize_crossing_events (display,
+ src_window,
+ NULL,
+ device, source_device,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
+ gdk_window_get_pointer (dest_toplevel,
+ &x, &y, &state);
+ _gdk_synthesize_crossing_events (display,
+ NULL,
+ dest_window,
+ device, source_device,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
+ }
+}
- /* We send GRAB crossing events from the window under the pointer to the
- grab window. Except if there is an old grab then we start from that */
- if (display->pointer_grab.window)
- src_window = display->pointer_grab.window;
- else
- src_window = display->pointer_info.window_under_pointer;
+static GdkWindow *
+get_current_toplevel (GdkDisplay *display,
+ GdkDevice *device,
+ int *x_out,
+ int *y_out,
+ GdkModifierType *state_out)
+{
+ GdkWindow *pointer_window;
+ int x, y;
+ GdkModifierType state;
- /* Unset any current grab to make sure we send the events */
- display->pointer_grab.window = NULL;
-
- if (src_window != window)
+ pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
+
+ if (pointer_window != NULL &&
+ (GDK_WINDOW_DESTROYED (pointer_window) ||
+ GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
+ GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
+ pointer_window = NULL;
+
+ *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,
+ gulong serial)
+{
+ GdkWindow *src_window, *pointer_window, *new_toplevel;
+ GdkPointerWindowInfo *info;
+ GList *old_grabs;
+ GdkModifierType state;
+ 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);
+ g_hash_table_steal (display->device_grabs, device);
+ info = _gdk_display_get_pointer_info (display, device);
+
+ if (grab)
+ {
+ /* New grab is in effect */
+
+ /* We need to generate crossing events for the grab.
+ * However, there are never any crossing events for implicit grabs
+ * TODO: ... Actually, this could happen if the pointer window
+ * doesn't have button mask so a parent gets the event...
+ */
+ if (!grab->implicit)
{
- /* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
- if (src_window)
- src_toplevel = gdk_window_get_toplevel (src_window);
+ /* We send GRAB crossing events from the window under the pointer to the
+ grab window. Except if there is an old grab then we start from that */
+ if (last_grab)
+ src_window = last_grab->window;
else
- src_toplevel = NULL;
- dest_toplevel = gdk_window_get_toplevel (window);
-
- if (src_toplevel == NULL ||
- src_toplevel == dest_toplevel)
+ src_window = info->window_under_pointer;
+
+ if (src_window != grab->window)
+ synthesize_crossing_events (display, device, source_device,
+ src_window, grab->window,
+ GDK_CROSSING_GRAB, time, serial);
+
+ /* !owner_event Grabbing a window that we're not inside, current status is
+ now NULL (i.e. outside grabbed window) */
+ if (!grab->owner_events && info->window_under_pointer != grab->window)
+ _gdk_display_set_window_under_pointer (display, device, NULL);
+ }
+
+ grab->activated = TRUE;
+ }
+
+ if (last_grab)
+ {
+ new_toplevel = NULL;
+
+ if (grab == NULL /* ungrab */ ||
+ (!last_grab->owner_events && grab->owner_events) /* switched to owner_events */ )
+ {
+ /* We force check what window we're in, and update the toplevel_under_pointer info,
+ * as that won't get told of this change with toplevel enter events.
+ */
+ if (info->toplevel_under_pointer)
+ g_object_unref (info->toplevel_under_pointer);
+ info->toplevel_under_pointer = NULL;
+
+ /* 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)
{
- _gdk_windowing_window_get_pointer (display,
- dest_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- src_window,
- window,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
+ /* w is now toplevel and x,y in toplevel coords */
+ info->toplevel_under_pointer = g_object_ref (new_toplevel);
+ info->toplevel_x = x;
+ info->toplevel_y = y;
+ info->state = state;
}
- else
+ }
+
+ if (grab == NULL) /* Ungrabbed, send events */
+ {
+ pointer_window = NULL;
+ if (new_toplevel)
{
- _gdk_windowing_window_get_pointer (display,
- src_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- src_window,
- NULL,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
- _gdk_windowing_window_get_pointer (display,
- dest_toplevel,
- &x, &y, &state);
- _gdk_syntesize_crossing_events (display,
- NULL,
- window,
- GDK_CROSSING_GRAB,
- x, y, state,
- time,
- NULL);
+ /* Find (possibly virtual) child window */
+ pointer_window =
+ _gdk_window_find_descendant_at (new_toplevel,
+ x, y,
+ NULL, NULL);
}
- }
- /* !owner_event Grabbing a window that we're not inside, current status is
- now NULL (i.e. outside grabbed window) */
- if (!owner_events && display->pointer_info.window_under_pointer != window)
- _gdk_display_set_window_under_pointer (display, NULL);
+ if (pointer_window != last_grab->window)
+ synthesize_crossing_events (display, device, source_device,
+ last_grab->window, pointer_window,
+ GDK_CROSSING_UNGRAB, time, serial);
+
+ /* We're now ungrabbed, update the window_under_pointer */
+ _gdk_display_set_window_under_pointer (display, device, pointer_window);
+ }
}
- display->pointer_grab.window = window;
- display->pointer_grab.native_window = native_window;
- display->pointer_grab.serial = serial;
- display->pointer_grab.owner_events = owner_events;
- display->pointer_grab.event_mask = event_mask;
- display->pointer_grab.time = time;
- display->pointer_grab.implicit = implicit;
- display->pointer_grab.converted_implicit = FALSE;
+ g_hash_table_insert (display->device_grabs, device, old_grabs);
}
void
-_gdk_display_unset_has_pointer_grab (GdkDisplay *display,
- gboolean implicit,
- gboolean do_grab_one_pointer_release_event,
- guint32 time)
-{
- GdkWindow *pointer_window, *src_toplevel, *dest_toplevel;
- GdkWindow *old_grab_window;
- GdkWindow *old_native_grab_window;
- int x, y;
- GdkModifierType state;
- GdkWindowObject *w;
+_gdk_display_device_grab_update (GdkDisplay *display,
+ GdkDevice *device,
+ GdkDevice *source_device,
+ gulong current_serial)
+{
+ GdkDeviceGrabInfo *current_grab, *next_grab;
+ GList *grabs;
+ guint32 time;
- old_grab_window = display->pointer_grab.window;
- old_native_grab_window = display->pointer_grab.native_window;
+ time = display->last_event_time;
+ grabs = g_hash_table_lookup (display->device_grabs, device);
- if (old_grab_window == NULL)
- return; /* This happens in the gdk_window_hide case */
+ while (grabs != NULL)
+ {
+ current_grab = grabs->data;
- if (do_grab_one_pointer_release_event)
- display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
+ if (current_grab->serial_start > current_serial)
+ return; /* Hasn't started yet */
- /* Set first so crossing events get sent */
- display->pointer_grab.window = NULL;
-
- pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
-
- if (pointer_window != NULL &&
- (GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
- GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
- pointer_window = NULL;
+ if (current_grab->serial_end > current_serial)
+ {
+ /* This one hasn't ended yet.
+ its the currently active one or scheduled to be active */
- /* We force checked what window we're in, so we need to
- * update the toplevel_under_pointer info, as that won't get told of
- * this change.
- */
- if (display->pointer_info.toplevel_under_pointer)
- g_object_unref (display->pointer_info.toplevel_under_pointer);
- display->pointer_info.toplevel_under_pointer = NULL;
-
- if (pointer_window)
- {
- /* Convert to toplevel */
- w = (GdkWindowObject *)pointer_window;
- while (w->parent->window_type != GDK_WINDOW_ROOT)
+ if (!current_grab->activated)
+ {
+ if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
+ switch_to_pointer_grab (display, device, source_device, current_grab, NULL, time, current_serial);
+ }
+
+ break;
+ }
+
+ next_grab = NULL;
+ if (grabs->next)
{
- x += w->x;
- y += w->y;
- w = w->parent;
+ /* This is the next active grab */
+ next_grab = grabs->next->data;
+
+ if (next_grab->serial_start > current_serial)
+ next_grab = NULL; /* Actually its not yet active */
}
- /* w is now toplevel and x,y in toplevel coords */
+ if ((next_grab == NULL && current_grab->implicit_ungrab) ||
+ (next_grab != NULL && current_grab->window != next_grab->window))
+ generate_grab_broken_event (GDK_WINDOW (current_grab->window),
+ device,
+ current_grab->implicit,
+ next_grab? next_grab->window : NULL);
- display->pointer_info.toplevel_under_pointer = g_object_ref (w);
-
- /* Find child window */
- pointer_window =
- _gdk_window_find_descendant_at ((GdkWindow *)w,
- x, y,
- NULL, NULL);
+ /* Remove old grab */
+ grabs = g_list_delete_link (grabs, grabs);
+ g_hash_table_insert (display->device_grabs, device, grabs);
+
+ if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
+ switch_to_pointer_grab (display, device, source_device,
+ next_grab, current_grab,
+ time, current_serial);
+
+ free_device_grab (current_grab);
}
-
-
- if (pointer_window == NULL)
+}
+
+static GList *
+grab_list_find (GList *grabs,
+ gulong serial)
+{
+ GdkDeviceGrabInfo *grab;
+
+ while (grabs)
{
- _gdk_syntesize_crossing_events (display,
- old_grab_window,
- NULL,
- GDK_CROSSING_UNGRAB,
- x, y, state,
- time,
- NULL);
+ grab = grabs->data;
+
+ if (serial >= grab->serial_start && serial < grab->serial_end)
+ return grabs;
+
+ grabs = grabs->next;
}
- else
+
+ return NULL;
+}
+
+static GList *
+find_device_grab (GdkDisplay *display,
+ GdkDevice *device,
+ gulong serial)
+{
+ GList *l;
+
+ l = g_hash_table_lookup (display->device_grabs, device);
+ return grab_list_find (l, serial);
+}
+
+GdkDeviceGrabInfo *
+_gdk_display_has_device_grab (GdkDisplay *display,
+ GdkDevice *device,
+ gulong serial)
+{
+ GList *l;
+
+ l = find_device_grab (display, device, serial);
+ if (l)
+ return l->data;
+
+ return NULL;
+}
+
+/* Returns true if last grab was ended
+ * If if_child is non-NULL, end the grab only if the grabbed
+ * window is the same as if_child or a descendant of it */
+gboolean
+_gdk_display_end_device_grab (GdkDisplay *display,
+ GdkDevice *device,
+ gulong serial,
+ GdkWindow *if_child,
+ gboolean implicit)
+{
+ GdkDeviceGrabInfo *grab;
+ GList *l;
+
+ l = find_device_grab (display, device, serial);
+
+ if (l == NULL)
+ return FALSE;
+
+ grab = l->data;
+ if (grab &&
+ (if_child == NULL ||
+ _gdk_window_event_parent_of (if_child, grab->window)))
{
- if (pointer_window != old_grab_window)
- {
- /* _gdk_syntesize_crossing_events only works inside one toplevel, split into two calls if needed */
- src_toplevel = gdk_window_get_toplevel (old_grab_window);
- dest_toplevel = gdk_window_get_toplevel (pointer_window);
+ grab->serial_end = serial;
+ grab->implicit_ungrab = implicit;
+ return l->next == NULL;
+ }
+
+ return FALSE;
+}
- if (src_toplevel == dest_toplevel)
- {
- _gdk_syntesize_crossing_events (display,
- display->pointer_info.window_under_pointer,
- pointer_window,
- GDK_CROSSING_UNGRAB,
- x, y, state,
- time,
- NULL);
- }
- else
- {
- /* TODO: We're reporting the wrong coords here. They are in pointer_window toplevel coords */
- _gdk_syntesize_crossing_events (display,
- display->pointer_info.window_under_pointer,
- NULL,
- GDK_CROSSING_UNGRAB,
- x, y, state,
- time,
- NULL);
- _gdk_syntesize_crossing_events (display,
- NULL,
- pointer_window,
- GDK_CROSSING_UNGRAB,
- x, y, state,
- time,
- NULL);
- }
- }
+/* Returns TRUE if device events are not blocked by any grab */
+gboolean
+_gdk_display_check_grab_ownership (GdkDisplay *display,
+ GdkDevice *device,
+ gulong serial)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ GdkGrabOwnership higher_ownership, device_ownership;
+ gboolean device_is_keyboard;
+
+ g_hash_table_iter_init (&iter, display->device_grabs);
+ higher_ownership = device_ownership = GDK_OWNERSHIP_NONE;
+ device_is_keyboard = (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GdkDeviceGrabInfo *grab;
+ GdkDevice *dev;
+ GList *grabs;
+
+ dev = key;
+ grabs = value;
+ grabs = grab_list_find (grabs, serial);
+
+ if (!grabs)
+ continue;
+
+ /* Discard device if it's not of the same type */
+ 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;
+
+ if (dev == device)
+ device_ownership = grab->ownership;
+ else
+ {
+ if (grab->ownership > higher_ownership)
+ higher_ownership = grab->ownership;
+ }
}
- /* We're now ungrabbed, update the window_under_pointer */
- _gdk_display_set_window_under_pointer (display, pointer_window);
-
- if (implicit)
- generate_grab_broken_event (old_grab_window,
- FALSE, implicit,
- NULL);
+ if (higher_ownership > device_ownership)
+ {
+ /* There's a higher priority ownership
+ * going on for other device(s)
+ */
+ return FALSE;
+ }
+
+ return TRUE;
}
-void
-_gdk_display_set_has_keyboard_grab (GdkDisplay *display,
- GdkWindow *window,
- GdkWindow *native_window,
- gboolean owner_events,
- unsigned long serial,
- guint32 time)
-{
- if (display->keyboard_grab.window != NULL &&
- display->keyboard_grab.window != window)
- generate_grab_broken_event (display->keyboard_grab.window,
- TRUE, FALSE, window);
-
- display->keyboard_grab.window = window;
- display->keyboard_grab.native_window = native_window;
- display->keyboard_grab.owner_events = owner_events;
- display->keyboard_grab.serial = serial;
- display->keyboard_grab.time = time;
+GdkPointerWindowInfo *
+_gdk_display_get_pointer_info (GdkDisplay *display,
+ GdkDevice *device)
+{
+ GdkPointerWindowInfo *info;
+
+ if (G_UNLIKELY (!device))
+ return NULL;
+
+ info = g_hash_table_lookup (display->pointers_info, device);
+
+ if (G_UNLIKELY (!info))
+ {
+ info = g_slice_new0 (GdkPointerWindowInfo);
+ g_hash_table_insert (display->pointers_info, device, info);
+ }
+
+ return info;
}
void
-_gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
- gboolean implicit)
+_gdk_display_pointer_info_foreach (GdkDisplay *display,
+ GdkDisplayPointerInfoForeach func,
+ gpointer user_data)
{
- if (implicit)
- generate_grab_broken_event (display->keyboard_grab.window,
- TRUE, FALSE, NULL);
- display->keyboard_grab.window = NULL;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, display->pointers_info);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GdkPointerWindowInfo *info = value;
+ GdkDevice *device = key;
+
+ (func) (display, device, info, user_data);
+ }
}
/**
- * gdk_keyboard_grab_info_libgtk_only:
+ * gdk_device_grab_info_libgtk_only:
* @display: the display for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- * the @owner_events flag to gdk_keyboard_grab() was %TRUE.
- *
+ * @device: device to get the grab information from
+ * @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.
+ *
* Determines information about the current keyboard grab.
* This is not public API and must not be used by applications.
- *
+ *
* Return value: %TRUE if this application currently has the
* keyboard grabbed.
**/
gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
+gdk_device_grab_info_libgtk_only (GdkDisplay *display,
+ GdkDevice *device,
+ GdkWindow **grab_window,
+ gboolean *owner_events)
{
+ GdkDeviceGrabInfo *info;
+
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
- if (display->keyboard_grab.window)
+ info = _gdk_display_get_last_device_grab (display, device);
+
+ if (info)
{
if (grab_window)
- *grab_window = display->keyboard_grab.window;
+ *grab_window = info->window;
if (owner_events)
- *owner_events = display->keyboard_grab.owner_events;
+ *owner_events = info->owner_events;
return TRUE;
}
}
/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- * the @owner_events flag to gdk_pointer_grab() was %TRUE.
- *
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- *
- * Return value: %TRUE if this application currently has the
- * pointer grabbed.
- **/
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ *
+ * Deprecated: 3.0: Use gdk_display_device_is_grabbed() instead.
+ */
gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
{
- g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+ GdkDeviceManager *device_manager;
+ GList *devices, *dev;
+ GdkDevice *device;
+
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
- if (display->pointer_grab.window)
+ device_manager = gdk_display_get_device_manager (display);
+ devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
+
+ for (dev = devices; dev; dev = dev->next)
{
- if (grab_window)
- *grab_window = (GdkWindow *)display->pointer_grab.window;
- if (owner_events)
- *owner_events = display->pointer_grab.owner_events;
+ device = dev->data;
- return TRUE;
+ if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
+ gdk_display_device_is_grabbed (display, device))
+ return TRUE;
}
- else
- return FALSE;
+
+ return FALSE;
}
+/**
+ * gdk_display_device_is_grabbed:
+ * @display: a #GdkDisplay
+ * @device: a #GdkDevice
+ *
+ * Returns %TRUE if there is an ongoing grab on @device for @display.
+ *
+ * Returns: %TRUE if there is a grab in effect for @device.
+ **/
+gboolean
+gdk_display_device_is_grabbed (GdkDisplay *display,
+ GdkDevice *device)
+{
+ GdkDeviceGrabInfo *info;
+
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+ g_return_val_if_fail (GDK_IS_DEVICE (device), TRUE);
+
+ /* What we're interested in is the steady state (ie last grab),
+ because we're interested e.g. if we grabbed so that we
+ can ungrab, even if our grab is not active just yet. */
+ info = _gdk_display_get_last_device_grab (display, device);
+
+ return (info && !info->implicit);
+}
/**
- * gdk_display_pointer_is_grabbed:
+ * gdk_display_get_device_manager:
+ * @display: a #GdkDisplay.
+ *
+ * Returns the #GdkDeviceManager associated to @display.
+ *
+ * Returns: (transfer none): A #GdkDeviceManager, or %NULL. This memory is
+ * owned by GDK and must not be freed or unreferenced.
+ *
+ * Since: 3.0
+ **/
+GdkDeviceManager *
+gdk_display_get_device_manager (GdkDisplay *display)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ return display->device_manager;
+}
+
+/**
+ * gdk_display_get_name:
* @display: a #GdkDisplay
*
- * Test if the pointer is grabbed.
+ * Gets the name of the display.
*
- * Returns: %TRUE if an active X pointer grab is in effect
+ * Returns: a string representing the display name. This string is owned
+ * by GDK and should not be modified or freed.
*
* Since: 2.2
*/
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
+G_CONST_RETURN gchar *
+gdk_display_get_name (GdkDisplay *display)
{
- g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-
- return (display->pointer_grab.window != NULL &&
- !display->pointer_grab.implicit);
+ 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);
}
-#define __GDK_DISPLAY_C__
-#include "gdkaliasdef.c"
+/**
+ * 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
+ * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
+ * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
+ *
+ * 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.
+ *
+* <example>
+ * <title>Trapping an X error</title>
+ * <programlisting>
+ * gdk_error_trap_push (<!-- -->);
+ *
+ * // ... Call the X function which may cause an error here ...
+ *
+ *
+ * if (gdk_error_trap_pop (<!-- -->))
+ * {
+ * // ... Handle the error here ...
+ * }
+ * </programlisting>
+ * </example>
+ */
+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);
+}