From 776a86a65f6898840bacc90d096febe49696d4a2 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Wed, 11 Sep 2013 14:06:05 +0200 Subject: [PATCH] wayland: heavily refactor pointer grabs Grabs are now slice allocated structures that are handled by whoever starts the grab. They contain a generic grab structure with the interface and a backpointer to the MetaWaylandPointer. The grab interface has been changed to pass full clutter events, which allowed to remove the confusion between grab->focus and pointer->focus. Invidual grabs are now required to keep their focus, and choose whoever gets the events. https://bugzilla.gnome.org/show_bug.cgi?id=707863 --- src/wayland/meta-wayland-data-device.c | 177 ++++++++++-------- src/wayland/meta-wayland-pointer.c | 192 +++++++++++++------- src/wayland/meta-wayland-pointer.h | 29 +-- src/wayland/meta-wayland-seat.c | 138 ++++---------- src/wayland/meta-wayland-seat.h | 18 +- src/wayland/meta-wayland-surface.c | 242 ++++++++++--------------- src/wayland/meta-wayland.c | 4 +- 7 files changed, 378 insertions(+), 422 deletions(-) diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 38d3def0e..b9bb21c68 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -151,42 +151,63 @@ static struct wl_data_source_interface data_source_interface = { data_source_destroy }; +typedef struct { + MetaWaylandPointerGrab generic; + + MetaWaylandSeat *seat; + struct wl_client *drag_client; + + MetaWaylandSurface *drag_focus; + struct wl_resource *drag_focus_data_device; + struct wl_listener drag_focus_listener; + + MetaWaylandSurface *drag_surface; + struct wl_listener drag_icon_listener; + + MetaWaylandDataSource *drag_data_source; + struct wl_listener drag_data_source_listener; +} MetaWaylandDragGrab; + static void destroy_drag_focus (struct wl_listener *listener, void *data) { - MetaWaylandSeat *seat = wl_container_of (listener, seat, drag_focus_listener); + MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener); - seat->drag_focus_resource = NULL; + grab->drag_focus_data_device = NULL; } static void drag_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface, - wl_fixed_t x, - wl_fixed_t y) + MetaWaylandSurface *surface, + const ClutterEvent *event) { - MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab); + MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; + MetaWaylandSeat *seat = drag_grab->seat; struct wl_resource *resource, *offer = NULL; struct wl_display *display; guint32 serial; + wl_fixed_t sx, sy; - if (seat->drag_focus_resource) + if (drag_grab->drag_focus == surface) + return; + + if (drag_grab->drag_focus_data_device) { - wl_data_device_send_leave (seat->drag_focus_resource); - wl_list_remove (&seat->drag_focus_listener.link); - seat->drag_focus_resource = NULL; - seat->drag_focus = NULL; + wl_data_device_send_leave (drag_grab->drag_focus_data_device); + wl_list_remove (&drag_grab->drag_focus_listener.link); + drag_grab->drag_focus_data_device = NULL; + drag_grab->drag_focus = NULL; } if (!surface) return; - if (!seat->drag_data_source && - wl_resource_get_client (surface->resource) != seat->drag_client) + if (!drag_grab->drag_data_source && + wl_resource_get_client (surface->resource) != drag_grab->drag_client) return; resource = - wl_resource_find_for_client (&seat->drag_resource_list, + wl_resource_find_for_client (&seat->data_device_resource_list, wl_resource_get_client (surface->resource)); if (!resource) return; @@ -194,68 +215,73 @@ drag_grab_focus (MetaWaylandPointerGrab *grab, display = wl_client_get_display (wl_resource_get_client (resource)); serial = wl_display_next_serial (display); - if (seat->drag_data_source) - offer = meta_wayland_data_source_send_offer (seat->drag_data_source, + if (drag_grab->drag_data_source) + offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source, resource); + meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy); wl_data_device_send_enter (resource, serial, surface->resource, - x, y, offer); + sx, sy, offer); - seat->drag_focus = surface; - seat->drag_focus_listener.notify = destroy_drag_focus; - wl_resource_add_destroy_listener (resource, &seat->drag_focus_listener); - seat->drag_focus_resource = resource; - grab->focus = surface; + drag_grab->drag_focus = surface; + + drag_grab->drag_focus_data_device = resource; + drag_grab->drag_focus_listener.notify = destroy_drag_focus; + wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener); } static void drag_grab_motion (MetaWaylandPointerGrab *grab, - guint32 time, wl_fixed_t x, wl_fixed_t y) + const ClutterEvent *event) { - MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab); + MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; + wl_fixed_t sx, sy; - if (seat->drag_focus_resource) - wl_data_device_send_motion (seat->drag_focus_resource, time, x, y); + if (drag_grab->drag_focus_data_device) + { + meta_wayland_pointer_get_relative_coordinates (grab->pointer, + drag_grab->drag_focus, + &sx, &sy); + wl_data_device_send_motion (drag_grab->drag_focus_data_device, + clutter_event_get_time (event), + sx, sy); + } } static void -data_device_end_drag_grab (MetaWaylandSeat *seat) +data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) { - if (seat->drag_surface) + if (drag_grab->drag_surface) { - seat->drag_surface = NULL; - wl_signal_emit (&seat->drag_icon_signal, NULL); - wl_list_remove (&seat->drag_icon_listener.link); + drag_grab->drag_surface = NULL; + wl_list_remove (&drag_grab->drag_icon_listener.link); } - drag_grab_focus (&seat->drag_grab, NULL, - wl_fixed_from_int (0), wl_fixed_from_int (0)); + if (drag_grab->drag_data_source) + wl_list_remove (&drag_grab->drag_data_source_listener.link); - meta_wayland_pointer_end_grab (&seat->pointer); + drag_grab_focus (&drag_grab->generic, NULL, NULL); - seat->drag_data_source = NULL; - seat->drag_client = NULL; + meta_wayland_pointer_end_grab (drag_grab->generic.pointer); + g_slice_free (MetaWaylandDragGrab, drag_grab); } static void drag_grab_button (MetaWaylandPointerGrab *grab, - guint32 time, guint32 button, guint32 state_w) + const ClutterEvent *event) { - MetaWaylandSeat *seat = wl_container_of (grab, seat, drag_grab); - enum wl_pointer_button_state state = state_w; + MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; + MetaWaylandSeat *seat = drag_grab->seat; + ClutterEventType event_type = clutter_event_type (event); - if (seat->drag_focus_resource && - seat->pointer.grab_button == button && - state == WL_POINTER_BUTTON_STATE_RELEASED) - wl_data_device_send_drop (seat->drag_focus_resource); + if (drag_grab->drag_focus_data_device && + drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) && + event_type == CLUTTER_BUTTON_RELEASE) + wl_data_device_send_drop (drag_grab->drag_focus_data_device); if (seat->pointer.button_count == 0 && - state == WL_POINTER_BUTTON_STATE_RELEASED) - { - if (seat->drag_data_source) - wl_list_remove (&seat->drag_data_source_listener.link); - data_device_end_drag_grab (seat); - } + event_type == CLUTTER_BUTTON_RELEASE) + data_device_end_drag_grab (drag_grab); } static const MetaWaylandPointerGrabInterface drag_grab_interface = { @@ -267,19 +293,20 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = { static void destroy_data_device_source (struct wl_listener *listener, void *data) { - MetaWaylandSeat *seat = - wl_container_of (listener, seat, drag_data_source_listener); + MetaWaylandDragGrab *drag_grab = + wl_container_of (listener, drag_grab, drag_data_source_listener); - data_device_end_drag_grab (seat); + drag_grab->drag_data_source = NULL; + data_device_end_drag_grab (drag_grab); } static void destroy_data_device_icon (struct wl_listener *listener, void *data) { - MetaWaylandSeat *seat = - wl_container_of (listener, seat, drag_icon_listener); + MetaWaylandDragGrab *drag_grab = + wl_container_of (listener, drag_grab, drag_data_source_listener); - seat->drag_surface = NULL; + drag_grab->drag_surface = NULL; } static void @@ -290,38 +317,40 @@ data_device_start_drag (struct wl_client *client, struct wl_resource *icon_resource, guint32 serial) { MetaWaylandSeat *seat = wl_resource_get_user_data (resource); - + MetaWaylandDragGrab *drag_grab; /* FIXME: Check that client has implicit grab on the origin * surface that matches the given time. */ /* FIXME: Check that the data source type array isn't empty. */ - seat->drag_grab.interface = &drag_grab_interface; + if (seat->pointer.grab != &seat->pointer.default_grab) + return; - 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; diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index a8b67e9c0..28a2e7bc0 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -45,6 +45,7 @@ #include #include +#include #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); +} diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index bba28d023..d355d2993 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -28,22 +28,19 @@ struct _MetaWaylandPointerGrabInterface { - void (*focus) (MetaWaylandPointerGrab * grab, - MetaWaylandSurface * surface, wl_fixed_t x, wl_fixed_t y); - void (*motion) (MetaWaylandPointerGrab * grab, - uint32_t time, wl_fixed_t x, wl_fixed_t y); - void (*button) (MetaWaylandPointerGrab * grab, - uint32_t time, uint32_t button, uint32_t state); + void (*focus) (MetaWaylandPointerGrab *grab, + MetaWaylandSurface *surface, + const ClutterEvent *event); + void (*motion) (MetaWaylandPointerGrab *grab, + const ClutterEvent *event); + void (*button) (MetaWaylandPointerGrab *grab, + const ClutterEvent *event); }; struct _MetaWaylandPointerGrab { const MetaWaylandPointerGrabInterface *interface; MetaWaylandPointer *pointer; - MetaWaylandSurface *focus; - wl_fixed_t x, y; - - struct wl_listener focus_destroy_listener; }; struct _MetaWaylandPointer @@ -59,6 +56,7 @@ struct _MetaWaylandPointer MetaWaylandPointerGrab *grab; MetaWaylandPointerGrab default_grab; wl_fixed_t grab_x, grab_y; + wl_fixed_t focus_x, focus_y; guint32 grab_button; guint32 grab_serial; guint32 grab_time; @@ -80,10 +78,7 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer); void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - wl_fixed_t sx, - wl_fixed_t sy); - + MetaWaylandSurface *surface); void meta_wayland_pointer_destroy_focus (MetaWaylandPointer *pointer); @@ -107,4 +102,10 @@ void meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, MetaWaylandSurface *surface); +void +meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, + MetaWaylandSurface *surface, + wl_fixed_t *x, + wl_fixed_t *y); + #endif /* __META_WAYLAND_POINTER_H__ */ diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index a55071e3b..e4678d55a 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -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 diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h index 09b9d7093..3c968ef9c 100644 --- a/src/wayland/meta-wayland-seat.h +++ b/src/wayland/meta-wayland-seat.h @@ -61,18 +61,7 @@ struct _MetaWaylandSeat struct wl_listener selection_data_source_listener; struct wl_signal selection_signal; - struct wl_list drag_resource_list; - struct wl_client *drag_client; - MetaWaylandDataSource *drag_data_source; - struct wl_listener drag_data_source_listener; - MetaWaylandSurface *drag_focus; - struct wl_resource *drag_focus_resource; - struct wl_listener drag_focus_listener; - MetaWaylandPointerGrab drag_grab; - MetaWaylandSurface *drag_surface; - struct wl_listener drag_icon_listener; - struct wl_signal drag_icon_signal; - + struct wl_list data_device_resource_list; MetaWaylandPointer pointer; MetaWaylandKeyboard keyboard; @@ -95,9 +84,8 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat, const ClutterEvent *event); void -meta_wayland_seat_repick (MetaWaylandSeat *seat, - uint32_t time, - ClutterActor *actor); +meta_wayland_seat_repick (MetaWaylandSeat *seat, + const ClutterEvent *for_event); void meta_wayland_seat_update_sprite (MetaWaylandSeat *seat); diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 58dab549f..f77f9cb3e 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -407,7 +407,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface) meta_wayland_pointer_destroy_focus (&compositor->seat->pointer); g_assert (surface != compositor->seat->pointer.focus); - g_assert (surface != compositor->seat->pointer.grab->focus); } if (compositor->implicit_grab_surface == surface) @@ -493,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 diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index dee940245..13bbb9a43 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -219,9 +219,7 @@ meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor) { - meta_wayland_seat_repick (compositor->seat, - get_time (), - NULL); + meta_wayland_seat_repick (compositor->seat, NULL); } static void