]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkdisplay.c
win32: Fix build
[~andy/gtk] / gdk / gdkdisplay.c
index 9a083e18b745b830a4df69150d6fa6e03790d4d9..79d162b2a9df6261ac18b4612e2b8904ab82646a 100644 (file)
  * 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 "gdkdisplay.h"
+#include "gdkdisplayprivate.h"
 
+#include "gdkdeviceprivate.h"
 #include "gdkevents.h"
 #include "gdkwindowimpl.h"
 #include "gdkinternals.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().
  */
 
 
@@ -69,105 +74,10 @@ enum {
 static void gdk_display_dispose     (GObject         *object);
 static void gdk_display_finalize    (GObject         *object);
 
-static void        multihead_get_device_state           (GdkDisplay       *display,
-                                                         GdkDevice        *device,
-                                                         GdkScreen       **screen,
-                                                         gint             *x,
-                                                         gint             *y,
-                                                         GdkModifierType  *mask);
-static GdkWindow * multihead_window_get_device_position (GdkDisplay       *display,
-                                                         GdkDevice        *device,
-                                                         GdkWindow        *window,
-                                                         gint             *x,
-                                                         gint             *y,
-                                                         GdkModifierType  *mask);
-static GdkWindow * multihead_window_at_device_position  (GdkDisplay       *display,
-                                                         GdkDevice        *device,
-                                                         gint             *win_x,
-                                                         gint             *win_y);
-
-static void        multihead_default_get_pointer        (GdkDisplay       *display,
-                                                         GdkScreen       **screen,
-                                                         gint             *x,
-                                                         gint             *y,
-                                                         GdkModifierType  *mask);
-static GdkWindow * multihead_default_window_get_pointer (GdkDisplay      *display,
-                                                         GdkWindow       *window,
-                                                         gint            *x,
-                                                         gint            *y,
-                                                         GdkModifierType *mask);
-static GdkWindow * multihead_default_window_at_pointer  (GdkDisplay      *display,
-                                                         gint            *win_x,
-                                                         gint            *win_y);
-
-
-static void       singlehead_get_pointer (GdkDisplay       *display,
-                                         GdkScreen       **screen,
-                                         gint             *x,
-                                         gint             *y,
-                                         GdkModifierType  *mask);
-static GdkWindow* singlehead_window_get_pointer (GdkDisplay       *display,
-                                                GdkWindow        *window,
-                                                gint             *x,
-                                                gint             *y,
-                                                GdkModifierType  *mask);
-static GdkWindow* singlehead_window_at_pointer  (GdkDisplay       *display,
-                                                gint             *win_x,
-                                                gint             *win_y);
-
-static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window,
-                                                        gint            *x,
-                                                        gint            *y,
-                                                        GdkModifierType *mask);
-static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
-                                                        gint            *win_x,
-                                                        gint            *win_y);
-static GdkWindow *gdk_window_real_window_get_device_position     (GdkDisplay       *display,
-                                                                  GdkDevice        *device,
-                                                                  GdkWindow        *window,
-                                                                  gint             *x,
-                                                                  gint             *y,
-                                                                  GdkModifierType  *mask);
-static GdkWindow *gdk_display_real_get_window_at_device_position (GdkDisplay       *display,
-                                                                  GdkDevice        *device,
-                                                                  gint             *win_x,
-                                                                  gint             *win_y);
 
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static char *gdk_sm_client_id;
-
-static const GdkDisplayDeviceHooks default_device_hooks = {
-  _gdk_windowing_get_device_state,
-  gdk_window_real_window_get_device_position,
-  gdk_display_real_get_window_at_device_position
-};
-
-static const GdkDisplayDeviceHooks multihead_pointer_hooks = {
-  multihead_get_device_state,
-  multihead_window_get_device_position,
-  multihead_window_at_device_position
-};
-
-static const GdkDisplayPointerHooks multihead_default_pointer_hooks = {
-  multihead_default_get_pointer,
-  multihead_default_window_get_pointer,
-  multihead_default_window_at_pointer
-};
+static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay *display);
 
-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;
+static guint signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
 
@@ -179,6 +89,9 @@ gdk_display_class_init (GdkDisplayClass *class)
   object_class->finalize = gdk_display_finalize;
   object_class->dispose = gdk_display_dispose;
 
