[mutter/wip/wayland-work: 20/22] wayland: heavily refactor pointer grabs



commit 0fefd5d6cc757fdc101b10c9f3b89f266a66b799
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Wed Sep 11 14:06:05 2013 +0200

    wayland: heavily refactor pointer grabs
    
    Grabs are now slice allocated structures that are handled by
    whoever starts the grab. They contain a generic grab structure
    with the interface and a backpointer to the MetaWaylandPointer.
    The grab interface has been changed to pass full clutter events,
    which allowed to remove the confusion between grab->focus and
    pointer->focus. Invidual grabs are now required to keep their
    focus, and choose whoever gets the events.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707863

 src/wayland/meta-wayland-data-device.c |  177 +++++++++++++++++------------
 src/wayland/meta-wayland-pointer.c     |  192 ++++++++++++++++++++-----------
 src/wayland/meta-wayland-pointer.h     |   29 +++---
 src/wayland/meta-wayland-seat.c        |  138 ++++++----------------
 src/wayland/meta-wayland-seat.h        |   18 +---
 src/wayland/meta-wayland-surface.c     |  198 ++++++++++++--------------------
 src/wayland/meta-wayland.c             |    4 +-
 7 files changed, 356 insertions(+), 400 deletions(-)
---
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 38d3def..b9bb21c 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -151,42 +151,63 @@ static struct wl_data_source_interface data_source_interface = {
   data_source_destroy
 };
 
+typedef struct {
+  MetaWaylandPointerGrab  generic;
+
+  MetaWaylandSeat        *seat;
+  struct wl_client       *drag_client;
+
+  MetaWaylandSurface     *drag_focus;
+  struct wl_resource     *drag_focus_data_device;
+  struct wl_listener      drag_focus_listener;
+
+  MetaWaylandSurface     *drag_surface;
+  struct wl_listener      drag_icon_listener;
+
+  MetaWaylandDataSource  *drag_data_source;
+  struct wl_listener      drag_data_source_listener;
+} MetaWaylandDragGrab;
+
 static void
 destroy_drag_focus (struct wl_listener *listener, void *data)
 {
-  MetaWaylandSeat *seat = wl_container_of (listener, seat, drag_focus_listener);
+  MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener);
 
-  seat->drag_focus_resource = NULL;
+  grab->drag_focus_data_device = NULL;
 }
 
 static void
 drag_grab_focus (MetaWaylandPointerGrab *grab,
-                 MetaWaylandSurface *surface,
-                 wl_fixed_t x,
-                 wl_fixed_t y)
+                 MetaWaylandSurface     *surface,
+                const ClutterEvent     *event)
 {
-  MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab);
+  MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
+  MetaWaylandSeat *seat = drag_grab->seat;
   struct wl_resource *resource, *offer = NULL;
   struct wl_display *display;
   guint32 serial;
+  wl_fixed_t sx, sy;
 
-  if (seat->drag_focus_resource)
+  if (drag_grab->drag_focus == surface)
+    return;
+
+  if (drag_grab->drag_focus_data_device)
     {
-      wl_data_device_send_leave (seat->drag_focus_resource);
-      wl_list_remove (&seat->drag_focus_listener.link);
-      seat->drag_focus_resource = NULL;
-      seat->drag_focus = NULL;
+      wl_data_device_send_leave (drag_grab->drag_focus_data_device);
+      wl_list_remove (&drag_grab->drag_focus_listener.link);
+      drag_grab->drag_focus_data_device = NULL;
+      drag_grab->drag_focus = NULL;
     }
 
   if (!surface)
     return;
 
-  if (!seat->drag_data_source &&
-      wl_resource_get_client (surface->resource) != seat->drag_client)
+  if (!drag_grab->drag_data_source &&
+      wl_resource_get_client (surface->resource) != drag_grab->drag_client)
     return;
 
   resource =
-    wl_resource_find_for_client (&seat->drag_resource_list,
+    wl_resource_find_for_client (&seat->data_device_resource_list,
                                  wl_resource_get_client (surface->resource));
   if (!resource)
     return;
@@ -194,68 +215,73 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
   display = wl_client_get_display (wl_resource_get_client (resource));
   serial = wl_display_next_serial (display);
 
-  if (seat->drag_data_source)
-    offer = meta_wayland_data_source_send_offer (seat->drag_data_source,
+  if (drag_grab->drag_data_source)
+    offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
                                                  resource);
 
+  meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
   wl_data_device_send_enter (resource, serial, surface->resource,
-                             x, y, offer);
+                             sx, sy, offer);
 
-  seat->drag_focus = surface;
-  seat->drag_focus_listener.notify = destroy_drag_focus;
-  wl_resource_add_destroy_listener (resource, &seat->drag_focus_listener);
-  seat->drag_focus_resource = resource;
-  grab->focus = surface;
+  drag_grab->drag_focus = surface;
+
+  drag_grab->drag_focus_data_device = resource;
+  drag_grab->drag_focus_listener.notify = destroy_drag_focus;
+  wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener);
 }
 
 static void
 drag_grab_motion (MetaWaylandPointerGrab *grab,
-                  guint32 time, wl_fixed_t x, wl_fixed_t y)
+                 const ClutterEvent     *event)
 {
-  MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab);
+  MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
+  wl_fixed_t sx, sy;
 
-  if (seat->drag_focus_resource)
-    wl_data_device_send_motion (seat->drag_focus_resource, time, x, y);
+  if (drag_grab->drag_focus_data_device)
+    {
+      meta_wayland_pointer_get_relative_coordinates (grab->pointer,
+                                                    drag_grab->drag_focus,
+                                                    &sx, &sy);
+      wl_data_device_send_motion (drag_grab->drag_focus_data_device,
+                                 clutter_event_get_time (event),
+                                 sx, sy);
+    }
 }
 
 static void
