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
This commit is contained in:
Giovanni Campagna 2013-09-11 14:06:05 +02:00
parent 76e2455d1b
commit 776a86a65f
7 changed files with 378 additions and 422 deletions

View File

@ -151,42 +151,63 @@ static struct wl_data_source_interface data_source_interface = {
data_source_destroy 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 static void
destroy_drag_focus (struct wl_listener *listener, void *data) 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 static void
drag_grab_focus (MetaWaylandPointerGrab *grab, drag_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface, MetaWaylandSurface *surface,
wl_fixed_t x, const ClutterEvent *event)
wl_fixed_t y)
{ {
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_resource *resource, *offer = NULL;
struct wl_display *display; struct wl_display *display;
guint32 serial; 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_data_device_send_leave (drag_grab->drag_focus_data_device);
wl_list_remove (&seat->drag_focus_listener.link); wl_list_remove (&drag_grab->drag_focus_listener.link);
seat->drag_focus_resource = NULL; drag_grab->drag_focus_data_device = NULL;
seat->drag_focus = NULL; drag_grab->drag_focus = NULL;
} }
if (!surface) if (!surface)
return; return;
if (!seat->drag_data_source && if (!drag_grab->drag_data_source &&
wl_resource_get_client (surface->resource) != seat->drag_client) wl_resource_get_client (surface->resource) != drag_grab->drag_client)
return; return;
resource = 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)); wl_resource_get_client (surface->resource));
if (!resource) if (!resource)
return; return;
@ -194,68 +215,73 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
display = wl_client_get_display (wl_resource_get_client (resource)); display = wl_client_get_display (wl_resource_get_client (resource));
serial = wl_display_next_serial (display); serial = wl_display_next_serial (display);
if (seat->drag_data_source) if (drag_grab->drag_data_source)
offer = meta_wayland_data_source_send_offer (seat->drag_data_source, offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
resource); resource);
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
wl_data_device_send_enter (resource, serial, surface->resource, wl_data_device_send_enter (resource, serial, surface->resource,
x, y, offer); sx, sy, offer);
seat->drag_focus = surface; drag_grab->drag_focus = surface;
seat->drag_focus_listener.notify = destroy_drag_focus;
wl_resource_add_destroy_listener (resource, &seat->drag_focus_listener); drag_grab->drag_focus_data_device = resource;
seat->drag_focus_resource = resource; drag_grab->drag_focus_listener.notify = destroy_drag_focus;
grab->focus = surface; wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener);
} }
static void static void
drag_grab_motion (MetaWaylandPointerGrab *grab, 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) if (drag_grab->drag_focus_data_device)
wl_data_device_send_motion (seat->drag_focus_resource, time, x, y); {
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 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; drag_grab->drag_surface = NULL;
wl_signal_emit (&seat->drag_icon_signal, NULL); wl_list_remove (&drag_grab->drag_icon_listener.link);
wl_list_remove (&seat->drag_icon_listener.link);
} }
drag_grab_focus (&seat->drag_grab, NULL, if (drag_grab->drag_data_source)
wl_fixed_from_int (0), wl_fixed_from_int (0)); 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; meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
seat->drag_client = NULL; g_slice_free (MetaWaylandDragGrab, drag_grab);
} }
static void static void
drag_grab_button (MetaWaylandPointerGrab *grab, drag_grab_button (MetaWaylandPointerGrab *grab,
guint32 time, guint32 button, guint32 state_w) const ClutterEvent *event)
{ {
MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab); MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
enum wl_pointer_button_state state = state_w; MetaWaylandSeat *seat = drag_grab->seat;
ClutterEventType event_type = clutter_event_type (event);
if (seat->drag_focus_resource && if (drag_grab->drag_focus_data_device &&
seat->pointer.grab_button == button && drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
state == WL_POINTER_BUTTON_STATE_RELEASED) event_type == CLUTTER_BUTTON_RELEASE)
wl_data_device_send_drop (seat->drag_focus_resource); wl_data_device_send_drop (drag_grab->drag_focus_data_device);
if (seat->pointer.button_count == 0 && if (seat->pointer.button_count == 0 &&
state == WL_POINTER_BUTTON_STATE_RELEASED) event_type == CLUTTER_BUTTON_RELEASE)
{ data_device_end_drag_grab (drag_grab);
if (seat->drag_data_source)
wl_list_remove (&seat->drag_data_source_listener.link);
data_device_end_drag_grab (seat);
}
} }
static const MetaWaylandPointerGrabInterface drag_grab_interface = { static const MetaWaylandPointerGrabInterface drag_grab_interface = {
@ -267,19 +293,20 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
static void static void
destroy_data_device_source (struct wl_listener *listener, void *data) destroy_data_device_source (struct wl_listener *listener, void *data)
{ {
MetaWaylandSeat *seat = MetaWaylandDragGrab *drag_grab =
wl_container_of (listener, seat, drag_data_source_listener); 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 static void
destroy_data_device_icon (struct wl_listener *listener, void *data) destroy_data_device_icon (struct wl_listener *listener, void *data)
{ {
MetaWaylandSeat *seat = MetaWaylandDragGrab *drag_grab =
wl_container_of (listener, seat, drag_icon_listener); wl_container_of (listener, drag_grab, drag_data_source_listener);
seat->drag_surface = NULL; drag_grab->drag_surface = NULL;
} }
static void static void
@ -290,38 +317,40 @@ data_device_start_drag (struct wl_client *client,
struct wl_resource *icon_resource, guint32 serial) struct wl_resource *icon_resource, guint32 serial)
{ {
MetaWaylandSeat *seat = wl_resource_get_user_data (resource); MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandDragGrab *drag_grab;
/* FIXME: Check that client has implicit grab on the origin /* FIXME: Check that client has implicit grab on the origin
* surface that matches the given time. */ * surface that matches the given time. */
/* FIXME: Check that the data source type array isn't empty. */ /* 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;
seat->drag_client = client; drag_grab = g_slice_new0 (MetaWaylandDragGrab);
seat->drag_data_source = NULL;
drag_grab->generic.interface = &drag_grab_interface;
drag_grab->generic.pointer = &seat->pointer;
drag_grab->drag_client = client;
if (source_resource) if (source_resource)
{ {
seat->drag_data_source = wl_resource_get_user_data (source_resource); drag_grab->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_listener.notify = destroy_data_device_source;
wl_resource_add_destroy_listener (source_resource, wl_resource_add_destroy_listener (source_resource,
&seat->drag_data_source_listener); &drag_grab->drag_data_source_listener);
} }
if (icon_resource) if (icon_resource)
{ {
seat->drag_surface = wl_resource_get_user_data (icon_resource); drag_grab->drag_surface = wl_resource_get_user_data (icon_resource);
seat->drag_icon_listener.notify = destroy_data_device_icon; drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
wl_resource_add_destroy_listener (icon_resource, wl_resource_add_destroy_listener (icon_resource,
&seat->drag_icon_listener); &drag_grab->drag_icon_listener);
wl_signal_emit (&seat->drag_icon_signal, icon_resource);
} }
meta_wayland_pointer_set_focus (&seat->pointer, NULL, meta_wayland_pointer_set_focus (&seat->pointer, NULL);
wl_fixed_from_int (0), meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
wl_fixed_from_int (0));
meta_wayland_pointer_start_grab (&seat->pointer, &seat->drag_grab);
} }
static void static void
@ -339,7 +368,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
if (focus) if (focus)
{ {
data_device = 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)); wl_resource_get_client (focus));
if (data_device) if (data_device)
wl_data_device_send_selection (data_device, NULL); wl_data_device_send_selection (data_device, NULL);
@ -375,7 +404,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
if (focus) if (focus)
{ {
data_device = 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)); wl_resource_get_client (focus));
if (data_device && source) if (data_device && source)
{ {
@ -497,7 +526,7 @@ get_data_device (struct wl_client *client,
MIN (META_WL_DATA_DEVICE_VERSION, MIN (META_WL_DATA_DEVICE_VERSION,
wl_resource_get_version (manager_resource)), id); wl_resource_get_version (manager_resource)), id);
wl_resource_set_implementation (resource, &data_device_interface, seat, unbind_data_device); 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 = { 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) if (!focus)
return; 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)); wl_resource_get_client (focus));
if (!data_device) if (!data_device)
return; return;

View File

@ -45,6 +45,7 @@
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <clutter/evdev/clutter-evdev.h> #include <clutter/evdev/clutter-evdev.h>
#include <linux/input.h>
#include "meta-wayland-pointer.h" #include "meta-wayland-pointer.h"
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
@ -74,50 +75,78 @@ lose_pointer_focus (struct wl_listener *listener, void *data)
static void static void
default_grab_focus (MetaWaylandPointerGrab *grab, default_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface, MetaWaylandSurface *surface,
wl_fixed_t x, const ClutterEvent *event)
wl_fixed_t y)
{ {
MetaWaylandPointer *pointer = grab->pointer; MetaWaylandPointer *pointer = grab->pointer;
if (pointer->button_count > 0) if (pointer->button_count > 0)
return; return;
meta_wayland_pointer_set_focus (pointer, surface, x, y); meta_wayland_pointer_set_focus (pointer, surface);
} }
static void static void
default_grab_motion (MetaWaylandPointerGrab *grab, default_grab_motion (MetaWaylandPointerGrab *grab,
uint32_t time, wl_fixed_t x, wl_fixed_t y) const ClutterEvent *event)
{ {
struct wl_resource *resource; struct wl_resource *resource;
resource = grab->pointer->focus_resource; resource = grab->pointer->focus_resource;
if (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 static void
default_grab_button (MetaWaylandPointerGrab *grab, default_grab_button (MetaWaylandPointerGrab *grab,
uint32_t time, uint32_t button, uint32_t state_w) const ClutterEvent *event)
{ {
MetaWaylandPointer *pointer = grab->pointer; MetaWaylandPointer *pointer = grab->pointer;
struct wl_resource *resource; struct wl_resource *resource;
uint32_t serial; ClutterEventType event_type;
enum wl_pointer_button_state state = state_w;
event_type = clutter_event_type (event);
resource = pointer->focus_resource; resource = pointer->focus_resource;
if (resource) if (resource)
{ {
struct wl_client *client = wl_resource_get_client (resource); struct wl_client *client = wl_resource_get_client (resource);
struct wl_display *display = wl_client_get_display (client); struct wl_display *display = wl_client_get_display (client);
serial = wl_display_next_serial (display); uint32_t button;
pointer->click_serial = serial; uint32_t serial;
wl_pointer_send_button (resource, serial, time, button, state_w);
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;
} }
if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED) serial = wl_display_next_serial (display);
meta_wayland_pointer_set_focus (pointer, pointer->current, wl_pointer_send_button (resource, serial,
pointer->current_x, pointer->current_y); clutter_event_get_time (event), button,
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
}
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 = { static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
@ -282,8 +311,7 @@ find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface)
void void
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface, MetaWaylandSurface *surface)
wl_fixed_t sx, wl_fixed_t sy)
{ {
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
MetaWaylandKeyboard *kbd = &seat->keyboard; MetaWaylandKeyboard *kbd = &seat->keyboard;
@ -306,7 +334,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
{ {
struct wl_client *client = wl_resource_get_client (resource); struct wl_client *client = wl_resource_get_client (resource);
struct wl_display *display = wl_client_get_display (client); struct wl_display *display = wl_client_get_display (client);
wl_fixed_t sx, sy;
serial = wl_display_next_serial (display); serial = wl_display_next_serial (display);
if (kbd) if (kbd)
{ {
kr = find_resource_for_surface (&kbd->resource_list, surface); kr = find_resource_for_surface (&kbd->resource_list, surface);
@ -320,6 +351,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
kbd->modifier_state.group); 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_pointer_send_enter (resource, serial, surface->resource, sx, sy);
wl_resource_add_destroy_listener (resource, &pointer->focus_listener); wl_resource_add_destroy_listener (resource, &pointer->focus_listener);
pointer->focus_serial = serial; pointer->focus_serial = serial;
@ -327,8 +360,6 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
pointer->focus_resource = resource; pointer->focus_resource = resource;
pointer->focus = surface; pointer->focus = surface;
pointer->default_grab.focus = surface;
wl_signal_emit (&pointer->focus_signal, pointer);
} }
void void
@ -342,8 +373,7 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
grab->pointer = pointer; grab->pointer = pointer;
if (pointer->current) if (pointer->current)
interface->focus (pointer->grab, pointer->current, interface->focus (pointer->grab, pointer->current, NULL);
pointer->current_x, pointer->current_y);
} }
void void
@ -353,8 +383,7 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
pointer->grab = &pointer->default_grab; pointer->grab = &pointer->default_grab;
interface = pointer->grab->interface; interface = pointer->grab->interface;
interface->focus (pointer->grab, pointer->current, interface->focus (pointer->grab, pointer->current, NULL);
pointer->current_x, pointer->current_y);
} }
static void static void
@ -386,24 +415,19 @@ meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
static void static void
modal_focus (MetaWaylandPointerGrab *grab, modal_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface, MetaWaylandSurface *surface,
wl_fixed_t x, const ClutterEvent *event)
wl_fixed_t y)
{ {
} }
static void static void
modal_motion (MetaWaylandPointerGrab *grab, modal_motion (MetaWaylandPointerGrab *grab,
uint32_t time, const ClutterEvent *event)
wl_fixed_t x,
wl_fixed_t y)
{ {
} }
static void static void
modal_button (MetaWaylandPointerGrab *grab, modal_button (MetaWaylandPointerGrab *grab,
uint32_t time, const ClutterEvent *event)
uint32_t button,
uint32_t state)
{ {
} }
@ -421,9 +445,7 @@ meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
if (pointer->grab != &pointer->default_grab) if (pointer->grab != &pointer->default_grab)
return FALSE; return FALSE;
meta_wayland_pointer_set_focus (pointer, NULL, meta_wayland_pointer_set_focus (pointer, NULL);
wl_fixed_from_int (0),
wl_fixed_from_int (0));
grab = g_slice_new0 (MetaWaylandPointerGrab); grab = g_slice_new0 (MetaWaylandPointerGrab);
grab->interface = &modal_grab; grab->interface = &modal_grab;
@ -459,56 +481,61 @@ meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer)
we have button down, and the clients would be confused if the we have button down, and the clients would be confused if the
pointer enters the surface. 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 static void
popup_grab_focus (MetaWaylandPointerGrab *grab, popup_grab_focus (MetaWaylandPointerGrab *grab,
MetaWaylandSurface *surface, MetaWaylandSurface *surface,
wl_fixed_t x, const ClutterEvent *event)
wl_fixed_t y)
{ {
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
/* Popup grabs are in owner-events mode (ie, events for the same client /* Popup grabs are in owner-events mode (ie, events for the same client
are reported as normal) */ are reported as normal) */
if (wl_resource_get_client (surface->resource) == if (wl_resource_get_client (surface->resource) ==
wl_resource_get_client (grab->focus->resource)) wl_resource_get_client (popup_grab->popup->resource))
default_grab_focus (grab, surface, x, y); default_grab_focus (grab, surface, event);
else else
meta_wayland_pointer_set_focus (grab->pointer, NULL, 0, 0); meta_wayland_pointer_set_focus (grab->pointer, NULL);
} }
static void static void
popup_grab_motion (MetaWaylandPointerGrab *grab, popup_grab_motion (MetaWaylandPointerGrab *grab,
uint32_t time, const ClutterEvent *event)
wl_fixed_t x,
wl_fixed_t y)
{ {
default_grab_motion (grab, time, x, y); default_grab_motion (grab, event);
} }
static void static void
popup_grab_button (MetaWaylandPointerGrab *grab, popup_grab_button (MetaWaylandPointerGrab *grab,
uint32_t time, const ClutterEvent *event)
uint32_t button,
uint32_t state)
{ {
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
MetaWaylandPointer *pointer = grab->pointer; MetaWaylandPointer *pointer = grab->pointer;
if (pointer->focus_resource) if (pointer->focus_resource)
{ {
/* This is ensured by popup_grab_focus */ /* This is ensured by popup_grab_focus */
g_assert (wl_resource_get_client (pointer->focus_resource) == 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) pointer->button_count == 0)
meta_wayland_pointer_end_popup_grab (grab->pointer); meta_wayland_pointer_end_popup_grab (grab->pointer);
} }
static MetaWaylandPointerGrabInterface popup_grab = { static MetaWaylandPointerGrabInterface popup_grab_interface = {
popup_grab_focus, popup_grab_focus,
popup_grab_motion, popup_grab_motion,
popup_grab_button popup_grab_button
@ -517,50 +544,75 @@ static MetaWaylandPointerGrabInterface popup_grab = {
static void static void
meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer) 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_shell_surface_send_popup_done (popup_grab->popup->shell_surface->resource);
wl_list_remove (&grab->focus_destroy_listener.link); wl_list_remove (&popup_grab->popup_destroy_listener.link);
} }
meta_wayland_pointer_end_grab (pointer); meta_wayland_pointer_end_grab (pointer);
g_slice_free (MetaWaylandPointerGrab, grab); g_slice_free (MetaWaylandPopupGrab, popup_grab);
} }
static void static void
on_popup_surface_destroy (struct wl_listener *listener, on_popup_surface_destroy (struct wl_listener *listener,
void *data) void *data)
{ {
MetaWaylandPointerGrab *grab = MetaWaylandPopupGrab *grab =
wl_container_of (listener, grab, focus_destroy_listener); wl_container_of (listener, grab, popup_destroy_listener);
grab->focus = NULL; grab->popup = NULL;
meta_wayland_pointer_end_popup_grab (grab->pointer); meta_wayland_pointer_end_popup_grab (grab->generic.pointer);
} }
gboolean gboolean
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface) 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; return FALSE;
grab = g_slice_new0 (MetaWaylandPointerGrab); grab = g_slice_new0 (MetaWaylandPopupGrab);
grab->interface = &popup_grab; grab->generic.interface = &popup_grab_interface;
grab->pointer = pointer; grab->generic.pointer = pointer;
grab->focus = surface; grab->popup = surface;
grab->focus_destroy_listener.notify = on_popup_surface_destroy; grab->popup_destroy_listener.notify = on_popup_surface_destroy;
wl_resource_add_destroy_listener (surface->resource, &grab->focus_destroy_listener); 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; 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);
}