+  class->get_app_launch_context = gdk_display_real_get_app_launch_context;
+  class->window_type = GDK_TYPE_WINDOW;
+
   /**
    * GdkDisplay::opened:
    * @display: the object on which the signal is emitted
@@ -219,7 +132,8 @@ gdk_display_class_init (GdkDisplayClass *class)
 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);
 }
 
@@ -238,8 +152,7 @@ free_device_grabs_foreach (gpointer key,
 {
   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;
 }
@@ -270,13 +183,10 @@ gdk_display_opened (GdkDisplay *display)
 static void
 gdk_display_init (GdkDisplay *display)
 {
-  _gdk_displays = g_slist_prepend (_gdk_displays, display);
-
   display->double_click_time = 250;
   display->double_click_distance = 5;
 
-  display->device_hooks = &default_device_hooks;
-
+  display->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);
@@ -294,28 +204,15 @@ gdk_display_init (GdkDisplay *display)
 static void
 gdk_display_dispose (GObject *object)
 {
-  GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
+  GdkDisplay *display = GDK_DISPLAY (object);
   GdkDeviceManager *device_manager;
 
-  device_manager = gdk_display_get_device_manager (GDK_DISPLAY_OBJECT (object));
+  device_manager = gdk_display_get_device_manager (GDK_DISPLAY (object));
 
-  g_list_foreach (display->queued_events, (GFunc)gdk_event_free, NULL);
-  g_list_free (display->queued_events);
+  g_list_free_full (display->queued_events, (GDestroyNotify) gdk_event_free);
   display->queued_events = NULL;
   display->queued_tail = NULL;
 
-  _gdk_displays = g_slist_remove (_gdk_displays, object);
-
-  if (gdk_display_get_default () == display)
-    {
-      if (_gdk_displays)
-        gdk_display_manager_set_default_display (gdk_display_manager_get(),
-                                                 _gdk_displays->data);
-      else
-        gdk_display_manager_set_default_display (gdk_display_manager_get(),
-                                                 NULL);
-    }
-
   if (device_manager)
     {
       /* this is to make it drop devices which may require using the X
@@ -331,13 +228,16 @@ gdk_display_dispose (GObject *object)
 static void
 gdk_display_finalize (GObject *object)
 {
-  GdkDisplay *display = GDK_DISPLAY_OBJECT (object);
+  GdkDisplay *display = GDK_DISPLAY (object);
 
   g_hash_table_foreach_remove (display->device_grabs,
                                free_device_grabs_foreach,
                                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);
 
@@ -406,8 +306,12 @@ GdkEvent*
 gdk_display_get_event (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  
-  _gdk_events_queue (display);
+
+  if (display->event_pause_count > 0)
+    return NULL;
+
+  GDK_DISPLAY_GET_CLASS (display)->queue_events (display);
+
   return _gdk_event_unqueue (display);
 }
 
@@ -503,42 +407,6 @@ gdk_display_pointer_ungrab (GdkDisplay *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.
@@ -579,23 +447,6 @@ gdk_display_keyboard_ungrab (GdkDisplay *display,
   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:
  * 
@@ -608,127 +459,26 @@ gdk_beep (void)
 }
 
 /**
- * gdk_event_send_client_message:
- * @event: the #GdkEvent to send, which should be a #GdkEventClient.
- * @winid:  the window to send the X ClientMessage event to.
- * 
- * Sends an X ClientMessage event to a given window (which must be
- * on the default #GdkDisplay.)
- * This could be used for communicating between different applications,
- * though the amount of data is limited to 20 bytes.
- * 
- * Return value: non-zero on success.
- **/
-gboolean
-gdk_event_send_client_message (GdkEvent        *event,
-                              GdkNativeWindow  winid)
-{
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  return gdk_event_send_client_message_for_display (gdk_display_get_default (),
-                                                   event, winid);
-}
-
-/**
- * gdk_event_send_clientmessage_toall:
- * @event: the #GdkEvent to send, which should be a #GdkEventClient.
- *
- * Sends an X ClientMessage event to all toplevel windows on the default
- * #GdkScreen.
- *
- * Toplevel windows are determined by checking for the WM_STATE property, as
- * described in the Inter-Client Communication Conventions Manual (ICCCM).
- * If no windows are found with the WM_STATE property set, the message is sent
- * to all children of the root window.
- **/
-void
-gdk_event_send_clientmessage_toall (GdkEvent *event)
-{
-  g_return_if_fail (event != NULL);
-
-  gdk_screen_broadcast_client_message (gdk_screen_get_default (), event);
-}
-
-/**
- * gdk_device_get_core_pointer:
- * 
- * Returns the core pointer device for the default display.
- * 
- * Return value: (transfer none): the core pointer device; this is owned
- *   by the display and should not be freed.
- *
- * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
- *             gdk_event_get_device() if a #GdkEvent with pointer device
- *             information is available.
- **/
-GdkDevice *
-gdk_device_get_core_pointer (void)
-{
-  return gdk_display_get_core_pointer (gdk_display_get_default ());
-}
-
-/**
- * gdk_display_get_core_pointer:
- * @display: a #GdkDisplay
- * 
- * Returns the core pointer device for the given display
- * 
- * Return value: (transfer none): the core pointer device; this is owned by the
- *   display and should not be freed.
+ * gdk_flush:
  *
- * Since: 2.2
- *
- * Deprecated: 3.0: Use gdk_device_manager_get_client_pointer() instead, or
- *             gdk_event_get_device() if a #GdkEvent with device
- *             information is available.
- **/
-GdkDevice *
-gdk_display_get_core_pointer (GdkDisplay *display)
-{
-  return display->core_pointer;
-}
-
-/**
- * gdk_set_sm_client_id:
- * @sm_client_id: the client id assigned by the session manager when the
- *    connection was opened, or %NULL to remove the property.
- * 
- * Sets the <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.)
- **/
+ * Flushes the output buffers of all display connections and waits
+ * until all requests have been processed.
+ * This is rarely needed by applications.
+ */
 void