-data_device_end_drag_grab (MetaWaylandSeat *seat)
+data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
 {
-  if (seat->drag_surface)
+  if (drag_grab->drag_surface)
     {
-      seat->drag_surface = NULL;
-      wl_signal_emit (&seat->drag_icon_signal, NULL);
-      wl_list_remove (&seat->drag_icon_listener.link);
+      drag_grab->drag_surface = NULL;
+      wl_list_remove (&drag_grab->drag_icon_listener.link);
     }
 
-  drag_grab_focus (&seat->drag_grab, NULL,
-                   wl_fixed_from_int (0), wl_fixed_from_int (0));
+  if (drag_grab->drag_data_source)
+    wl_list_remove (&drag_grab->drag_data_source_listener.link);
 
-  meta_wayland_pointer_end_grab (&seat->pointer);
+  drag_grab_focus (&drag_grab->generic, NULL, NULL);
 
-  seat->drag_data_source = NULL;
-  seat->drag_client = NULL;
+  meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
+  g_slice_free (MetaWaylandDragGrab, drag_grab);
 }
 
 static void
 drag_grab_button (MetaWaylandPointerGrab *grab,
-                  guint32 time, guint32 button, guint32 state_w)
+                 const ClutterEvent     *event)
 {
-  MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab);
-  enum wl_pointer_button_state state = state_w;
+  MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
+  MetaWaylandSeat *seat = drag_grab->seat;
+  ClutterEventType event_type = clutter_event_type (event);
 
-  if (seat->drag_focus_resource &&
-      seat->pointer.grab_button == button &&
-      state == WL_POINTER_BUTTON_STATE_RELEASED)
-    wl_data_device_send_drop (seat->drag_focus_resource);
+  if (drag_grab->drag_focus_data_device &&
+      drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
+      event_type == CLUTTER_BUTTON_RELEASE)
+    wl_data_device_send_drop (drag_grab->drag_focus_data_device);
 
   if (seat->pointer.button_count == 0 &&
-      state == WL_POINTER_BUTTON_STATE_RELEASED)
-    {
-      if (seat->drag_data_source)
-        wl_list_remove (&seat->drag_data_source_listener.link);
-      data_device_end_drag_grab (seat);
-    }
+      event_type == CLUTTER_BUTTON_RELEASE)
+    data_device_end_drag_grab (drag_grab);
 }
 
 static const MetaWaylandPointerGrabInterface drag_grab_interface = {
@@ -267,19 +293,20 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
 static void
 destroy_data_device_source (struct wl_listener *listener, void *data)
 {
-  MetaWaylandSeat *seat =
-    wl_container_of (listener, seat, drag_data_source_listener);
+  MetaWaylandDragGrab *drag_grab =
+    wl_container_of (listener, drag_grab, drag_data_source_listener);
 
-  data_device_end_drag_grab (seat);
+  drag_grab->drag_data_source = NULL;
+  data_device_end_drag_grab (drag_grab);
 }
 
 static void
 destroy_data_device_icon (struct wl_listener *listener, void *data)
 {
-  MetaWaylandSeat *seat =
-    wl_container_of (listener, seat, drag_icon_listener);
+  MetaWaylandDragGrab *drag_grab =
+    wl_container_of (listener, drag_grab, drag_data_source_listener);
 
-  seat->drag_surface = NULL;
+  drag_grab->drag_surface = NULL;
 }
 
 static void
@@ -290,38 +317,40 @@ data_device_start_drag (struct wl_client *client,
                         struct wl_resource *icon_resource, guint32 serial)
 {
   MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
-
+  MetaWaylandDragGrab *drag_grab;
   /* FIXME: Check that client has implicit grab on the origin
    * surface that matches the given time. */
 
   /* FIXME: Check that the data source type array isn't empty. */
 
-  seat->drag_grab.interface = &drag_grab_interface;
+  if (seat->pointer.grab != &seat->pointer.default_grab)
+    return;
+
+  drag_grab = g_slice_new0 (MetaWaylandDragGrab);
+
+  drag_grab->generic.interface = &drag_grab_interface;
+  drag_grab->generic.pointer = &seat->pointer;
 
-  seat->drag_client = client;
-  seat->drag_data_source = NULL;
+  drag_grab->drag_client = client;
 
   if (source_resource)
     {
-      seat->drag_data_source = wl_resource_get_user_data (source_resource);
-      seat->drag_data_source_listener.notify = destroy_data_device_source;
+      drag_grab->drag_data_source = wl_resource_get_user_data (source_resource);
+      drag_grab->drag_data_source_listener.notify = destroy_data_device_source;
       wl_resource_add_destroy_listener (source_resource,
-                                        &seat->drag_data_source_listener);
+                                        &drag_grab->drag_data_source_listener);
     }
 
   if (icon_resource)
     {
-      seat->drag_surface = wl_resource_get_user_data (icon_resource);
-      seat->drag_icon_listener.notify = destroy_data_device_icon;
+      drag_grab->drag_surface = wl_resource_get_user_data (icon_resource);
+      drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
       wl_resource_add_destroy_listener (icon_resource,
-                                        &seat->drag_icon_listener);
-      wl_signal_emit (&seat->drag_icon_signal, icon_resource);
+                                        &drag_grab->drag_icon_listener);
     }
 
-  meta_wayland_pointer_set_focus (&seat->pointer, NULL,
-                              wl_fixed_from_int (0),
-                              wl_fixed_from_int (0));
-  meta_wayland_pointer_start_grab (&seat->pointer, &seat->drag_grab);
+  meta_wayland_pointer_set_focus (&seat->pointer, NULL);
+  meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
 }
 
 static void