View File

@ -28,22 +28,19 @@
struct _MetaWaylandPointerGrabInterface struct _MetaWaylandPointerGrabInterface
{ {
void (*focus) (MetaWaylandPointerGrab * grab, void (*focus) (MetaWaylandPointerGrab *grab,
MetaWaylandSurface * surface, wl_fixed_t x, wl_fixed_t y); MetaWaylandSurface *surface,
void (*motion) (MetaWaylandPointerGrab * grab, const ClutterEvent *event);
uint32_t time, wl_fixed_t x, wl_fixed_t y); void (*motion) (MetaWaylandPointerGrab *grab,
void (*button) (MetaWaylandPointerGrab * grab, const ClutterEvent *event);
uint32_t time, uint32_t button, uint32_t state); void (*button) (MetaWaylandPointerGrab *grab,
const ClutterEvent *event);
}; };
struct _MetaWaylandPointerGrab struct _MetaWaylandPointerGrab
{ {
const MetaWaylandPointerGrabInterface *interface; const MetaWaylandPointerGrabInterface *interface;
MetaWaylandPointer *pointer; MetaWaylandPointer *pointer;
MetaWaylandSurface *focus;
wl_fixed_t x, y;
struct wl_listener focus_destroy_listener;
}; };
struct _MetaWaylandPointer struct _MetaWaylandPointer
@ -59,6 +56,7 @@ struct _MetaWaylandPointer
MetaWaylandPointerGrab *grab; MetaWaylandPointerGrab *grab;
MetaWaylandPointerGrab default_grab; MetaWaylandPointerGrab default_grab;
wl_fixed_t grab_x, grab_y; wl_fixed_t grab_x, grab_y;
wl_fixed_t focus_x, focus_y;
guint32 grab_button; guint32 grab_button;
guint32 grab_serial; guint32 grab_serial;
guint32 grab_time; guint32 grab_time;
@ -80,10 +78,7 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer);
void void
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface, MetaWaylandSurface *surface);
wl_fixed_t sx,
wl_fixed_t sy);
void void
meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer); meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer);
@ -107,4 +102,10 @@ void
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface); 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__ */ #endif /* __META_WAYLAND_POINTER_H__ */