-gdk_set_sm_client_id (const gchar* sm_client_id)
+gdk_flush (void)
 {
-  GSList *displays, *tmp_list;
-  
-  g_free (gdk_sm_client_id);
-  gdk_sm_client_id = g_strdup (sm_client_id);
+  GSList *list, *l;
 
-  displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
-  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
-    _gdk_windowing_display_set_sm_client_id (tmp_list->data, sm_client_id);
+  list = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = list; l; l = l->next)
+    {
+      GdkDisplay *display = l->data;
 
-  g_slist_free (displays);
-}
+      GDK_DISPLAY_GET_CLASS (display)->sync (display);
+    }
 
-/**
- * _gdk_get_sm_client_id:
- * 
- * Gets the client ID set with gdk_set_sm_client_id(), if any.
- * 
- * Return value: Session ID, or %NULL if gdk_set_sm_client_id()
- *               has never been called.
- **/
-const char *
-_gdk_get_sm_client_id (void)
-{
-  return gdk_sm_client_id;
+  g_slist_free (list);
 }
 
 void
@@ -748,7 +498,7 @@ _gdk_display_enable_motion_hints (GdkDisplay *display,
 
   if (*device_serial != 0)
     {
-      serial = _gdk_windowing_window_get_next_serial (display);
+      serial = _gdk_display_get_next_serial (display);
       /* We might not actually generate the next request, so
         make sure this triggers always, this may cause it to
         trigger slightly too early, but this is just a hint
@@ -760,120 +510,10 @@ _gdk_display_enable_motion_hints (GdkDisplay *display,
     }
 }
 
-/**
- * gdk_display_get_device_state:
- * @display: a #GdkDisplay.
- * @device: device to query status to.
- * @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));
-
-  display->device_hooks->get_device_state (display, device, &tmp_screen, &tmp_x, &tmp_y, &tmp_mask);
-
-  if (screen)
-    *screen = tmp_screen;
-  if (x)
-    *x = tmp_x;
-  if (y)
-    *y = tmp_y;
-  if (mask)
-    *mask = tmp_mask;
-}
-
-/**
- * gdk_display_get_window_at_device_position:
- * @display: a #GdkDisplay.
- * @device: #GdkDevice to query info to.
- * @win_x: (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);
-
-  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.
@@ -884,7 +524,7 @@ gdk_display_set_device_hooks (GdkDisplay                  *display,
  *
  * Since: 2.2
  *
- * Deprecated: 3.0: Use gdk_display_get_device_state() instead.
+ * Deprecated: 3.0: Use gdk_device_get_position() instead.
  **/
 void
 gdk_display_get_pointer (GdkDisplay      *display,
@@ -893,71 +533,36 @@ gdk_display_get_pointer (GdkDisplay      *display,
                         gint            *y,
                         GdkModifierType *mask)
 {
-  g_return_if_fail (GDK_IS_DISPLAY (display));
-
-  gdk_display_get_device_state (display, display->core_pointer, screen, x, y, mask);
-}
-
-static GdkWindow *
-gdk_display_real_get_window_at_device_position (GdkDisplay *display,
-                                                GdkDevice  *device,
-                                                gint       *win_x,
-                                                gint       *win_y)
-{
-  GdkWindow *window;
-  gint x, y;
-
-  window = _gdk_windowing_window_at_device_position (display, device, &x, &y, NULL, FALSE);
-
-  /* This might need corrections, as the native window returned
-     may contain client side children */
-  if (window)
-    {
-      double xx, yy;
+  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;
 }
 
 /**
@@ -977,7 +582,7 @@ gdk_window_real_window_get_device_position (GdkDisplay       *display,
  *
  * Since: 2.2
  *
- * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
+ * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead.
  **/
 GdkWindow *
 gdk_display_get_window_at_pointer (GdkDisplay *display,
@@ -986,267 +591,65 @@ 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);
+  return gdk_device_get_window_at_position (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)
+generate_grab_broken_event (GdkWindow *window,
+                            GdkDevice *device,
+                           gboolean   implicit,
+                           GdkWindow *grab_window)
 {
-  return multihead_current_pointer_hooks->window_at_pointer (display, win_x, win_y);
-}
+  g_return_if_fail (window != NULL);
 
-static void
-multihead_default_get_pointer (GdkDisplay       *display,
-                               GdkScreen       **screen,
-                               gint             *x,
-                               gint             *y,
-                               GdkModifierType  *mask)
-{
-  return _gdk_windowing_get_device_state (display,
-                                          display->core_pointer,
-                                          screen, x, y, mask);
-}
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkEvent *event;
 
-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);
-}
+      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;
 
-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_event_put (event);
+      gdk_event_free (event);
+    }
 }
 