@@ -339,7 +368,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
   if (focus)
     {
       data_device =
-        wl_resource_find_for_client (&seat->drag_resource_list,
+        wl_resource_find_for_client (&seat->data_device_resource_list,
                                      wl_resource_get_client (focus));
       if (data_device)
         wl_data_device_send_selection (data_device, NULL);
@@ -375,7 +404,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
   if (focus)
     {
       data_device =
-        wl_resource_find_for_client (&seat->drag_resource_list,
+        wl_resource_find_for_client (&seat->data_device_resource_list,
                                      wl_resource_get_client (focus));
       if (data_device && source)
         {
@@ -497,7 +526,7 @@ get_data_device (struct wl_client *client,
                                 MIN (META_WL_DATA_DEVICE_VERSION,
                                      wl_resource_get_version (manager_resource)), id);
   wl_resource_set_implementation (resource, &data_device_interface, seat, unbind_data_device);
-  wl_list_insert (&seat->drag_resource_list, wl_resource_get_link (resource));
+  wl_list_insert (&seat->data_device_resource_list, wl_resource_get_link (resource));
 }
 
 static const struct wl_data_device_manager_interface manager_interface = {
@@ -526,7 +555,7 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat)
   if (!focus)
     return;
 
-  data_device = wl_resource_find_for_client (&seat->drag_resource_list,
+  data_device = wl_resource_find_for_client (&seat->data_device_resource_list,
                                              wl_resource_get_client (focus));
   if (!data_device)
     return;
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index ca0dc49..8877b37 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -45,6 +45,7 @@
 
 #include <clutter/clutter.h>
 #include <clutter/evdev/clutter-evdev.h>
+#include <linux/input.h>
 
 #include "meta-wayland-pointer.h"
 #include "meta-wayland-private.h"
@@ -74,51 +75,79 @@ lose_pointer_focus (struct wl_listener *listener, void *data)
 
 static void
 default_grab_focus (MetaWaylandPointerGrab *grab,
-                    MetaWaylandSurface *surface,
-                    wl_fixed_t x,
-                    wl_fixed_t y)
+                    MetaWaylandSurface     *surface,
+                   const ClutterEvent     *event)
 {
   MetaWaylandPointer *pointer = grab->pointer;
 
   if (pointer->button_count > 0)
     return;
 
-  meta_wayland_pointer_set_focus (pointer, surface, x, y);
+  meta_wayland_pointer_set_focus (pointer, surface);
 }
 
 static void
 default_grab_motion (MetaWaylandPointerGrab *grab,
-                     uint32_t time, wl_fixed_t x, wl_fixed_t y)
+                    const ClutterEvent     *event)
 {
   struct wl_resource *resource;
 
   resource = grab->pointer->focus_resource;
   if (resource)
-    wl_pointer_send_motion (resource, time, x, y);
+    {
+      wl_fixed_t sx, sy;
+
+      meta_wayland_pointer_get_relative_coordinates (grab->pointer,
+                                                    grab->pointer->focus,
+                                                    &sx, &sy);
+      wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
+    }
 }
 
 static void
 default_grab_button (MetaWaylandPointerGrab *grab,
-                     uint32_t time, uint32_t button, uint32_t state_w)
+                    const ClutterEvent     *event)
 {
   MetaWaylandPointer *pointer = grab->pointer;
   struct wl_resource *resource;
-  uint32_t serial;
-  enum wl_pointer_button_state state = state_w;
+  ClutterEventType event_type;
+
+  event_type = clutter_event_type (event);
 
   resource = pointer->focus_resource;
   if (resource)
     {
       struct wl_client *client = wl_resource_get_client (resource);
       struct wl_display *display = wl_client_get_display (client);
+      uint32_t button;
+      uint32_t serial;
+
+      button = clutter_event_get_button (event);
+      switch (button)
+       {
+         /* The evdev input right and middle button numbers are swapped
+            relative to how Clutter numbers them */
+       case 2:
+         button = BTN_MIDDLE;
+         break;
+
+       case 3:
+         button = BTN_RIGHT;
+         break;
+
+       default:
+         button = button + BTN_LEFT - 1;
+         break;
+       }
+
       serial = wl_display_next_serial (display);
-      pointer->click_serial = serial;
-      wl_pointer_send_button (resource, serial, time, button, state_w);
+      wl_pointer_send_button (resource, serial,
+                             clutter_event_get_time (event), button,
+                             event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
     }
 
-  if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED)
-    meta_wayland_pointer_set_focus (pointer, pointer->current,
-                                pointer->current_x, pointer->current_y);
+  if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
+    meta_wayland_pointer_set_focus (pointer, pointer->current);
 }
 
 static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
@@ -293,8 +322,7 @@ find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface)
 
 void
 meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
-                                MetaWaylandSurface *surface,
-                                wl_fixed_t sx, wl_fixed_t sy)
+                                MetaWaylandSurface *surface)
 {
   MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
   MetaWaylandKeyboard *kbd = &seat->keyboard;
@@ -317,7 +345,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
     {
       struct wl_client *client = wl_resource_get_client (resource);
       struct wl_display *display = wl_client_get_display (client);
+      wl_fixed_t sx, sy;
+
       serial = wl_display_next_serial (display);
+
       if (kbd)
         {
           kr = find_resource_for_surface (&kbd->resource_list, surface);
@@ -331,6 +362,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
                                           kbd->modifier_state.group);
             }
         }
+
+      meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
       wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
       wl_resource_add_destroy_listener (resource, &pointer->focus_listener);
       pointer->focus_serial = serial;
@@ -338,8 +371,6 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
 
   pointer->focus_resource = resource;
   pointer->focus = surface;
-  pointer->default_grab.focus = surface;
-  wl_signal_emit (&pointer->focus_signal, pointer);
 }
 
 void
@@ -353,8 +384,7 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
   grab->pointer = pointer;
 
   if (pointer->current)
-    interface->focus (pointer->grab, pointer->current,
-                      pointer->current_x, pointer->current_y);
+    interface->focus (pointer->grab, pointer->current, NULL);
 }
 
 void
@@ -364,8 +394,7 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
 
   pointer->grab = &pointer->default_grab;
   interface = pointer->grab->interface;
-  interface->focus (pointer->grab, pointer->current,
-                    pointer->current_x, pointer->current_y);
+  interface->focus (pointer->grab, pointer->current, NULL);
 }
 
 static void
