* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkscreen.h"
#include <glib.h>
-#include <math.h>
/**
* SECTION:gdkdisplay
- * @Short_description: Controls the keyboard/mouse pointer grabs and a set of <type>GdkScreen</type>s
+ * @Short_description: Controls a set of GdkScreens and their associated input devices
* @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>
+ * <listitem>
+ * To manage and provide information about input devices (pointers
+ * and keyboards)
+ * </listitem>
+ * <listitem>
+ * To manage and provide information about the available #GdkScreens
+ * </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.
+ * GdkDisplay objects are the GDK representation of an 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 instantiated by the application. It is also used to
+ * access the keyboard(s) and mouse pointer(s) of the display.
+ *
+ * Most of the input device handling has been factored out into
+ * the separate #GdkDeviceManager object. Every display has a
+ * device manager, which you can obtain using
+ * gdk_display_get_device_manager().
*/
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 void gdk_display_real_get_device_state (GdkDisplay *display,
- GdkDevice *device,
- GdkScreen **screen,
- gint *x,
- gint *y,
- GdkModifierType *mask);
+
static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
static guint signals[LAST_SIGNAL] = { 0 };
-static const GdkDisplayDeviceHooks default_device_hooks = {
- gdk_display_real_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 const GdkPointerHooks *singlehead_current_pointer_hooks = &singlehead_default_pointer_hooks;
-static const GdkDisplayPointerHooks *multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
-
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
static void
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:
static void
free_pointer_info (GdkPointerWindowInfo *info)
{
- g_object_unref (info->toplevel_under_pointer);
+ if (info->toplevel_under_pointer)
+ g_object_unref (info->toplevel_under_pointer);
g_slice_free (GdkPointerWindowInfo, info);
}
{
GList *list = value;
- g_list_foreach (list, (GFunc) free_device_grab, NULL);
- g_list_free (list);
+ g_list_free_full (list, (GDestroyNotify) free_device_grab);
return TRUE;
}
display->double_click_time = 250;
display->double_click_distance = 5;
- display->device_hooks = &default_device_hooks;
-
+ display->touch_implicit_grabs = g_array_new (FALSE, FALSE, sizeof (GdkTouchGrabInfo));
display->device_grabs = g_hash_table_new (NULL, NULL);
display->motion_hint_info = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_free);
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);
+ g_list_free_full (display->queued_events, (GDestroyNotify) gdk_event_free);
display->queued_events = NULL;
display->queued_tail = NULL;
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,
NULL);
g_hash_table_destroy (display->device_grabs);
+ g_array_free (display->touch_implicit_grabs, TRUE);
+
+ g_hash_table_destroy (display->motion_hint_info);
g_hash_table_destroy (display->pointers_info);
g_hash_table_destroy (display->multiple_click_info);
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+ if (display->event_pause_count > 0)
+ return NULL;
+
GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
+
return _gdk_event_unqueue (display);
}
g_list_free (devices);
}
-/**
- * gdk_pointer_ungrab:
- * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
- * timestamp is available.
- *
- * 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)
-{
- gdk_display_pointer_ungrab (gdk_display_get_default (), time);
-}
-
-/**
- * gdk_pointer_is_grabbed:
- *
- * Returns %TRUE if the pointer on the default display is currently
- * grabbed by this application.
- *
- * 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.
- *
- * 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.
g_list_free (devices);
}
-/**
- * gdk_keyboard_ungrab:
- * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no
- * timestamp is available.
- *
- * 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_display_keyboard_ungrab (gdk_display_get_default (), time);
-}
-
/**
* gdk_beep:
*
g_slist_free (list);
}
-/**
- * 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);
-}
-
void
_gdk_display_enable_motion_hints (GdkDisplay *display,
GdkDevice *device)
}
}
-/**
- * gdk_display_get_device_state:
- * @display: a #GdkDisplay.
- * @device: pointer device to query status about.
- * @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
- * the @device is on, or %NULL.
- * @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
- * @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
- * @mask: (out) (allow-none): 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));
- g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
-
- 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: pointer #GdkDevice to query info to.
- * @win_x: (out) (allow-none): return location for the X coordinate of the device location,
- * relative to the window origin, or %NULL.
- * @win_y: (out) (allow-none): 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: (transfer none): 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);
- g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, 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: (allow-none): 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: (transfer none): 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) (transfer 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.
*
* 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,
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_device_window_at_position (device, &x, &y, NULL, FALSE);
-
- /* This might need corrections, as the native window returned
- may contain client side children */
- if (window)
- {
- double xx, yy;
+ GdkScreen *default_screen;
+ GdkWindow *root;
+ gint tmp_x, tmp_y;
+ GdkModifierType tmp_mask;
- window = _gdk_window_find_descendant_at (window,
- x, y,
- &xx, &yy);
- x = floor (xx + 0.5);
- y = floor (yy + 0.5);
- }
+ g_return_if_fail (GDK_IS_DISPLAY (display));
- *win_x = x;
- *win_y = y;
+ if (gdk_display_is_closed (display))
+ return;
- return window;
-}
+ default_screen = gdk_display_get_default_screen (display);
-static GdkWindow *
-gdk_window_real_window_get_device_position (GdkDisplay *display,
- GdkDevice *device,
- GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- gint tmpx, tmpy;
- GdkModifierType tmp_mask;
- gboolean normal_child;
+ /* 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_CLASS (window->impl)->get_device_state (window,
- device,
- &tmpx, &tmpy,
- &tmp_mask);
- /* We got the coords on the impl, convert to the window */
- tmpx -= window->abs_x;
- tmpy -= window->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;
}
/**
*
* 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,
{
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
-gdk_display_real_get_device_state (GdkDisplay *display,
- GdkDevice *device,
- GdkScreen **screen,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- GdkScreen *default_screen;
- GdkWindow *root;
-
- if (gdk_display_is_closed (display))
- return;
-
- default_screen = gdk_display_get_default_screen (display);
-
- _gdk_device_query_state (device,
- gdk_screen_get_root_window (default_screen),
- &root, NULL,
- x, y,
- NULL, NULL,
- mask);
-
- *screen = gdk_window_get_screen (root);
-}
-
-static void
-multihead_default_get_pointer (GdkDisplay *display,
- GdkScreen **screen,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- gdk_display_real_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: (allow-none): 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: (transfer none): 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: (allow-none): 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
return info;
}
+static void
+_gdk_display_break_touch_grabs (GdkDisplay *display,
+ GdkDevice *device,
+ GdkWindow *new_grab_window)
+{
+ guint i;
+
+ for (i = 0; i < display->touch_implicit_grabs->len; i++)
+ {
+ GdkTouchGrabInfo *info;
+
+ info = &g_array_index (display->touch_implicit_grabs,
+ GdkTouchGrabInfo, i);
+
+ if (info->device == device && info->window != new_grab_window)
+ generate_grab_broken_event (GDK_WINDOW (info->window),
+ device, TRUE, new_grab_window);
+ }
+}
+
+void
+_gdk_display_add_touch_grab (GdkDisplay *display,
+ GdkDevice *device,
+ GdkEventSequence *sequence,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ GdkEventMask event_mask,
+ unsigned long serial,
+ guint32 time)
+{
+ GdkTouchGrabInfo info;
+
+ info.device = device;
+ info.sequence = sequence;
+ info.window = g_object_ref (window);
+ info.native_window = g_object_ref (native_window);
+ info.serial = serial;
+ info.event_mask = event_mask;
+ info.time = time;
+
+ g_array_append_val (display->touch_implicit_grabs, info);
+}
+
+gboolean
+_gdk_display_end_touch_grab (GdkDisplay *display,
+ GdkDevice *device,
+ GdkEventSequence *sequence)
+{
+ guint i;
+
+ for (i = 0; i < display->touch_implicit_grabs->len; i++)
+ {
+ GdkTouchGrabInfo *info;
+
+ info = &g_array_index (display->touch_implicit_grabs,
+ GdkTouchGrabInfo, i);
+
+ if (info->device == device && info->sequence == sequence)
+ {
+ g_array_remove_index_fast (display->touch_implicit_grabs, i);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/* _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 */
GdkModifierType state;
int x, y;
- /* 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 == dest_toplevel)
{
/* Same toplevels */
- gdk_window_get_pointer (dest_toplevel,
- &x, &y, &state);
+ gdk_window_get_device_position (dest_toplevel,
+ device,
+ &x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
dest_window,
}
else if (dest_toplevel == NULL)
{
- gdk_window_get_pointer (src_toplevel,
- &x, &y, &state);
+ gdk_window_get_device_position (src_toplevel,
+ device,
+ &x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
else
{
/* Different toplevels */
- gdk_window_get_pointer (src_toplevel,
- &x, &y, &state);
+ gdk_window_get_device_position (src_toplevel,
+ device,
+ &x, &y, &state);
_gdk_synthesize_crossing_events (display,
src_window,
NULL,
time,
NULL,
serial, FALSE);
- gdk_window_get_pointer (dest_toplevel,
- &x, &y, &state);
+ gdk_window_get_device_position (dest_toplevel,
+ device,
+ &x, &y, &state);
_gdk_synthesize_crossing_events (display,
NULL,
dest_window,
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);
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 */
if (grab == NULL) /* Ungrabbed, send events */
{
- pointer_window = NULL;
- if (new_toplevel)
- {
- /* Find (possibly virtual) child window */
- pointer_window =
- _gdk_window_find_descendant_at (new_toplevel,
- x, y,
- NULL, NULL);
- }
+ /* If the source device is a touch device, do not
+ * propagate any enter event yet, until one is
+ * synthesized when needed.
+ */
+ if (source_device &&
+ (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN))
+ info->need_touch_press_enter = TRUE;
+
+ pointer_window = NULL;
+
+ if (new_toplevel &&
+ !info->need_touch_press_enter)
+ {
+ /* Find (possibly virtual) child window */
+ pointer_window =
+ _gdk_window_find_descendant_at (new_toplevel,
+ x, y,
+ NULL, NULL);
+ }
- if (pointer_window != last_grab->window)
+ if (!info->need_touch_press_enter &&
+ pointer_window != last_grab->window)
synthesize_crossing_events (display, device, source_device,
last_grab->window, pointer_window,
GDK_CROSSING_UNGRAB, time, serial);
next_grab = NULL; /* Actually its not yet active */
}
+ if (next_grab)
+ _gdk_display_break_touch_grabs (display, device, next_grab->window);
+
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),
+ (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);
+ current_grab->implicit,
+ next_grab? next_grab->window : NULL);
/* Remove old grab */
grabs = g_list_delete_link (grabs, grabs);
return NULL;
}
+GdkTouchGrabInfo *
+_gdk_display_has_touch_grab (GdkDisplay *display,
+ GdkDevice *device,
+ GdkEventSequence *sequence,
+ gulong serial)
+{
+ guint i;
+
+ for (i = 0; i < display->touch_implicit_grabs->len; i++)
+ {
+ GdkTouchGrabInfo *info;
+
+ info = &g_array_index (display->touch_implicit_grabs,
+ GdkTouchGrabInfo, i);
+
+ if (info->device == device && info->sequence == sequence)
+ {
+ if (serial >= info->serial)
+ return info;
+ else
+ return NULL;
+ }
+ }
+
+ 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 */
{
GdkPointerWindowInfo *info;
+ if (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+ device = gdk_device_get_associated_device (device);
+
if (G_UNLIKELY (!device))
return NULL;
if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE &&
gdk_display_device_is_grabbed (display, device))
- return TRUE;
+ {
+ g_list_free (devices);
+ return TRUE;
+ }
}
+ g_list_free (devices);
+
return FALSE;
}
*
* Since: 2.2
*/
-G_CONST_RETURN gchar *
+const gchar *
gdk_display_get_name (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->get_name (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ return GDK_DISPLAY_GET_CLASS (display)->get_name (display);
}
gchar *
gint
gdk_display_get_n_screens (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->get_n_screens (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
+ return GDK_DISPLAY_GET_CLASS (display)->get_n_screens (display);
}
/**
gdk_display_get_screen (GdkDisplay *display,
gint screen_num)
{
- return GDK_DISPLAY_GET_CLASS(display)->get_screen (display, screen_num);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ return GDK_DISPLAY_GET_CLASS (display)->get_screen (display, screen_num);
}
/**
GdkScreen *
gdk_display_get_default_screen (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->get_default_screen (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ return GDK_DISPLAY_GET_CLASS (display)->get_default_screen (display);
}
/**
void
gdk_display_beep (GdkDisplay *display)
{
- GDK_DISPLAY_GET_CLASS(display)->beep (display);
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ GDK_DISPLAY_GET_CLASS (display)->beep (display);
}
/**
void
gdk_display_sync (GdkDisplay *display)
{
- GDK_DISPLAY_GET_CLASS(display)->sync (display);
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ GDK_DISPLAY_GET_CLASS (display)->sync (display);
}
/**
void
gdk_display_flush (GdkDisplay *display)
{
- GDK_DISPLAY_GET_CLASS(display)->flush (display);
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ GDK_DISPLAY_GET_CLASS (display)->flush (display);
}
/**
GdkWindow *
gdk_display_get_default_group (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->get_default_group (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ return GDK_DISPLAY_GET_CLASS (display)->get_default_group (display);
}
/**
gboolean
gdk_display_supports_selection_notification (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->supports_selection_notification (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->supports_selection_notification (display);
}
/**
GdkAtom selection)
{
- return GDK_DISPLAY_GET_CLASS(display)->request_selection_notification (display, selection);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->request_selection_notification (display, selection);
}
/**
- * gdk_display_supports_clipboard_persistence
+ * gdk_display_supports_clipboard_persistence:
* @display: a #GdkDisplay
*
* Returns whether the speicifed display supports clipboard
gboolean
gdk_display_supports_clipboard_persistence (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->supports_clipboard_persistence (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->supports_clipboard_persistence (display);
}
/**
- * gdk_display_store_clipboard
+ * gdk_display_store_clipboard:
* @display: a #GdkDisplay
* @clipboard_window: a #GdkWindow belonging to the clipboard owner
* @time_: a timestamp
- * @targets: an array of targets that should be saved, or %NULL
+ * @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
*
const GdkAtom *targets,
gint n_targets)
{
- GDK_DISPLAY_GET_CLASS(display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
+ GDK_DISPLAY_GET_CLASS (display)->store_clipboard (display, clipboard_window, time_, targets, n_targets);
}
/**
gboolean
gdk_display_supports_shapes (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->supports_shapes (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->supports_shapes (display);
}
/**
gboolean
gdk_display_supports_input_shapes (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->supports_input_shapes (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->supports_input_shapes (display);
}
/**
gboolean
gdk_display_supports_composite (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->supports_composite (display);
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ return GDK_DISPLAY_GET_CLASS (display)->supports_composite (display);
}
/**
GList *
gdk_display_list_devices (GdkDisplay *display)
{
- return GDK_DISPLAY_GET_CLASS(display)->list_devices (display);
-}
-
-/**
- * gdk_event_send_client_message_for_display:
- * @display: the #GdkDisplay for the window where the message is to be sent.
- * @event: the #GdkEvent to send, which should be a #GdkEventClient.
- * @winid: the window to send the client message to.
- *
- * On X11, sends an X ClientMessage event to a given window. On
- * Windows, sends a message registered with the name
- * GDK_WIN32_CLIENT_MESSAGE.
- *
- * This could be used for communicating between different
- * applications, though the amount of data is limited to 20 bytes on
- * X11, and to just four bytes on Windows.
- *
- * Returns: non-zero on success.
- *
- * Since: 2.2
- */
-gboolean
-gdk_event_send_client_message_for_display (GdkDisplay *display,
- GdkEvent *event,
- GdkNativeWindow winid)
-{
- return GDK_DISPLAY_GET_CLASS(display)->send_client_message (display, event, winid);
-}
-
-/**
- * gdk_display_add_client_message_filter:
- * @display: a #GdkDisplay for which this message filter applies
- * @message_type: the type of ClientMessage events to receive.
- * This will be checked against the @message_type field
- * of the XClientMessage event struct.
- * @func: the function to call to process the event.
- * @data: user data to pass to @func.
- *
- * Adds a filter to be called when X ClientMessage events are received.
- * See gdk_window_add_filter() if you are interested in filtering other
- * types of events.
- *
- * Since: 2.2
- **/
-void
-gdk_display_add_client_message_filter (GdkDisplay *display,
- GdkAtom message_type,
- GdkFilterFunc func,
- gpointer data)
-{
- GDK_DISPLAY_GET_CLASS(display)->add_client_message_filter (display, message_type, func, data);
-}
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-/**
- * gdk_add_client_message_filter:
- * @message_type: the type of ClientMessage events to receive. This will be
- * checked against the <structfield>message_type</structfield> field of the
- * XClientMessage event struct.
- * @func: the function to call to process the event.
- * @data: user data to pass to @func.
- *
- * Adds a filter to the default display to be called when X ClientMessage events
- * are received. See gdk_display_add_client_message_filter().
- **/
-void
-gdk_add_client_message_filter (GdkAtom message_type,
- GdkFilterFunc func,
- gpointer data)
-{
- gdk_display_add_client_message_filter (gdk_display_get_default (),
- message_type, func, data);
+ return GDK_DISPLAY_GET_CLASS (display)->list_devices (display);
}
static GdkAppLaunchContext *
{
GdkAppLaunchContext *ctx;
- ctx = gdk_app_launch_context_new ();
- gdk_app_launch_context_set_display (ctx, display);
+ ctx = g_object_new (GDK_TYPE_APP_LAUNCH_CONTEXT,
+ "display", display,
+ NULL);
return ctx;
}
* Returns a #GdkAppLaunchContext suitable for launching
* applications on the given display.
*
- * Returns: a new #GdkAppLaunchContext for @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);
-}
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-/**
- * gdk_drag_get_protocol_for_display:
- * @display: the #GdkDisplay where the destination window resides
- * @xid: the windowing system id of the destination window.
- * @protocol: location where the supported DND protocol is returned.
- *
- * Finds out the DND protocol supported by a window.
- *
- * Return value: the windowing system id of the window where the drop
- * should happen. This may be @xid or the id of a proxy window,
- * or zero if @xid does not support Drag and Drop.
- *
- * Since: 2.2
- */
-GdkNativeWindow
-gdk_drag_get_protocol_for_display (GdkDisplay *display,
- GdkNativeWindow xid,
- GdkDragProtocol *protocol)
-{
- return GDK_DISPLAY_GET_CLASS (display)->get_drag_protocol (display, xid, protocol, NULL);
+ return GDK_DISPLAY_GET_CLASS (display)->get_app_launch_context (display);
}
/**
*
* Opens a display.
*
- * Return value: (transfer none): a #GdkDisplay, or %NULL if the display
- * could not be opened.
+ * 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);
+ 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)
{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
return GDK_DISPLAY_GET_CLASS (display)->has_pending (display);
}
*
* Since: 2.8
*
- * Deprecated: 3.0: Use gdk_display_warp_device() instead.
+ * Deprecated: 3.0: Use gdk_device_warp() instead.
*/
void
gdk_display_warp_pointer (GdkDisplay *display,
GdkScreen *screen,
gint x,
gint y)
-{
- gdk_display_warp_device (display,
- display->core_pointer,
- screen,
- x, y);
-}
-
-/**
- * gdk_display_warp_device:
- * @display: a #GdkDisplay.
- * @device: a #GdkDevice.
- * @screen: the screen of @display to warp @device to.
- * @x: the X coordinate of the destination.
- * @y: the Y coordinate of the destination.
- *
- * Warps @device in @display to the point @x,@y on
- * the screen @screen, unless the device 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: 3.0
- **/
-void
-gdk_display_warp_device (GdkDisplay *display,
- GdkDevice *device,
- GdkScreen *screen,
- gint x,
- gint y)
{
g_return_if_fail (GDK_IS_DISPLAY (display));
- g_return_if_fail (GDK_IS_DEVICE (device));
- g_return_if_fail (GDK_IS_SCREEN (screen));
- g_return_if_fail (display == gdk_device_get_display (device));
- GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
+ gdk_device_warp (display->core_pointer,
+ screen,
+ x, y);
}
gulong
/**
* gdk_notify_startup_complete_with_id:
- * @startup_id: a startup-notification identifier, for which notification
- * process should be completed
+ * @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.
+ * 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.
+ * 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
*/
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)
{
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+
GDK_DISPLAY_GET_CLASS (display)->notify_startup_complete (display, startup_id);
}
+void
+_gdk_display_pause_events (GdkDisplay *display)
+{
+ display->event_pause_count++;
+}
+
+void
+_gdk_display_unpause_events (GdkDisplay *display)
+{
+ g_return_if_fail (display->event_pause_count > 0);
+
+ display->event_pause_count--;
+}
+
+void
+_gdk_display_flush_events (GdkDisplay *display)
+{
+ display->flushing_events = TRUE;
+
+ while (TRUE)
+ {
+ GdkEvent *event = _gdk_event_unqueue (display);
+ if (event == NULL)
+ break;
+
+ _gdk_event_emit (event);
+ gdk_event_free (event);
+ }
+
+ display->flushing_events = FALSE;
+}
+
void
_gdk_display_event_data_copy (GdkDisplay *display,
const 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)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+ 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);
+}