View File

@ -47,31 +47,6 @@ unbind_resource (struct wl_resource *resource)
wl_list_remove (wl_resource_get_link (resource)); wl_list_remove (wl_resource_get_link (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 static void
pointer_unmap_sprite (MetaWaylandSeat *seat) pointer_unmap_sprite (MetaWaylandSeat *seat)
{ {
@ -173,19 +148,7 @@ seat_get_pointer (struct wl_client *client,
if (seat->pointer.focus && if (seat->pointer.focus &&
wl_resource_get_client (seat->pointer.focus->resource) == client) wl_resource_get_client (seat->pointer.focus->resource) == client)
{ meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus);
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);
}
} }
static void static void
@ -209,8 +172,7 @@ seat_get_keyboard (struct wl_client *client,
if (seat->keyboard.focus && if (seat->keyboard.focus &&
wl_resource_get_client (seat->keyboard.focus->resource) == client) wl_resource_get_client (seat->keyboard.focus->resource) == client)
{ {
meta_wayland_keyboard_set_focus (&seat->keyboard, meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus);
seat->keyboard.focus);
meta_wayland_data_device_set_keyboard_focus (seat); 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; seat->selection_data_source = NULL;
wl_list_init (&seat->base_resource_list); wl_list_init (&seat->base_resource_list);
wl_signal_init (&seat->selection_signal); wl_signal_init (&seat->selection_signal);
wl_list_init (&seat->drag_resource_list); wl_list_init (&seat->data_device_resource_list);
wl_signal_init (&seat->drag_icon_signal);
meta_wayland_pointer_init (&seat->pointer, is_native); meta_wayland_pointer_init (&seat->pointer, is_native);
@ -305,61 +266,40 @@ notify_motion (MetaWaylandSeat *seat,
pointer->x = wl_fixed_from_double (x); pointer->x = wl_fixed_from_double (x);
pointer->y = wl_fixed_from_double (y); pointer->y = wl_fixed_from_double (y);
meta_wayland_seat_repick (seat, meta_wayland_seat_repick (seat, event);
clutter_event_get_time (event),
clutter_event_get_source (event));
pointer->grab->interface->motion (pointer->grab, pointer->grab->interface->motion (pointer->grab, event);
clutter_event_get_time (event),
pointer->grab->x,
pointer->grab->y);
} }
static void static void
handle_motion_event (MetaWaylandSeat *seat, handle_motion_event (MetaWaylandSeat *seat,
const ClutterMotionEvent *event) const ClutterEvent *event)
{ {
notify_motion (seat, (const ClutterEvent *) event); notify_motion (seat, event);
} }
static void static void
handle_button_event (MetaWaylandSeat *seat, handle_button_event (MetaWaylandSeat *seat,
const ClutterButtonEvent *event) const ClutterEvent *event)
{ {
MetaWaylandPointer *pointer = &seat->pointer; MetaWaylandPointer *pointer = &seat->pointer;
gboolean state = event->type == CLUTTER_BUTTON_PRESS; gboolean state = event->type == CLUTTER_BUTTON_PRESS;
uint32_t button; uint32_t button;
MetaWaylandSurface *surface;
notify_motion (seat, (const ClutterEvent *) event); notify_motion (seat, 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;
}
/* FIXME: synth a XI2 event and handle in display.c */
if (state && pointer->button_count == 1) if (state && pointer->button_count == 1)
{ {
MetaWaylandSurface *surface = pointer->current; button = clutter_event_get_button (event);
pointer->grab_button = button; pointer->grab_button = button;
pointer->grab_time = event->time; pointer->grab_time = clutter_event_get_time (event);
pointer->grab_x = pointer->x; pointer->grab_x = pointer->x;
pointer->grab_y = pointer->y; 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 &&
surface->window && surface->window &&
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
@ -368,7 +308,7 @@ 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) if (pointer->button_count == 1)
pointer->grab_serial = wl_display_get_serial (seat->display); pointer->grab_serial = wl_display_get_serial (seat->display);
@ -376,14 +316,14 @@ handle_button_event (MetaWaylandSeat *seat,
static void static void
handle_scroll_event (MetaWaylandSeat *seat, handle_scroll_event (MetaWaylandSeat *seat,
const ClutterScrollEvent *event) const ClutterEvent *event)
{ {
enum wl_pointer_axis axis; enum wl_pointer_axis axis;
wl_fixed_t value; 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: case CLUTTER_SCROLL_UP:
axis = WL_POINTER_AXIS_VERTICAL_SCROLL; axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
@ -411,7 +351,7 @@ handle_scroll_event (MetaWaylandSeat *seat,
if (seat->pointer.focus_resource) if (seat->pointer.focus_resource)
wl_pointer_send_axis (seat->pointer.focus_resource, wl_pointer_send_axis (seat->pointer.focus_resource,
event->time, clutter_event_get_time (event),
axis, axis,
value); value);
} }
@ -447,14 +387,12 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
switch (event->type) switch (event->type)
{ {
case CLUTTER_MOTION: case CLUTTER_MOTION:
handle_motion_event (seat, handle_motion_event (seat, event);
(const ClutterMotionEvent *) event);
break; break;
case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE: case CLUTTER_BUTTON_RELEASE:
handle_button_event (seat, handle_button_event (seat, event);
(const ClutterButtonEvent *) event);
break; break;
case CLUTTER_KEY_PRESS: case CLUTTER_KEY_PRESS:
@ -463,7 +401,7 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
(const ClutterKeyEvent *) event); (const ClutterKeyEvent *) event);
case CLUTTER_SCROLL: case CLUTTER_SCROLL:
handle_scroll_event (seat, (const ClutterScrollEvent *) event); handle_scroll_event (seat, event);
break; break;
default: default:
@ -494,13 +432,17 @@ update_pointer_position_for_actor (MetaWaylandPointer *pointer,
redundantly doing another one */ redundantly doing another one */
void void
meta_wayland_seat_repick (MetaWaylandSeat *seat, meta_wayland_seat_repick (MetaWaylandSeat *seat,
uint32_t time, const ClutterEvent *for_event)
ClutterActor *actor)
{ {
ClutterActor *actor = NULL;
MetaWaylandPointer *pointer = &seat->pointer; MetaWaylandPointer *pointer = &seat->pointer;
MetaWaylandSurface *surface = NULL; 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); ClutterStage *stage = CLUTTER_STAGE (seat->current_stage);
actor = clutter_stage_get_actor_at_pos (stage, actor = clutter_stage_get_actor_at_pos (stage,
@ -538,16 +480,8 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
const MetaWaylandPointerGrabInterface *interface = const MetaWaylandPointerGrabInterface *interface =
pointer->grab->interface; pointer->grab->interface;
interface->focus (pointer->grab, interface->focus (pointer->grab,
surface, surface, for_event);
pointer->current_x, pointer->current_y);
} }
if (pointer->grab->focus)
transform_stage_point_fixed (pointer->grab->focus,
pointer->x,
pointer->y,
&pointer->grab->x,
&pointer->grab->y);
} }
void void

View File

@ -61,18 +61,7 @@ struct _MetaWaylandSeat
struct wl_listener selection_data_source_listener; struct wl_listener selection_data_source_listener;
struct wl_signal selection_signal; struct wl_signal selection_signal;
struct wl_list drag_resource_list; struct wl_list data_device_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;
MetaWaylandPointer pointer; MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard; MetaWaylandKeyboard keyboard;
@ -96,8 +85,7 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
void void
meta_wayland_seat_repick (MetaWaylandSeat *seat, meta_wayland_seat_repick (MetaWaylandSeat *seat,
uint32_t time, const ClutterEvent *for_event);
ClutterActor *actor);
void void
meta_wayland_seat_update_sprite (MetaWaylandSeat *seat); meta_wayland_seat_update_sprite (MetaWaylandSeat *seat);

View File

@ -407,7 +407,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
meta_wayland_pointer_destroy_focus (&compositor->seat->pointer); meta_wayland_pointer_destroy_focus (&compositor->seat->pointer);
g_assert (surface != compositor->seat->pointer.focus); g_assert (surface != compositor->seat->pointer.focus);
g_assert (surface != compositor->seat->pointer.grab->focus);
} }
if (compositor->implicit_grab_surface == surface) if (compositor->implicit_grab_surface == surface)
@ -493,58 +492,118 @@ shell_surface_pong (struct wl_client *client,
{ {
} }
typedef struct _MetaWaylandGrab typedef struct
{ {
MetaWaylandPointerGrab grab; MetaWaylandPointerGrab generic;
MetaWaylandSurfaceExtension *shell_surface; MetaWaylandSurface *surface;
struct wl_listener shell_surface_destroy_listener; struct wl_listener surface_destroy_listener;
MetaWaylandPointer *pointer;
} MetaWaylandGrab;
typedef struct _MetaWaylandMoveGrab
{
MetaWaylandGrab base;
wl_fixed_t dx, dy; wl_fixed_t dx, dy;
} MetaWaylandMoveGrab; } MetaWaylandMoveGrab;
static void static void
destroy_shell_surface_grab_listener (struct wl_listener *listener, end_move_grab (MetaWaylandMoveGrab *move_grab)
void *data)
{ {
MetaWaylandGrab *grab = wl_container_of (listener, grab, if (move_grab->surface)
shell_surface_destroy_listener); {
grab->shell_surface = NULL; 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 meta_wayland_pointer_end_grab (move_grab->generic.pointer);
* to consider grab->shell_surface becoming NULL in grab interface g_slice_free (MetaWaylandMoveGrab, move_grab);
* callbacks? */
} }
typedef enum _GrabCursor static void
move_grab_lose_surface (struct wl_listener *listener, void *data)
{ {
GRAB_CURSOR_MOVE, MetaWaylandMoveGrab *move_grab =
} GrabCursor; wl_container_of (listener, move_grab, surface_destroy_listener);
move_grab->surface = NULL;
end_move_grab (move_grab);
}
static void static void
grab_pointer (MetaWaylandGrab *grab, move_grab_focus (MetaWaylandPointerGrab *grab,
const MetaWaylandPointerGrabInterface *interface, MetaWaylandSurface *surface,
MetaWaylandSurfaceExtension *shell_surface, const ClutterEvent *event)
MetaWaylandPointer *pointer,
GrabCursor cursor)
{ {
/* TODO: popup_grab_end (pointer); */ }
grab->grab.interface = interface; static void
grab->shell_surface = shell_surface; move_grab_motion (MetaWaylandPointerGrab *grab,
grab->shell_surface_destroy_listener.notify = const ClutterEvent *event)
destroy_shell_surface_grab_listener; {
wl_resource_add_destroy_listener (shell_surface->resource, MetaWaylandMoveGrab *move_grab = (MetaWaylandMoveGrab *)grab;
&grab->shell_surface_destroy_listener); MetaWaylandPointer *pointer = grab->pointer;
grab->pointer = pointer; meta_window_move (move_grab->surface->window,
grab->grab.focus = shell_surface->surface; TRUE,
wl_fixed_to_int (pointer->x + move_grab->dx),
wl_fixed_to_int (pointer->y + move_grab->dy));
}
meta_wayland_pointer_start_grab (pointer, &grab->grab); static void
move_grab_button (MetaWaylandPointerGrab *grab,
const ClutterEvent *event)
{
MetaWaylandMoveGrab *move_grab = (MetaWaylandMoveGrab *)grab;
MetaWaylandPointer *pointer = grab->pointer;
if (pointer->button_count == 0 &&
clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)
end_move_grab (move_grab);
}
static const MetaWaylandPointerGrabInterface move_grab_interface = {
move_grab_focus,
move_grab_motion,
move_grab_button,
};
static void
shell_surface_move (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
guint32 serial)
{
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;
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); */ /* TODO: send_grab_cursor (cursor); */
@ -557,112 +616,7 @@ grab_pointer (MetaWaylandGrab *grab,
* XXX: For now we just focus the surface directly associated with * XXX: For now we just focus the surface directly associated with
* the grab. * the grab.
*/ */
meta_wayland_pointer_set_focus (pointer, meta_wayland_pointer_set_focus (&seat->pointer, shell_surface->surface);
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;
MetaWaylandSurfaceExtension *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 (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,
guint32 serial)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurfaceExtension *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 static void

View File

@ -219,9 +219,7 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
void void
meta_wayland_compositor_repick (MetaWaylandCompositor *compositor) meta_wayland_compositor_repick (MetaWaylandCompositor *compositor)
{ {
meta_wayland_seat_repick (compositor->seat, meta_wayland_seat_repick (compositor->seat, NULL);
get_time (),
NULL);
} }
static void static void