@@ -397,24 +426,19 @@ meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
 static void
 modal_focus (MetaWaylandPointerGrab *grab,
             MetaWaylandSurface     *surface,
-            wl_fixed_t              x,
-            wl_fixed_t              y)
+            const ClutterEvent     *event)
 {
 }
 
 static void
 modal_motion (MetaWaylandPointerGrab *grab,
-             uint32_t                time,
-             wl_fixed_t              x,
-             wl_fixed_t              y)
+             const ClutterEvent     *event)
 {
 }
 
 static void
 modal_button (MetaWaylandPointerGrab *grab,
-             uint32_t                time,
-             uint32_t                button,
-             uint32_t                state)
+             const ClutterEvent     *event)
 {
 }
 
@@ -432,9 +456,7 @@ meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
   if (pointer->grab != &pointer->default_grab)
     return FALSE;
 
-  meta_wayland_pointer_set_focus (pointer, NULL,
-                                 wl_fixed_from_int (0),
-                                 wl_fixed_from_int (0));
+  meta_wayland_pointer_set_focus (pointer, NULL);
 
   grab = g_slice_new0 (MetaWaylandPointerGrab);
   grab->interface = &modal_grab;
@@ -470,56 +492,61 @@ meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer)
         we have button down, and the clients would be confused if the
         pointer enters the surface.
       */
-      meta_wayland_pointer_set_focus (pointer, NULL, 0, 0);
+      meta_wayland_pointer_set_focus (pointer, NULL);
     }
 }
 
+typedef struct {
+  MetaWaylandPointerGrab  generic;
+
+  MetaWaylandSurface     *popup;
+  struct wl_listener      popup_destroy_listener;
+} MetaWaylandPopupGrab;
+
 static void
 popup_grab_focus (MetaWaylandPointerGrab *grab,
                  MetaWaylandSurface     *surface,
-                 wl_fixed_t              x,
-                 wl_fixed_t              y)
+                 const ClutterEvent     *event)
 {
+  MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
+
   /* Popup grabs are in owner-events mode (ie, events for the same client
      are reported as normal) */
   if (wl_resource_get_client (surface->resource) ==
-      wl_resource_get_client (grab->focus->resource))
-    default_grab_focus (grab, surface, x, y);
+      wl_resource_get_client (popup_grab->popup->resource))
+    default_grab_focus (grab, surface, event);
   else
-    meta_wayland_pointer_set_focus (grab->pointer, NULL, 0, 0);
+    meta_wayland_pointer_set_focus (grab->pointer, NULL);
 }
 
 static void
 popup_grab_motion (MetaWaylandPointerGrab *grab,
-                  uint32_t                time,
-                  wl_fixed_t              x,
-                  wl_fixed_t              y)
+                  const ClutterEvent     *event)
 {
-  default_grab_motion (grab, time, x, y);
+  default_grab_motion (grab, event);
 }
 
 static void
 popup_grab_button (MetaWaylandPointerGrab *grab,
-                  uint32_t                time,
-                  uint32_t                button,
-                  uint32_t                state)
+                  const ClutterEvent     *event)
 {
+  MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
   MetaWaylandPointer *pointer = grab->pointer;
 
   if (pointer->focus_resource)
     {
       /* This is ensured by popup_grab_focus */
       g_assert (wl_resource_get_client (pointer->focus_resource) ==
-               wl_resource_get_client (grab->focus->resource));
+               wl_resource_get_client (popup_grab->popup->resource));
 
-      default_grab_button (grab, time, button, state);
+      default_grab_button (grab, event);
     }
-  else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
+  else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE &&
           pointer->button_count == 0)
     meta_wayland_pointer_end_popup_grab (grab->pointer);
 }
 