-/**
- * 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)
+GdkDeviceGrabInfo *
+_gdk_display_get_last_device_grab (GdkDisplay *display,
+                                   GdkDevice  *device)
 {
-  const GdkDisplayPointerHooks *result = multihead_current_pointer_hooks;
-
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  GList *l;
 
-  if (new_hooks)
-    multihead_current_pointer_hooks = new_hooks;
-  else
-    multihead_current_pointer_hooks = &multihead_default_pointer_hooks;
+  l = g_hash_table_lookup (display->device_grabs, device);
 
-  gdk_display_set_device_hooks (display, &multihead_pointer_hooks);
+  if (l)
+    {
+      l = g_list_last (l);
+      return l->data;
+    }
 
-  return (GdkDisplayPointerHooks *)result;
+  return NULL;
 }
 
-static void
-singlehead_get_pointer (GdkDisplay       *display,
-                       GdkScreen       **screen,
-                       gint             *x,
-                       gint             *y,
-                       GdkModifierType  *mask)
+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);
-  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;
-}
-
-static void
-generate_grab_broken_event (GdkWindow *window,
-                            GdkDevice *device,
-                           gboolean   implicit,
-                           GdkWindow *grab_window)
-{
-  g_return_if_fail (window != NULL);
-
-  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);
-    }
-}
-
-GdkDeviceGrabInfo *
-_gdk_display_get_last_device_grab (GdkDisplay *display,
-                                   GdkDevice  *device)
-{
-  GList *l;
-
-  l = g_hash_table_lookup (display->device_grabs, device);
-
-  if (l)
-    {
-      l = g_list_last (l);
-      return l->data;
-    }
-
-  return NULL;
-}
-
-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)
-{
-  GdkDeviceGrabInfo *info, *other_info;
-  GList *grabs, *l;
+  GdkDeviceGrabInfo *info, *other_info;
+  GList *grabs, *l;
 
   info = g_new0 (GdkDeviceGrabInfo, 1);
 
@@ -1296,6 +699,73 @@ _gdk_display_add_device_grab (GdkDisplay       *display,
   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 */
