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:
parent
76e2455d1b
commit
776a86a65f
@ -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;
|
||||
|
||||
seat->drag_client = client;
|
||||
seat->drag_data_source = NULL;
|
||||
drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
|
||||
drag_grab->generic.interface = &drag_grab_interface;
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
|
||||
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;
|
||||
|
@ -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"
|
||||
@ -73,51 +74,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 = {
|
||||
@ -282,8 +311,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;
|
||||
@ -306,7 +334,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);
|
||||
@ -320,6 +351,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;
|
||||
@ -327,8 +360,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
|
||||
@ -342,8 +373,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
|
||||
@ -353,8 +383,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
|
||||
@ -386,24 +415,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)
|
||||
{
|
||||
}
|
||||
|
||||
@ -421,9 +445,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;
|
||||
@ -459,56 +481,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
|
||||
@ -517,50 +544,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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -47,31 +47,6 @@ unbind_resource (struct wl_resource *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
|
||||
pointer_unmap_sprite (MetaWaylandSeat *seat)
|
||||
{
|
||||
@ -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);
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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,58 +492,118 @@ 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
|
||||
static void
|
||||
move_grab_lose_surface (struct wl_listener *listener, void *data)
|
||||
{
|
||||
GRAB_CURSOR_MOVE,
|
||||
} GrabCursor;
|
||||
MetaWaylandMoveGrab *move_grab =
|
||||
wl_container_of (listener, move_grab, surface_destroy_listener);
|
||||
|
||||
move_grab->surface = NULL;
|
||||
end_move_grab (move_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
grab_pointer (MetaWaylandGrab *grab,
|
||||
const MetaWaylandPointerGrabInterface *interface,
|
||||
MetaWaylandSurfaceExtension *shell_surface,
|
||||
MetaWaylandPointer *pointer,
|
||||
GrabCursor cursor)
|
||||
move_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
/* 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);
|
||||
static void
|
||||
move_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandMoveGrab *move_grab = (MetaWaylandMoveGrab *)grab;
|
||||
MetaWaylandPointer *pointer = grab->pointer;
|
||||
|
||||
grab->pointer = pointer;
|
||||
grab->grab.focus = shell_surface->surface;
|
||||
meta_window_move (move_grab->surface->window,
|
||||
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); */
|
||||
|
||||
@ -557,112 +616,7 @@ grab_pointer (MetaWaylandGrab *grab,
|
||||
* 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;
|
||||
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);
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, shell_surface->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user