-static MetaWaylandPointerGrabInterface popup_grab = {
+static MetaWaylandPointerGrabInterface popup_grab_interface = {
   popup_grab_focus,
   popup_grab_motion,
   popup_grab_button
@@ -528,50 +555,75 @@ static MetaWaylandPointerGrabInterface popup_grab = {
 static void
 meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
 {
-  MetaWaylandPointerGrab *grab;
+  MetaWaylandPopupGrab *popup_grab;
 
-  grab = pointer->grab;
+  popup_grab = (MetaWaylandPopupGrab*)pointer->grab;
 
-  g_assert (grab->interface == &popup_grab);
+  g_assert (popup_grab->generic.interface == &popup_grab_interface);
 
-  if (grab->focus)
+  if (popup_grab->popup)
     {
-      wl_shell_surface_send_popup_done (grab->focus->shell_surface->resource);
-      wl_list_remove (&grab->focus_destroy_listener.link);
+      wl_shell_surface_send_popup_done (popup_grab->popup->shell_surface->resource);
+      wl_list_remove (&popup_grab->popup_destroy_listener.link);
     }
 
   meta_wayland_pointer_end_grab (pointer);
-  g_slice_free (MetaWaylandPointerGrab, grab);
+  g_slice_free (MetaWaylandPopupGrab, popup_grab);
 }
 
 static void
 on_popup_surface_destroy (struct wl_listener *listener,
                          void               *data)
 {
-  MetaWaylandPointerGrab *grab =
-    wl_container_of (listener, grab, focus_destroy_listener);
+  MetaWaylandPopupGrab *grab =
+    wl_container_of (listener, grab, popup_destroy_listener);
 
-  grab->focus = NULL;
-  meta_wayland_pointer_end_popup_grab (grab->pointer);
+  grab->popup = NULL;
+  meta_wayland_pointer_end_popup_grab (grab->generic.pointer);
 }
 
 gboolean
 meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
                                       MetaWaylandSurface *surface)
 {
-  MetaWaylandPointerGrab *grab;
+  MetaWaylandPopupGrab *grab;
 
-  if (pointer->grab != &pointer->default_grab)
+  if (pointer->grab != &pointer->default_grab &&
+      pointer->grab->interface != &popup_grab_interface)
     return FALSE;
 
-  grab = g_slice_new0 (MetaWaylandPointerGrab);
-  grab->interface = &popup_grab;
-  grab->pointer = pointer;
-  grab->focus = surface;
+  grab = g_slice_new0 (MetaWaylandPopupGrab);
+  grab->generic.interface = &popup_grab_interface;
+  grab->generic.pointer = pointer;
+  grab->popup = surface;
 
-  grab->focus_destroy_listener.notify = on_popup_surface_destroy;
-  wl_resource_add_destroy_listener (surface->resource, &grab->focus_destroy_listener);
+  grab->popup_destroy_listener.notify = on_popup_surface_destroy;
+  wl_resource_add_destroy_listener (surface->resource, &grab->popup_destroy_listener);
 
-  meta_wayland_pointer_start_grab (pointer, grab);
+  meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab);
   return TRUE;
 }
+
+void
+meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
+                                              MetaWaylandSurface *surface,
+                                              wl_fixed_t         *sx,
+                                              wl_fixed_t         *sy)
+{
+  float xf = 0.0f, yf = 0.0f;
+
+  if (surface->window)
+    {
+      ClutterActor *actor =
+        CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window));
+
+      if (actor)
+        clutter_actor_transform_stage_point (actor,
+                                             wl_fixed_to_double (pointer->x),
+                                             wl_fixed_to_double (pointer->y),
+                                             &xf, &yf);
+    }
+
+  *sx = wl_fixed_from_double (xf);
+  *sy = wl_fixed_from_double (yf);
+}
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index bba28d0..d355d29 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -28,22 +28,19 @@
 
 struct _MetaWaylandPointerGrabInterface
 {
-  void (*focus) (MetaWaylandPointerGrab * grab,
-                 MetaWaylandSurface * surface, wl_fixed_t x, wl_fixed_t y);
-  void (*motion) (MetaWaylandPointerGrab * grab,
-                  uint32_t time, wl_fixed_t x, wl_fixed_t y);
-  void (*button) (MetaWaylandPointerGrab * grab,
-                  uint32_t time, uint32_t button, uint32_t state);
+  void (*focus) (MetaWaylandPointerGrab *grab,
+                 MetaWaylandSurface     *surface,
+                const ClutterEvent     *event);
+  void (*motion) (MetaWaylandPointerGrab *grab,
+                 const ClutterEvent     *event);
+  void (*button) (MetaWaylandPointerGrab *grab,
+                 const ClutterEvent     *event);
 };
 
 struct _MetaWaylandPointerGrab
 {
   const MetaWaylandPointerGrabInterface *interface;
   MetaWaylandPointer *pointer;
-  MetaWaylandSurface *focus;
-  wl_fixed_t x, y;
-
-  struct wl_listener focus_destroy_listener;
 };
 
 struct _MetaWaylandPointer
@@ -59,6 +56,7 @@ struct _MetaWaylandPointer
   MetaWaylandPointerGrab *grab;
   MetaWaylandPointerGrab default_grab;
   wl_fixed_t grab_x, grab_y;
+  wl_fixed_t focus_x, focus_y;
   guint32 grab_button;
   guint32 grab_serial;
   guint32 grab_time;
@@ -80,10 +78,7 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer);
 
 void
 meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
-                                MetaWaylandSurface *surface,
-                                wl_fixed_t sx,
-                                wl_fixed_t sy);
-
+                                MetaWaylandSurface *surface);
 void
 meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer);
 
@@ -107,4 +102,10 @@ void
 meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
                                   MetaWaylandSurface *surface);
 
+void
+meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
+                                              MetaWaylandSurface *surface,
+                                              wl_fixed_t         *x,
+                                              wl_fixed_t         *y);
+
 #endif /* __META_WAYLAND_POINTER_H__ */
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index a55071e..e4678d5 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -48,31 +48,6 @@ unbind_resource (struct wl_resource *resource)
 }
 
 static void
-transform_stage_point_fixed (MetaWaylandSurface *surface,
-                             wl_fixed_t x,
-                             wl_fixed_t y,
-                             wl_fixed_t *sx,
-                             wl_fixed_t *sy)
-{
-  float xf = 0.0f, yf = 0.0f;
-
-  if (surface->window)
-    {
-      ClutterActor *actor =
-        CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window));
-
-      if (actor)
-        clutter_actor_transform_stage_point (actor,
-                                             wl_fixed_to_double (x),
-                                             wl_fixed_to_double (y),
-                                             &xf, &yf);
-    }
-
-  *sx = wl_fixed_from_double (xf);
-  *sy = wl_fixed_from_double (yf);
-}
-
-static void
 pointer_unmap_sprite (MetaWaylandSeat *seat)
 {
   if (seat->cursor_tracker)
@@ -173,19 +148,7 @@ seat_get_pointer (struct wl_client *client,
 
   if (seat->pointer.focus &&
       wl_resource_get_client (seat->pointer.focus->resource) == client)
-    {
-      MetaWaylandSurface *surface;
-      wl_fixed_t sx, sy;
-
-      surface = (MetaWaylandSurface *) seat->pointer.focus;
-      transform_stage_point_fixed (surface,
-                                   seat->pointer.x,
-                                   seat->pointer.y,
-                                   &sx, &sy);
-      meta_wayland_pointer_set_focus (&seat->pointer,
-                                  seat->pointer.focus,
-                                  sx, sy);
-    }
+    meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus);
 }
 
 static void
@@ -209,8 +172,7 @@ seat_get_keyboard (struct wl_client *client,
   if (seat->keyboard.focus &&
       wl_resource_get_client (seat->keyboard.focus->resource) == client)
     {
-      meta_wayland_keyboard_set_focus (&seat->keyboard,
-                                   seat->keyboard.focus);
+      meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus);
       meta_wayland_data_device_set_keyboard_focus (seat);
     }
 }