@@ -1313,10 +783,6 @@ synthesize_crossing_events (GdkDisplay      *display,
   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
@@ -1333,8 +799,9 @@ synthesize_crossing_events (GdkDisplay      *display,
       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,
@@ -1347,8 +814,9 @@ synthesize_crossing_events (GdkDisplay      *display,
     }
   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,
@@ -1362,8 +830,9 @@ synthesize_crossing_events (GdkDisplay      *display,
   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,
@@ -1373,8 +842,9 @@ synthesize_crossing_events (GdkDisplay      *display,
                                       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,
@@ -1398,7 +868,7 @@ get_current_toplevel (GdkDisplay      *display,
   int x, y;
   GdkModifierType state;
 
-  pointer_window = _gdk_windowing_window_at_device_position (display, device, &x, &y, &state, TRUE);
+  pointer_window = _gdk_device_window_at_position (device, &x, &y, &state, TRUE);
 
   if (pointer_window != NULL &&
       (GDK_WINDOW_DESTROYED (pointer_window) ||
@@ -1409,6 +879,7 @@ get_current_toplevel (GdkDisplay      *display,
   *x_out = x;
   *y_out = y;
   *state_out = state;
+
   return pointer_window;
 }
 
@@ -1425,7 +896,7 @@ switch_to_pointer_grab (GdkDisplay        *display,
   GdkPointerWindowInfo *info;
   GList *old_grabs;
   GdkModifierType state;
-  int x, y;
+  int x = 0, y = 0;
 
   /* Temporarily unset pointer to make sure we send the crossing events below */
   old_grabs = g_hash_table_lookup (display->device_grabs, device);
@@ -1478,7 +949,14 @@ switch_to_pointer_grab (GdkDisplay        *display,
            g_object_unref (info->toplevel_under_pointer);
          info->toplevel_under_pointer = NULL;
 
-         new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
+          /* Ungrabbed slave devices don't have a position by
+           * itself, rather depend on its master pointer, so
+           * it doesn't make sense to track any position for
+           * these after the grab
+           */
+          if (grab || gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_SLAVE)
+            new_toplevel = get_current_toplevel (display, device, &x, &y, &state);
+
          if (new_toplevel)
            {
              /* w is now toplevel and x,y in toplevel coords */
@@ -1491,17 +969,28 @@ switch_to_pointer_grab (GdkDisplay        *display,
 
       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);
@@ -1558,12 +1047,15 @@ _gdk_display_device_grab_update (GdkDisplay *display,
            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);
@@ -1622,6 +1114,33 @@ _gdk_display_has_device_grab (GdkDisplay *display,
   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 */
@@ -1714,6 +1233,9 @@ _gdk_display_get_pointer_info (GdkDisplay *display,
 {
   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;
 
@@ -1818,9 +1340,14 @@ gdk_display_pointer_is_grabbed (GdkDisplay *display)
 
       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;
 }
 
@@ -1868,3 +1395,846 @@ gdk_display_get_device_manager (GdkDisplay *display)
 
   return display->device_manager;
 }
+
+/**
+ * gdk_display_get_name:
+ * @display: a #GdkDisplay
+ *
+ * Gets the name of the display.
+ *
+ * Returns: a string representing the display name. This string is owned
+ * by GDK and should not be modified or freed.
+ *
+ * Since: 2.2
+ */
+const gchar *
+gdk_display_get_name (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (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)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+  GDK_DISPLAY_GET_CLASS (display)->sync (display);
+}
+
+/**
+ * gdk_display_flush:
+ * @display: a #GdkDisplay
+ *
+ * Flushes any requests queued for the windowing system; this happens automatically
+ * when the main loop blocks waiting for new events, but if your application
+ * is drawing without returning control to the main loop, you may need
+ * to call this function explicitely. A common case where this function
+ * needs to be called is when an application is executing drawing commands
+ * from a thread other than the thread where the main loop is running.
+ *
+ * This is most useful for X11. On windowing systems where requests are
+ * handled synchronously, this function will do nothing.
+ *
+ * Since: 2.4
+ */
+void
+gdk_display_flush (GdkDisplay *display)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+
+{
+  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:
+ * @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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  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)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  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)
+{
+  g_return_if_fail (GDK_IS_DISPLAY (display));
+
+  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)
+{
+  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,
+                              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)
+{
+  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);
+}