diff --git a/src/compositor.h b/src/compositor.h index 8303a5f3..58ae94bc 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -336,6 +336,7 @@ struct weston_data_source { bool actions_set; uint32_t dnd_actions; enum wl_data_device_manager_dnd_action current_dnd_action; + enum wl_data_device_manager_dnd_action compositor_action; void (*accept)(struct weston_data_source *source, uint32_t serial, const char *mime_type); diff --git a/src/data-device.c b/src/data-device.c index 75a4424a..2cfdcfe2 100644 --- a/src/data-device.c +++ b/src/data-device.c @@ -44,6 +44,7 @@ struct weston_drag { struct weston_view *icon; struct wl_listener icon_destroy_listener; int32_t dx, dy; + struct weston_keyboard_grab keyboard_grab; }; struct weston_pointer_drag { @@ -139,6 +140,10 @@ data_offer_choose_action(struct weston_data_offer *offer) if (!available_actions) return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + if (offer->source->seat && + offer->source->compositor_action & available_actions) + return offer->source->compositor_action; + /* If the dest side has a preferred DnD action, use it */ if ((preferred_action & available_actions) != 0) return preferred_action; @@ -611,9 +616,11 @@ static void data_device_end_pointer_drag_grab(struct weston_pointer_drag *drag) { struct weston_pointer *pointer = drag->grab.pointer; + struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard; data_device_end_drag_grab(&drag->base, pointer->seat); weston_pointer_end_grab(pointer); + weston_keyboard_end_grab(keyboard); free(drag); } @@ -706,9 +713,11 @@ static void data_device_end_touch_drag_grab(struct weston_touch_drag *drag) { struct weston_touch *touch = drag->grab.touch; + struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard; data_device_end_drag_grab(&drag->base, touch->seat); weston_touch_end_grab(touch); + weston_keyboard_end_grab(keyboard); free(drag); } @@ -799,6 +808,61 @@ static const struct weston_touch_grab_interface touch_drag_grab_interface = { drag_grab_touch_cancel }; +static void +drag_grab_keyboard_key(struct weston_keyboard_grab *grab, + uint32_t time, uint32_t key, uint32_t state) +{ +} + +static void +drag_grab_keyboard_modifiers(struct weston_keyboard_grab *grab, + uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + struct weston_keyboard *keyboard = grab->keyboard; + struct weston_drag *drag = + container_of(grab, struct weston_drag, keyboard_grab); + uint32_t compositor_action; + + if (mods_depressed & (1 << keyboard->xkb_info->shift_mod)) + compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; + else if (mods_depressed & (1 << keyboard->xkb_info->ctrl_mod)) + compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; + else + compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + + drag->data_source->compositor_action = compositor_action; + + if (drag->data_source->offer) + data_offer_update_action(drag->data_source->offer); +} + +static void +drag_grab_keyboard_cancel(struct weston_keyboard_grab *grab) +{ + struct weston_drag *drag = + container_of(grab, struct weston_drag, keyboard_grab); + struct weston_pointer *pointer = grab->keyboard->seat->pointer_state; + struct weston_touch *touch = grab->keyboard->seat->touch_state; + + if (pointer && pointer->grab->interface == &pointer_drag_grab_interface) { + struct weston_touch_drag *touch_drag = + (struct weston_touch_drag *) drag; + drag_grab_touch_cancel(&touch_drag->grab); + } else if (touch && touch->grab->interface == &touch_drag_grab_interface) { + struct weston_pointer_drag *pointer_drag = + (struct weston_pointer_drag *) drag; + drag_grab_cancel(&pointer_drag->grab); + } +} + +static const struct weston_keyboard_grab_interface keyboard_drag_grab_interface = { + drag_grab_keyboard_key, + drag_grab_keyboard_modifiers, + drag_grab_keyboard_cancel +}; + static void destroy_pointer_data_device_source(struct wl_listener *listener, void *data) { @@ -824,12 +888,15 @@ weston_pointer_start_drag(struct weston_pointer *pointer, struct wl_client *client) { struct weston_pointer_drag *drag; + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(pointer->seat); drag = zalloc(sizeof *drag); if (drag == NULL) return -1; drag->grab.interface = &pointer_drag_grab_interface; + drag->base.keyboard_grab.interface = &keyboard_drag_grab_interface; drag->base.client = client; drag->base.data_source = source; @@ -859,7 +926,10 @@ weston_pointer_start_drag(struct weston_pointer *pointer, } weston_pointer_clear_focus(pointer); + weston_keyboard_set_focus(keyboard, NULL); + weston_pointer_start_grab(pointer, &drag->grab); + weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab); return 0; } @@ -880,6 +950,8 @@ weston_touch_start_drag(struct weston_touch *touch, struct wl_client *client) { struct weston_touch_drag *drag; + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(touch->seat); drag = zalloc(sizeof *drag); if (drag == NULL) @@ -914,7 +986,10 @@ weston_touch_start_drag(struct weston_touch *touch, &drag->base.data_source_listener); } + weston_keyboard_set_focus(keyboard, NULL); + weston_touch_start_grab(touch, &drag->grab); + weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab); drag_grab_touch_focus(drag); @@ -1172,6 +1247,7 @@ create_data_source(struct wl_client *client, source->actions_set = false; source->dnd_actions = 0; source->current_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + source->compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; wl_array_init(&source->mime_types);