@@ -273,8 +235,7 @@ meta_wayland_seat_new (struct wl_display *display,
   seat->selection_data_source = NULL;
   wl_list_init (&seat->base_resource_list);
   wl_signal_init (&seat->selection_signal);
-  wl_list_init (&seat->drag_resource_list);
-  wl_signal_init (&seat->drag_icon_signal);
+  wl_list_init (&seat->data_device_resource_list);
 
   meta_wayland_pointer_init (&seat->pointer, is_native);
 
@@ -295,7 +256,7 @@ meta_wayland_seat_new (struct wl_display *display,
 }
 
 static void
-notify_motion (MetaWaylandSeat *seat,
+notify_motion (MetaWaylandSeat    *seat,
                const ClutterEvent *event)
 {
   MetaWaylandPointer *pointer = &seat->pointer;
@@ -305,61 +266,40 @@ notify_motion (MetaWaylandSeat *seat,
   pointer->x = wl_fixed_from_double (x);
   pointer->y = wl_fixed_from_double (y);
 
-  meta_wayland_seat_repick (seat,
-                        clutter_event_get_time (event),
-                        clutter_event_get_source (event));
+  meta_wayland_seat_repick (seat, event);
 
-  pointer->grab->interface->motion (pointer->grab,
-                                    clutter_event_get_time (event),
-                                    pointer->grab->x,
-                                    pointer->grab->y);
+  pointer->grab->interface->motion (pointer->grab, event);
 }
 
 static void
-handle_motion_event (MetaWaylandSeat *seat,
-                     const ClutterMotionEvent *event)
+handle_motion_event (MetaWaylandSeat    *seat,
+                     const ClutterEvent *event)
 {
-  notify_motion (seat, (const ClutterEvent *) event);
+  notify_motion (seat, event);
 }
 
 static void
-handle_button_event (MetaWaylandSeat *seat,
-                     const ClutterButtonEvent *event)
+handle_button_event (MetaWaylandSeat    *seat,
+                     const ClutterEvent *event)
 {
   MetaWaylandPointer *pointer = &seat->pointer;
   gboolean state = event->type == CLUTTER_BUTTON_PRESS;
   uint32_t button;
+  MetaWaylandSurface *surface;
 
-  notify_motion (seat, (const ClutterEvent *) event);
-
-  switch (event->button)
-    {
-      /* The evdev input right and middle button numbers are swapped
-         relative to how Clutter numbers them */
-    case 2:
-      button = BTN_MIDDLE;
-      break;
-
-    case 3:
-      button = BTN_RIGHT;
-      break;
-
-    default:
-      button = event->button + BTN_LEFT - 1;
-      break;
-    }
+  notify_motion (seat, event);
 
-  /* FIXME: synth a XI2 event and handle in display.c */
   if (state && pointer->button_count == 1)
     {
-      MetaWaylandSurface *surface = pointer->current;
-
+      button = clutter_event_get_button (event);
       pointer->grab_button = button;
-      pointer->grab_time = event->time;
+      pointer->grab_time = clutter_event_get_time (event);
       pointer->grab_x = pointer->x;
       pointer->grab_y = pointer->y;
 
-      if (button == BTN_LEFT &&
+      /* FIXME: synth a XI2 event and handle in display.c */
+      surface = pointer->current;
+      if (button == CLUTTER_BUTTON_PRIMARY &&
          surface &&
          surface->window &&
          surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
@@ -368,22 +308,22 @@ handle_button_event (MetaWaylandSeat *seat,
        }
     }
 
-  pointer->grab->interface->button (pointer->grab, event->time, button, state);
+  pointer->grab->interface->button (pointer->grab, event);
 
   if (pointer->button_count == 1)
     pointer->grab_serial = wl_display_get_serial (seat->display);
 }
 
 static void
-handle_scroll_event (MetaWaylandSeat *seat,
-                     const ClutterScrollEvent *event)
+handle_scroll_event (MetaWaylandSeat    *seat,
+                     const ClutterEvent *event)
 {
   enum wl_pointer_axis axis;
   wl_fixed_t value;
 
-  notify_motion (seat, (const ClutterEvent *) event);
+  notify_motion (seat, event);
 
-  switch (event->direction)
+  switch (clutter_event_get_scroll_direction (event))
     {
     case CLUTTER_SCROLL_UP:
       axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
@@ -411,7 +351,7 @@ handle_scroll_event (MetaWaylandSeat *seat,
 
   if (seat->pointer.focus_resource)
     wl_pointer_send_axis (seat->pointer.focus_resource,
-                          event->time,
+                          clutter_event_get_time (event),
                           axis,
                           value);
 }
@@ -447,14 +387,12 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
   switch (event->type)
     {
     case CLUTTER_MOTION:
-      handle_motion_event (seat,
-                           (const ClutterMotionEvent *) event);
+      handle_motion_event (seat, event);
       break;
 
     case CLUTTER_BUTTON_PRESS:
     case CLUTTER_BUTTON_RELEASE:
-      handle_button_event (seat,
-                           (const ClutterButtonEvent *) event);
+      handle_button_event (seat, event);
       break;
 
     case CLUTTER_KEY_PRESS:
@@ -463,7 +401,7 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
                                                  (const ClutterKeyEvent *) event);
 
     case CLUTTER_SCROLL:
-      handle_scroll_event (seat, (const ClutterScrollEvent *) event);
+      handle_scroll_event (seat, event);
       break;
 
     default:
@@ -493,14 +431,18 @@ update_pointer_position_for_actor (MetaWaylandPointer *pointer,
    case Clutter will have already performed a pick so we can avoid
    redundantly doing another one */
 void
-meta_wayland_seat_repick (MetaWaylandSeat *seat,
-                          uint32_t time,
-                          ClutterActor *actor)
+meta_wayland_seat_repick (MetaWaylandSeat    *seat,
+                         const ClutterEvent *for_event)
 {
+  ClutterActor       *actor   = NULL;
   MetaWaylandPointer *pointer = &seat->pointer;
   MetaWaylandSurface *surface = NULL;
 
-  if (actor == NULL && seat->current_stage)
+  if (for_event)
+    {
+      actor = clutter_event_get_source (for_event);
+    }
+  else if (seat->current_stage)
     {
       ClutterStage *stage = CLUTTER_STAGE (seat->current_stage);
       actor = clutter_stage_get_actor_at_pos (stage,
@@ -538,16 +480,8 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
       const MetaWaylandPointerGrabInterface *interface =
         pointer->grab->interface;
       interface->focus (pointer->grab,
-                        surface,
-                        pointer->current_x, pointer->current_y);
+                        surface, for_event);
     }
-
-  if (pointer->grab->focus)
-    transform_stage_point_fixed (pointer->grab->focus,
-                                 pointer->x,
-                                 pointer->y,
-                                 &pointer->grab->x,
-                                 &pointer->grab->y);
 }
 
 void
diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h
index 09b9d70..3c968ef 100644
--- a/src/wayland/meta-wayland-seat.h
+++ b/src/wayland/meta-wayland-seat.h
@@ -61,18 +61,7 @@ struct _MetaWaylandSeat
   struct wl_listener selection_data_source_listener;
   struct wl_signal selection_signal;
 
-  struct wl_list drag_resource_list;
-  struct wl_client *drag_client;
-  MetaWaylandDataSource *drag_data_source;
-  struct wl_listener drag_data_source_listener;
-  MetaWaylandSurface *drag_focus;
-  struct wl_resource *drag_focus_resource;
-  struct wl_listener drag_focus_listener;
-  MetaWaylandPointerGrab drag_grab;
-  MetaWaylandSurface *drag_surface;
-  struct wl_listener drag_icon_listener;
-  struct wl_signal drag_icon_signal;
-
+  struct wl_list data_device_resource_list;
   MetaWaylandPointer pointer;
   MetaWaylandKeyboard keyboard;
 
@@ -95,9 +84,8 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
                                 const ClutterEvent *event);
 
 void
-meta_wayland_seat_repick (MetaWaylandSeat *seat,
-                          uint32_t time,
-                          ClutterActor *actor);
+meta_wayland_seat_repick (MetaWaylandSeat    *seat,
+                         const ClutterEvent *for_event);
 
 void
 meta_wayland_seat_update_sprite (MetaWaylandSeat *seat);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 58dab54..f77f9cb 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -407,7 +407,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
       meta_wayland_pointer_destroy_focus (&compositor->seat->pointer);
 
       g_assert (surface != compositor->seat->pointer.focus);
-      g_assert (surface != compositor->seat->pointer.grab->focus);
     }
 
  if (compositor->implicit_grab_surface == surface)
@@ -493,162 +492,76 @@ shell_surface_pong (struct wl_client *client,
 {
 }
 
-typedef struct _MetaWaylandGrab
+typedef struct
 {
-  MetaWaylandPointerGrab grab;
-  MetaWaylandSurfaceExtension *shell_surface;
-  struct wl_listener shell_surface_destroy_listener;
-  MetaWaylandPointer *pointer;
-} MetaWaylandGrab;
-
-typedef struct _MetaWaylandMoveGrab
-{
-  MetaWaylandGrab base;
-  wl_fixed_t dx, dy;
+  MetaWaylandPointerGrab  generic;
+  MetaWaylandSurface     *surface;
+  struct wl_listener      surface_destroy_listener;
+  wl_fixed_t              dx, dy;
 } MetaWaylandMoveGrab;
 
 static void
-destroy_shell_surface_grab_listener (struct wl_listener *listener,
-                                     void *data)
+end_move_grab (MetaWaylandMoveGrab *move_grab)
 {
-  MetaWaylandGrab *grab = wl_container_of (listener, grab,
-                                           shell_surface_destroy_listener);
-  grab->shell_surface = NULL;
+  if (move_grab->surface)
+    {
+      move_grab->surface = NULL;
+      wl_list_remove (&move_grab->surface_destroy_listener.link);
+    }
 
-  /* XXX: Could we perhaps just stop the grab here so we don't have
-   * to consider grab->shell_surface becoming NULL in grab interface
-   * callbacks? */
+  meta_wayland_pointer_end_grab (move_grab->generic.pointer);
+  g_slice_free (MetaWaylandMoveGrab, move_grab);
 }
 
-typedef enum _GrabCursor
-{
-  GRAB_CURSOR_MOVE,
-} GrabCursor;
-
 static void
-grab_pointer (MetaWaylandGrab *grab,
-              const MetaWaylandPointerGrabInterface *interface,
-              MetaWaylandSurfaceExtension *shell_surface,
-              MetaWaylandPointer *pointer,
-              GrabCursor cursor)
+move_grab_lose_surface (struct wl_listener *listener, void *data)
 {
-  /* TODO: popup_grab_end (pointer); */
-
-  grab->grab.interface = interface;
-  grab->shell_surface = shell_surface;
-  grab->shell_surface_destroy_listener.notify =
-    destroy_shell_surface_grab_listener;
-  wl_resource_add_destroy_listener (shell_surface->resource,
-                                    &grab->shell_surface_destroy_listener);
-
-  grab->pointer = pointer;
-  grab->grab.focus = shell_surface->surface;
-
-  meta_wayland_pointer_start_grab (pointer, &grab->grab);
+  MetaWaylandMoveGrab *move_grab =
+    wl_container_of (listener, move_grab, surface_destroy_listener);
 
-  /* TODO: send_grab_cursor (cursor); */
-
-  /* XXX: In Weston there is a desktop shell protocol which has
-   * a set_grab_surface request that's used to specify the surface
-   * that's focused here.
-   *
-   * TODO: understand why.
-   *
-   * XXX: For now we just focus the surface directly associated with
-   * the grab.
-   */
-  meta_wayland_pointer_set_focus (pointer,
-                                  grab->shell_surface->surface,
-                                  wl_fixed_from_int (0),
-                                  wl_fixed_from_int (0));
-}
-
-static void
-release_pointer (MetaWaylandGrab *grab)
-{
-  if (grab->shell_surface)
-    wl_list_remove (&grab->shell_surface_destroy_listener.link);
-
-  meta_wayland_pointer_end_grab (grab->pointer);
+  move_grab->surface = NULL;
+  end_move_grab (move_grab);
 }
 
 static void
-noop_grab_focus (MetaWaylandPointerGrab *grab,
-                 MetaWaylandSurface *surface,
-                 wl_fixed_t x,
-                 wl_fixed_t y)
+move_grab_focus (MetaWaylandPointerGrab *grab,
+                 MetaWaylandSurface     *surface,
+                const ClutterEvent     *event)
 {
-  grab->focus = NULL;
 }
 
 static void
 move_grab_motion (MetaWaylandPointerGrab *grab,
-                  uint32_t time,
-                  wl_fixed_t x,
-                  wl_fixed_t y)
+                 const ClutterEvent     *event)
 {
-  MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
-  MetaWaylandPointer *pointer = move->base.pointer;
-  MetaWaylandSurfaceExtension *shell_surface = move->base.shell_surface;
-
-  if (!shell_surface)
-    return;
+  MetaWaylandMoveGrab *move_grab = (MetaWaylandMoveGrab *)grab;
+  MetaWaylandPointer *pointer = grab->pointer;
 
-  meta_window_move (shell_surface->surface->window,
+  meta_window_move (move_grab->surface->window,
                     TRUE,
-                    wl_fixed_to_int (pointer->x + move->dx),
-                    wl_fixed_to_int (pointer->y + move->dy));
+                    wl_fixed_to_int (pointer->x + move_grab->dx),
+                    wl_fixed_to_int (pointer->y + move_grab->dy));
 }
 
 static void
-move_grab_button (MetaWaylandPointerGrab *pointer_grab,
-                  uint32_t time,
-                  uint32_t button,
-                  uint32_t state_w)
+move_grab_button (MetaWaylandPointerGrab *grab,
+                 const ClutterEvent     *event)
 {
-  MetaWaylandGrab *grab =
-    wl_container_of (pointer_grab, grab, grab);
-  MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
+  MetaWaylandMoveGrab *move_grab = (MetaWaylandMoveGrab *)grab;
   MetaWaylandPointer *pointer = grab->pointer;
-  enum wl_pointer_button_state state = state_w;
 
-  if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED)
-    {
-      release_pointer (grab);
-      g_slice_free (MetaWaylandMoveGrab, move);
-    }
+  if (pointer->button_count == 0 &&
+      clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)
+    end_move_grab (move_grab);
 }
 
 static const MetaWaylandPointerGrabInterface move_grab_interface = {
-    noop_grab_focus,
+    move_grab_focus,
     move_grab_motion,
     move_grab_button,
 };
 
 static void
-start_surface_move (MetaWaylandSurfaceExtension *shell_surface,
-                    MetaWaylandSeat *seat)
-{
-  MetaWaylandMoveGrab *move;
-  MetaRectangle rect;
-
-  g_return_if_fail (shell_surface != NULL);
-
-  /* TODO: check if the surface is fullscreen when we support fullscreen */
-
-  move = g_slice_new (MetaWaylandMoveGrab);
-
-  meta_window_get_input_rect (shell_surface->surface->window,
-                              &rect);
-
-  move->dx = wl_fixed_from_int (rect.x) - seat->pointer.grab_x;
-  move->dy = wl_fixed_from_int (rect.y) - seat->pointer.grab_y;
-
-  grab_pointer (&move->base, &move_grab_interface, shell_surface,
-                &seat->pointer, GRAB_CURSOR_MOVE);
-}
-
-static void
 shell_surface_move (struct wl_client *client,
                     struct wl_resource *resource,
                     struct wl_resource *seat_resource,
@@ -656,13 +569,54 @@ shell_surface_move (struct wl_client *client,
 {
   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
   MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
+  MetaWindow *window;
+  MetaWaylandMoveGrab *move_grab;
+  MetaRectangle rect;
 
   if (seat->pointer.button_count == 0 ||
       seat->pointer.grab_serial != serial ||
       seat->pointer.focus != shell_surface->surface)
     return;
 
-  start_surface_move (shell_surface, seat);
+  window = shell_surface->surface->window;
+  if (!window)
+    return;
+
+  /* small hack, this should be handled by window->shaken_loose when we
+     move everything to display.c */
+  if (window->fullscreen)
+    meta_window_unmake_fullscreen (window);
+
+  move_grab = g_slice_new (MetaWaylandMoveGrab);
+
+  meta_window_get_input_rect (shell_surface->surface->window,
+                              &rect);
+
+  move_grab->generic.interface = &move_grab_interface;
+  move_grab->generic.pointer = &seat->pointer;
+
+  move_grab->surface = shell_surface->surface;
+  move_grab->surface_destroy_listener.notify = move_grab_lose_surface;
+  wl_resource_add_destroy_listener (shell_surface->surface->resource,
+                                   &move_grab->surface_destroy_listener);
+
+  move_grab->dx = wl_fixed_from_int (rect.x) - seat->pointer.grab_x;
+  move_grab->dy = wl_fixed_from_int (rect.y) - seat->pointer.grab_y;
+
+  meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)move_grab);
+
+  /* TODO: send_grab_cursor (cursor); */
+
+  /* XXX: In Weston there is a desktop shell protocol which has
+   * a set_grab_surface request that's used to specify the surface
+   * that's focused here.
+   *
+   * TODO: understand why.
+   *
+   * XXX: For now we just focus the surface directly associated with
+   * the grab.
+   */
+  meta_wayland_pointer_set_focus (&seat->pointer, shell_surface->surface);
 }
 
 static void
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 0ec28c9..6186685 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -219,9 +219,7 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
 void
 meta_wayland_compositor_repick (MetaWaylandCompositor *compositor)
 {
-  meta_wayland_seat_repick (compositor->seat,
-                            get_time (),
-                            NULL);
+  meta_wayland_seat_repick (compositor->seat, NULL);
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]