diff --git a/src/compositor.h b/src/compositor.h index 526f3d19..8c19619a 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -408,10 +408,15 @@ void weston_seat_set_selection(struct weston_seat *seat, struct weston_data_source *source, uint32_t serial); int -weston_seat_start_drag(struct weston_seat *seat, +weston_pointer_start_drag(struct weston_pointer *pointer, struct weston_data_source *source, struct weston_surface *icon, struct wl_client *client); +int +weston_touch_start_drag(struct weston_touch *touch, + struct weston_data_source *source, + struct weston_surface *icon, + struct wl_client *client); struct weston_xkb_info { struct xkb_keymap *keymap; diff --git a/src/data-device.c b/src/data-device.c index 313278e9..5ef69d19 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -37,12 +37,21 @@ struct weston_drag { struct weston_view *focus; struct wl_resource *focus_resource; struct wl_listener focus_listener; - struct weston_pointer_grab grab; struct weston_view *icon; struct wl_listener icon_destroy_listener; int32_t dx, dy; }; +struct weston_pointer_drag { + struct weston_drag base; + struct weston_pointer_grab grab; +}; + +struct weston_touch_drag { + struct weston_drag base; + struct weston_touch_grab grab; +}; + static void empty_region(pixman_region32_t *region) { @@ -172,17 +181,21 @@ static struct wl_data_source_interface data_source_interface = { }; static void -drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +drag_surface_configure(struct weston_drag *drag, + struct weston_pointer *pointer, + struct weston_touch *touch, + struct weston_surface *es, int32_t sx, int32_t sy, + int32_t width, int32_t height) { - struct weston_drag *drag = es->configure_private; - struct weston_pointer *pointer = drag->grab.pointer; struct wl_list *list; float fx, fy; - assert(es->configure == drag_surface_configure); + assert((pointer != NULL && touch == NULL) || + (pointer == NULL && touch != NULL)); if (!weston_surface_is_mapped(es) && es->buffer_ref.buffer) { - if (pointer->sprite && weston_view_is_mapped(pointer->sprite)) + if (pointer && pointer->sprite && + weston_view_is_mapped(pointer->sprite)) list = &pointer->sprite->layer_link; else list = &es->compositor->cursor_layer.view_list; @@ -196,11 +209,40 @@ drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_ drag->dx += sx; drag->dy += sy; - fx = wl_fixed_to_double(pointer->x) + drag->dx; - fy = wl_fixed_to_double(pointer->y) + drag->dy; + /* init to 0 for avoiding a compile warning */ + fx = fy = 0; + if (pointer) { + fx = wl_fixed_to_double(pointer->x) + drag->dx; + fy = wl_fixed_to_double(pointer->y) + drag->dy; + } else if (touch) { + fx = wl_fixed_to_double(touch->grab_x) + drag->dx; + fy = wl_fixed_to_double(touch->grab_y) + drag->dy; + } weston_view_configure(drag->icon, fx, fy, width, height); } +static void +pointer_drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +{ + struct weston_pointer_drag *drag = es->configure_private; + struct weston_pointer *pointer = drag->grab.pointer; + + assert(es->configure == pointer_drag_surface_configure); + + drag_surface_configure(&drag->base, pointer, NULL, es, sx, sy, width, height); +} + +static void +touch_drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +{ + struct weston_touch_drag *drag = es->configure_private; + struct weston_touch *touch = drag->grab.touch; + + assert(es->configure == touch_drag_surface_configure); + + drag_surface_configure(&drag->base, NULL, touch, es, sx, sy, width, height); +} + static void destroy_drag_focus(struct wl_listener *listener, void *data) { @@ -211,12 +253,13 @@ destroy_drag_focus(struct wl_listener *listener, void *data) } static void -weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view, - wl_fixed_t sx, wl_fixed_t sy) +weston_drag_set_focus(struct weston_drag *drag, + struct weston_seat *seat, + struct weston_view *view, + wl_fixed_t sx, wl_fixed_t sy) { - struct weston_pointer *pointer = drag->grab.pointer; struct wl_resource *resource, *offer = NULL; - struct wl_display *display = pointer->seat->compositor->wl_display; + struct wl_display *display = seat->compositor->wl_display; uint32_t serial; if (drag->focus && view && drag->focus->surface == view->surface) { @@ -238,7 +281,7 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view, wl_resource_get_client(view->surface->resource) != drag->client) return; - resource = wl_resource_find_for_client(&pointer->seat->drag_resource_list, + resource = wl_resource_find_for_client(&seat->drag_resource_list, wl_resource_get_client(view->surface->resource)); if (!resource) return; @@ -264,8 +307,8 @@ weston_drag_set_focus(struct weston_drag *drag, struct weston_view *view, static void drag_grab_focus(struct weston_pointer_grab *grab) { - struct weston_drag *drag = - container_of(grab, struct weston_drag, grab); + struct weston_pointer_drag *drag = + container_of(grab, struct weston_pointer_drag, grab); struct weston_pointer *pointer = grab->pointer; struct weston_view *view; wl_fixed_t sx, sy; @@ -273,40 +316,41 @@ drag_grab_focus(struct weston_pointer_grab *grab) view = weston_compositor_pick_view(pointer->seat->compositor, pointer->x, pointer->y, &sx, &sy); - if (drag->focus != view) - weston_drag_set_focus(drag, view, sx, sy); + if (drag->base.focus != view) + weston_drag_set_focus(&drag->base, pointer->seat, view, sx, sy); } static void drag_grab_motion(struct weston_pointer_grab *grab, uint32_t time, wl_fixed_t x, wl_fixed_t y) { - struct weston_drag *drag = - container_of(grab, struct weston_drag, grab); + struct weston_pointer_drag *drag = + container_of(grab, struct weston_pointer_drag, grab); struct weston_pointer *pointer = drag->grab.pointer; float fx, fy; wl_fixed_t sx, sy; weston_pointer_move(pointer, x, y); - if (drag->icon) { - fx = wl_fixed_to_double(pointer->x) + drag->dx; - fy = wl_fixed_to_double(pointer->y) + drag->dy; - weston_view_set_position(drag->icon, fx, fy); - weston_view_schedule_repaint(drag->icon); + if (drag->base.icon) { + fx = wl_fixed_to_double(pointer->x) + drag->base.dx; + fy = wl_fixed_to_double(pointer->y) + drag->base.dy; + weston_view_set_position(drag->base.icon, fx, fy); + weston_view_schedule_repaint(drag->base.icon); } - if (drag->focus_resource) { - weston_view_from_global_fixed(drag->focus, + if (drag->base.focus_resource) { + weston_view_from_global_fixed(drag->base.focus, pointer->x, pointer->y, &sx, &sy); - wl_data_device_send_motion(drag->focus_resource, time, sx, sy); + wl_data_device_send_motion(drag->base.focus_resource, time, sx, sy); } } static void -data_device_end_drag_grab(struct weston_drag *drag) +data_device_end_drag_grab(struct weston_drag *drag, + struct weston_seat *seat) { if (drag->icon) { if (weston_view_is_mapped(drag->icon)) @@ -318,10 +362,16 @@ data_device_end_drag_grab(struct weston_drag *drag) weston_view_destroy(drag->icon); } - weston_drag_set_focus(drag, NULL, 0, 0); + weston_drag_set_focus(drag, seat, NULL, 0, 0); +} - weston_pointer_end_grab(drag->grab.pointer); +static void +data_device_end_pointer_drag_grab(struct weston_pointer_drag *drag) +{ + struct weston_pointer *pointer = drag->grab.pointer; + data_device_end_drag_grab(&drag->base, pointer->seat); + weston_pointer_end_grab(pointer); free(drag); } @@ -329,37 +379,37 @@ static void drag_grab_button(struct weston_pointer_grab *grab, uint32_t time, uint32_t button, uint32_t state_w) { - struct weston_drag *drag = - container_of(grab, struct weston_drag, grab); + struct weston_pointer_drag *drag = + container_of(grab, struct weston_pointer_drag, grab); struct weston_pointer *pointer = drag->grab.pointer; enum wl_pointer_button_state state = state_w; - if (drag->focus_resource && + if (drag->base.focus_resource && pointer->grab_button == button && state == WL_POINTER_BUTTON_STATE_RELEASED) - wl_data_device_send_drop(drag->focus_resource); + wl_data_device_send_drop(drag->base.focus_resource); if (pointer->button_count == 0 && state == WL_POINTER_BUTTON_STATE_RELEASED) { - if (drag->data_source) - wl_list_remove(&drag->data_source_listener.link); - data_device_end_drag_grab(drag); + if (drag->base.data_source) + wl_list_remove(&drag->base.data_source_listener.link); + data_device_end_pointer_drag_grab(drag); } } static void drag_grab_cancel(struct weston_pointer_grab *grab) { - struct weston_drag *drag = - container_of(grab, struct weston_drag, grab); + struct weston_pointer_drag *drag = + container_of(grab, struct weston_pointer_drag, grab); - if (drag->data_source) - wl_list_remove(&drag->data_source_listener.link); + if (drag->base.data_source) + wl_list_remove(&drag->base.data_source_listener.link); - data_device_end_drag_grab(drag); + data_device_end_pointer_drag_grab(drag); } -static const struct weston_pointer_grab_interface drag_grab_interface = { +static const struct weston_pointer_grab_interface pointer_drag_grab_interface = { drag_grab_focus, drag_grab_motion, drag_grab_button, @@ -367,12 +417,109 @@ static const struct weston_pointer_grab_interface drag_grab_interface = { }; static void -destroy_data_device_source(struct wl_listener *listener, void *data) +drag_grab_touch_down(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) { - struct weston_drag *drag = container_of(listener, struct weston_drag, - data_source_listener); +} - data_device_end_drag_grab(drag); +static void +data_device_end_touch_drag_grab(struct weston_touch_drag *drag) +{ + struct weston_touch *touch = drag->grab.touch; + + data_device_end_drag_grab(&drag->base, touch->seat); + weston_touch_end_grab(touch); + free(drag); +} + +static void +drag_grab_touch_up(struct weston_touch_grab *grab, + uint32_t time, int touch_id) +{ + struct weston_touch_drag *touch_drag = + container_of(grab, struct weston_touch_drag, grab); + struct weston_touch *touch = grab->touch; + + if (touch_id != touch->grab_touch_id) + return; + + if (touch_drag->base.focus_resource) + wl_data_device_send_drop(touch_drag->base.focus_resource); + if (touch_drag->base.data_source) + wl_list_remove(&touch_drag->base.data_source_listener.link); + data_device_end_touch_drag_grab(touch_drag); +} + +static void +drag_grab_touch_focus(struct weston_touch_drag *drag) +{ + struct weston_touch *touch = drag->grab.touch; + struct weston_view *view; + wl_fixed_t view_x, view_y; + + view = weston_compositor_pick_view(touch->seat->compositor, + touch->grab_x, touch->grab_y, + &view_x, &view_y); + if (drag->base.focus != view) + weston_drag_set_focus(&drag->base, touch->seat, + view, view_x, view_y); +} + +static void +drag_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time, + int touch_id, wl_fixed_t sx, wl_fixed_t sy) +{ + struct weston_touch_drag *touch_drag = + container_of(grab, struct weston_touch_drag, grab); + struct weston_touch *touch = grab->touch; + wl_fixed_t view_x, view_y; + float fx, fy; + + if (touch_id != touch->grab_touch_id) + return; + + drag_grab_touch_focus(touch_drag); + if (touch_drag->base.icon) { + fx = wl_fixed_to_double(touch->grab_x) + touch_drag->base.dx; + fy = wl_fixed_to_double(touch->grab_y) + touch_drag->base.dy; + weston_view_set_position(touch_drag->base.icon, fx, fy); + weston_view_schedule_repaint(touch_drag->base.icon); + } + + if (touch_drag->base.focus_resource) { + weston_view_from_global_fixed(touch_drag->base.focus, + touch->grab_x, touch->grab_y, + &view_x, &view_y); + wl_data_device_send_motion(touch_drag->base.focus_resource, time, + view_x, view_y); + } +} + +static void +drag_grab_touch_cancel(struct weston_touch_grab *grab) +{ + struct weston_touch_drag *touch_drag = + container_of(grab, struct weston_touch_drag, grab); + + if (touch_drag->base.data_source) + wl_list_remove(&touch_drag->base.data_source_listener.link); + data_device_end_touch_drag_grab(touch_drag); +} + +static const struct weston_touch_grab_interface touch_drag_grab_interface = { + drag_grab_touch_down, + drag_grab_touch_up, + drag_grab_touch_motion, + drag_grab_touch_cancel +}; + +static void +destroy_pointer_data_device_source(struct wl_listener *listener, void *data) +{ + struct weston_pointer_drag *drag = container_of(listener, + struct weston_pointer_drag, base.data_source_listener); + + data_device_end_pointer_drag_grab(drag); } static void @@ -385,47 +532,102 @@ handle_drag_icon_destroy(struct wl_listener *listener, void *data) } WL_EXPORT int -weston_seat_start_drag(struct weston_seat *seat, +weston_pointer_start_drag(struct weston_pointer *pointer, struct weston_data_source *source, struct weston_surface *icon, struct wl_client *client) { - struct weston_drag *drag; + struct weston_pointer_drag *drag; drag = zalloc(sizeof *drag); if (drag == NULL) return -1; - drag->grab.interface = &drag_grab_interface; - drag->client = client; - drag->data_source = source; + drag->grab.interface = &pointer_drag_grab_interface; + drag->base.client = client; + drag->base.data_source = source; if (icon) { - drag->icon = weston_view_create(icon); - if (drag->icon == NULL) { + drag->base.icon = weston_view_create(icon); + if (drag->base.icon == NULL) { free(drag); return -1; } - drag->icon_destroy_listener.notify = handle_drag_icon_destroy; + drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy; wl_signal_add(&icon->destroy_signal, - &drag->icon_destroy_listener); + &drag->base.icon_destroy_listener); - icon->configure = drag_surface_configure; + icon->configure = pointer_drag_surface_configure; icon->configure_private = drag; } else { - drag->icon = NULL; + drag->base.icon = NULL; } if (source) { - drag->data_source_listener.notify = destroy_data_device_source; + drag->base.data_source_listener.notify = destroy_pointer_data_device_source; wl_signal_add(&source->destroy_signal, - &drag->data_source_listener); + &drag->base.data_source_listener); } - weston_pointer_set_focus(seat->pointer, NULL, + weston_pointer_set_focus(pointer, NULL, wl_fixed_from_int(0), wl_fixed_from_int(0)); - weston_pointer_start_grab(seat->pointer, &drag->grab); + weston_pointer_start_grab(pointer, &drag->grab); + + return 0; +} + +static void +destroy_touch_data_device_source(struct wl_listener *listener, void *data) +{ + struct weston_touch_drag *drag = container_of(listener, + struct weston_touch_drag, base.data_source_listener); + + data_device_end_touch_drag_grab(drag); +} + +WL_EXPORT int +weston_touch_start_drag(struct weston_touch *touch, + struct weston_data_source *source, + struct weston_surface *icon, + struct wl_client *client) +{ + struct weston_touch_drag *drag; + + drag = zalloc(sizeof *drag); + if (drag == NULL) + return -1; + + drag->grab.interface = &touch_drag_grab_interface; + drag->base.client = client; + drag->base.data_source = source; + + if (icon) { + drag->base.icon = weston_view_create(icon); + if (drag->base.icon == NULL) { + free(drag); + return -1; + } + + drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy; + wl_signal_add(&icon->destroy_signal, + &drag->base.icon_destroy_listener); + + icon->configure = touch_drag_surface_configure; + icon->configure_private = drag; + } else { + drag->base.icon = NULL; + } + + if (source) { + drag->base.data_source_listener.notify = destroy_touch_data_device_source; + wl_signal_add(&source->destroy_signal, + &drag->base.data_source_listener); + } + + weston_touch_start_grab(touch, &drag->grab); + + drag_grab_touch_focus(drag); return 0; } @@ -439,11 +641,15 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, struct weston_seat *seat = wl_resource_get_user_data(resource); struct weston_data_source *source = NULL; struct weston_surface *icon = NULL; + int32_t ret = 0; - if (seat->pointer->button_count == 0 || + if ((seat->pointer->button_count == 0 || seat->pointer->grab_serial != serial || !seat->pointer->focus || - seat->pointer->focus->surface != wl_resource_get_user_data(origin_resource)) + seat->pointer->focus->surface != wl_resource_get_user_data(origin_resource)) && + (seat->touch->grab_serial != serial || + !seat->touch->focus || + seat->touch->focus->surface != wl_resource_get_user_data(origin_resource))) return; /* FIXME: Check that the data source type array isn't empty. */ @@ -459,7 +665,17 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, return; } - if (weston_seat_start_drag(seat, source, icon, client) < 0) + if (seat->pointer->button_count == 1 && + seat->pointer->grab_serial == serial && + seat->pointer->focus && + seat->pointer->focus->surface == wl_resource_get_user_data(origin_resource)) + ret = weston_pointer_start_drag(seat->pointer, source, icon, client); + else if (seat->touch->grab_serial != serial || + seat->touch->focus || + seat->touch->focus->surface != wl_resource_get_user_data(origin_resource)) + ret = weston_touch_start_drag(seat->touch, source, icon, client); + + if (ret < 0) wl_resource_post_no_memory(resource); } diff --git a/src/xwayland/dnd.c b/src/xwayland/dnd.c index b146e123..1fea3efc 100644 --- a/src/xwayland/dnd.c +++ b/src/xwayland/dnd.c @@ -211,7 +211,7 @@ handle_enter(struct weston_wm *wm, xcb_client_message_event_t *client_message) } free(reply); - weston_seat_start_drag(seat, &source->base, NULL, NULL); + weston_pointer_start_drag(seat->pointer, &source->base, NULL, NULL); } int