summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wayland/meta-wayland.c182
1 files changed, 181 insertions, 1 deletions
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index dfd5fa8fd..b35420188 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -43,6 +43,7 @@
#include "meta-window-actor-private.h"
#include "meta-wayland-seat.h"
#include "meta-wayland-keyboard.h"
+#include "meta-wayland-pointer.h"
#include "meta-wayland-data-device.h"
#include "display-private.h"
#include "window-private.h"
@@ -722,12 +723,191 @@ shell_surface_pong (struct wl_client *client,
{
}
+/* TODO: consider adding this to window.c */
+static void
+meta_window_get_surface_rect (const MetaWindow *window,
+ MetaRectangle *rect)
+{
+ if (window->frame)
+ {
+ MetaFrameBorders borders;
+ *rect = window->frame->rect;
+ meta_frame_calc_borders (window->frame, &borders);
+ }
+ else
+ *rect = window->rect;
+}
+
+typedef struct _MetaWaylandGrab
+{
+ MetaWaylandPointerGrab grab;
+ MetaWaylandShellSurface *shell_surface;
+ struct wl_listener shell_surface_destroy_listener;
+ MetaWaylandPointer *pointer;
+} MetaWaylandGrab;
+
+typedef struct _MetaWaylandMoveGrab
+{
+ MetaWaylandGrab base;
+ wl_fixed_t dx, dy;
+} MetaWaylandMoveGrab;
+
+static void
+destroy_shell_surface_grab_listener (struct wl_listener *listener,
+ void *data)
+{
+ MetaWaylandGrab *grab = wl_container_of (listener, grab,
+ shell_surface_destroy_listener);
+ grab->shell_surface = NULL;
+
+ /* 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? */
+}
+
+typedef enum _GrabCursor
+{
+ GRAB_CURSOR_MOVE,
+} GrabCursor;
+
+static void
+grab_pointer (MetaWaylandGrab *grab,
+ const MetaWaylandPointerGrabInterface *interface,
+ MetaWaylandShellSurface *shell_surface,
+ MetaWaylandPointer *pointer,
+ GrabCursor cursor)
+{
+ /* 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);
+
+ /* 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);
+}
+
+static void
+noop_grab_focus (MetaWaylandPointerGrab *grab,
+ MetaWaylandSurface *surface,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ grab->focus = NULL;
+}
+
+static void
+move_grab_motion (MetaWaylandPointerGrab *grab,
+ uint32_t time,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+ MetaWaylandMoveGrab *move = (MetaWaylandMoveGrab *)grab;
+ MetaWaylandPointer *pointer = move->base.pointer;
+ MetaWaylandShellSurface *shell_surface = move->base.shell_surface;
+
+ if (!shell_surface)
+ return;
+
+ meta_window_move (shell_surface->surface->window,
+ TRUE,
+ wl_fixed_to_int (pointer->x + move->dx),
+ wl_fixed_to_int (pointer->y + move->dy));
+}
+
+static void
+move_grab_button (MetaWaylandPointerGrab *pointer_grab,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state_w)
+{
+ MetaWaylandGrab *grab =
+ wl_container_of (pointer_grab, grab, grab);
+ MetaWaylandMoveGrab *move = (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);
+ }
+}
+
+static const MetaWaylandPointerGrabInterface move_grab_interface = {
+ noop_grab_focus,
+ move_grab_motion,
+ move_grab_button,
+};
+
+static void
+start_surface_move (MetaWaylandShellSurface *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_surface_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,
+ struct wl_resource *seat_resource,
guint32 serial)
{
+ MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
+ MetaWaylandShellSurface *shell_surface = wl_resource_get_user_data (resource);
+
+ if (seat->pointer.button_count == 0 ||
+ seat->pointer.grab_serial != serial ||
+ seat->pointer.focus != shell_surface->surface)
+ return;
+
+ start_surface_move (shell_surface, seat);
}
static void