xwayland: send DND_DROP

This commit is contained in:
emersion 2018-03-28 15:33:23 -04:00
parent 73394deb76
commit 2a34b154e6
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
5 changed files with 123 additions and 4 deletions

View File

@ -108,6 +108,7 @@ struct wlr_drag {
struct { struct {
struct wl_signal focus; struct wl_signal focus;
struct wl_signal motion; struct wl_signal motion;
struct wl_signal drop;
struct wl_signal destroy; struct wl_signal destroy;
} events; } events;
}; };
@ -118,6 +119,11 @@ struct wlr_drag_motion_event {
double sx, sy; double sx, sy;
}; };
struct wlr_drag_drop_event {
struct wlr_drag *drag;
uint32_t time;
};
/** /**
* Create a wl data device manager global for this display. * Create a wl data device manager global for this display.
*/ */

View File

@ -137,6 +137,7 @@ struct wlr_xwm {
struct wl_listener seat_start_drag; struct wl_listener seat_start_drag;
struct wl_listener seat_drag_focus; struct wl_listener seat_drag_focus;
struct wl_listener seat_drag_motion; struct wl_listener seat_drag_motion;
struct wl_listener seat_drag_drop;
struct wl_listener seat_drag_destroy; struct wl_listener seat_drag_destroy;
}; };
@ -148,6 +149,8 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride,
uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y); uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y);
int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event); int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event);
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
xcb_client_message_event_t *ev) ;
void xwm_selection_init(struct wlr_xwm *xwm); void xwm_selection_init(struct wlr_xwm *xwm);
void xwm_selection_finish(struct wlr_xwm *xwm); void xwm_selection_finish(struct wlr_xwm *xwm);

View File

@ -426,7 +426,6 @@ static void wlr_drag_set_focus(struct wlr_drag *drag,
struct wlr_seat_client *focus_client = struct wlr_seat_client *focus_client =
wlr_seat_client_for_wl_client(drag->seat_client->seat, wlr_seat_client_for_wl_client(drag->seat_client->seat,
wl_resource_get_client(surface->resource)); wl_resource_get_client(surface->resource));
if (!focus_client) { if (!focus_client) {
return; return;
} }
@ -541,6 +540,12 @@ static uint32_t pointer_drag_button(struct wlr_seat_pointer_grab *grab,
drag->source->offer->in_ask = drag->source->offer->in_ask =
drag->source->current_dnd_action == drag->source->current_dnd_action ==
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
struct wlr_drag_drop_event event = {
.drag = drag,
.time = time,
};
wlr_signal_emit_safe(&drag->events.drop, &event);
} else if (drag->source->dnd_finish) { } else if (drag->source->dnd_finish) {
drag->source->cancel(drag->source); drag->source->cancel(drag->source);
} }
@ -556,6 +561,7 @@ static uint32_t pointer_drag_button(struct wlr_seat_pointer_grab *grab,
static void pointer_drag_axis(struct wlr_seat_pointer_grab *grab, uint32_t time, static void pointer_drag_axis(struct wlr_seat_pointer_grab *grab, uint32_t time,
enum wlr_axis_orientation orientation, double value) { enum wlr_axis_orientation orientation, double value) {
// This space is intentionally left blank
} }
static void pointer_drag_cancel(struct wlr_seat_pointer_grab *grab) { static void pointer_drag_cancel(struct wlr_seat_pointer_grab *grab) {
@ -745,6 +751,7 @@ static bool seat_client_start_drag(struct wlr_seat_client *client,
wl_signal_init(&drag->events.focus); wl_signal_init(&drag->events.focus);
wl_signal_init(&drag->events.motion); wl_signal_init(&drag->events.motion);
wl_signal_init(&drag->events.drop);
wl_signal_init(&drag->events.destroy); wl_signal_init(&drag->events.destroy);
struct wlr_seat *seat = client->seat; struct wlr_seat *seat = client->seat;

View File

@ -183,8 +183,7 @@ error_out:
static void xwm_selection_source_send(struct wlr_xwm_selection *selection, static void xwm_selection_source_send(struct wlr_xwm_selection *selection,
const char *mime_type, int32_t fd) { const char *mime_type, int32_t fd) {
if (selection == &selection->xwm->clipboard_selection || if (selection == &selection->xwm->clipboard_selection) {
selection == &selection->xwm->dnd_selection) {
struct wlr_data_source *source = struct wlr_data_source *source =
selection->xwm->seat->selection_data_source; selection->xwm->seat->selection_data_source;
if (source != NULL) { if (source != NULL) {
@ -198,6 +197,15 @@ static void xwm_selection_source_send(struct wlr_xwm_selection *selection,
source->send(source, mime_type, fd); source->send(source, mime_type, fd);
return; return;
} }
} else if (selection == &selection->xwm->dnd_selection) {
if (selection->xwm->seat->drag != NULL) {
struct wlr_data_source *source =
selection->xwm->seat->drag->source;
if (source != NULL) {
source->send(source, mime_type, fd);
return;
}
}
} }
wlr_log(L_DEBUG, "not sending selection: no selection source available"); wlr_log(L_DEBUG, "not sending selection: no selection source available");
@ -263,7 +271,9 @@ static xcb_atom_t xwm_get_mime_type_atom(struct wlr_xwm *xwm, char *mime_type) {
static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { static void xwm_dnd_send_enter(struct wlr_xwm *xwm) {
struct wlr_drag *drag = xwm->drag; struct wlr_drag *drag = xwm->drag;
assert(drag != NULL);
struct wlr_xwayland_surface *dest = xwm->drag_focus; struct wlr_xwayland_surface *dest = xwm->drag_focus;
assert(dest != NULL);
struct wl_array *mime_types = &drag->source->mime_types; struct wl_array *mime_types = &drag->source->mime_types;
xcb_client_message_data_t data = { 0 }; xcb_client_message_data_t data = { 0 };
@ -321,7 +331,9 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) {
static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x, static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x,
int16_t y) { int16_t y) {
struct wlr_drag *drag = xwm->drag; struct wlr_drag *drag = xwm->drag;
assert(drag != NULL);
struct wlr_xwayland_surface *dest = xwm->drag_focus; struct wlr_xwayland_surface *dest = xwm->drag_focus;
assert(dest != NULL);
xcb_client_message_data_t data = { 0 }; xcb_client_message_data_t data = { 0 };
data.data32[0] = xwm->dnd_selection.window; data.data32[0] = xwm->dnd_selection.window;
@ -346,6 +358,63 @@ static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x,
(const char *)&event); (const char *)&event);
} }
static void xwm_dnd_send_drop(struct wlr_xwm *xwm, uint32_t time) {
struct wlr_drag *drag = xwm->drag;
assert(drag != NULL);
struct wlr_xwayland_surface *dest = xwm->drag_focus;
assert(dest != NULL);
xcb_client_message_data_t data = { 0 };
data.data32[0] = xwm->dnd_selection.window;
data.data32[2] = time;
xcb_client_message_event_t event = {
.response_type = XCB_CLIENT_MESSAGE,
.format = 32,
.sequence = 0,
.window = dest->window_id,
.type = xwm->atoms[DND_DROP],
.data = data,
};
xcb_send_event(xwm->xcb_conn,
0, // propagate
dest->window_id,
XCB_EVENT_MASK_NO_EVENT,
(const char *)&event);
}
/*static void xwm_dnd_send_finished(struct wlr_xwm *xwm) {
struct wlr_drag *drag = xwm->drag;
assert(drag != NULL);
struct wlr_xwayland_surface *dest = xwm->drag_focus;
assert(dest != NULL);
xcb_client_message_data_t data = { 0 };
data.data32[0] = xwm->dnd_selection.window;
data.data32[1] = drag->source->accepted;
if (drag->source->accepted) {
data.data32[2] = data_device_manager_dnd_action_to_atom(xwm,
drag->source->current_dnd_action);
}
xcb_client_message_event_t event = {
.response_type = XCB_CLIENT_MESSAGE,
.format = 32,
.sequence = 0,
.window = dest->window_id,
.type = xwm->atoms[DND_FINISHED],
.data = data,
};
xcb_send_event(xwm->xcb_conn,
0, // propagate
dest->window_id,
XCB_EVENT_MASK_NO_EVENT,
(const char *)&event);
}*/
static struct wl_array *xwm_selection_source_get_mime_types( static struct wl_array *xwm_selection_source_get_mime_types(
struct wlr_xwm_selection *selection) { struct wlr_xwm_selection *selection) {
if (selection == &selection->xwm->clipboard_selection || if (selection == &selection->xwm->clipboard_selection ||
@ -911,6 +980,26 @@ int xwm_handle_selection_event(struct wlr_xwm *xwm,
return 0; return 0;
} }
int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
xcb_client_message_event_t *ev) {
if (ev->type == xwm->atoms[DND_STATUS]) {
struct wlr_drag *drag = xwm->drag;
if (drag == NULL) {
return 0;
}
// xcb_client_message_data_t *data = &ev->data;
// xcb_window_t target_window = data->data32[0];
// bool accepted = data->data32[1] & 1;
// xcb_atom_t action = data->data32[4];
// TODO: drag->source->dnd_action(data_device_manager_dnd_action_from_atom(xwm, action))
return 1;
} else {
return 0;
}
}
static void selection_init(struct wlr_xwm *xwm, static void selection_init(struct wlr_xwm *xwm,
struct wlr_xwm_selection *selection, xcb_atom_t atom) { struct wlr_xwm_selection *selection, xcb_atom_t atom) {
selection->xwm = xwm; selection->xwm = xwm;
@ -1065,6 +1154,18 @@ static void seat_handle_drag_motion(struct wl_listener *listener, void *data) {
surface->y + (int16_t)event->sy); surface->y + (int16_t)event->sy);
} }
static void seat_handle_drag_drop(struct wl_listener *listener, void *data) {
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_drop);
struct wlr_drag_drop_event *event = data;
struct wlr_xwayland_surface *surface = xwm->drag_focus;
if (surface == NULL) {
return; // No xwayland surface focused
}
xwm_dnd_send_drop(xwm, event->time);
}
static void seat_handle_drag_destroy(struct wl_listener *listener, void *data) { static void seat_handle_drag_destroy(struct wl_listener *listener, void *data) {
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_destroy); struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_destroy);
@ -1085,6 +1186,8 @@ static void seat_handle_start_drag(struct wl_listener *listener, void *data) {
xwm->seat_drag_focus.notify = seat_handle_drag_focus; xwm->seat_drag_focus.notify = seat_handle_drag_focus;
wl_signal_add(&drag->events.motion, &xwm->seat_drag_motion); wl_signal_add(&drag->events.motion, &xwm->seat_drag_motion);
xwm->seat_drag_motion.notify = seat_handle_drag_motion; xwm->seat_drag_motion.notify = seat_handle_drag_motion;
wl_signal_add(&drag->events.drop, &xwm->seat_drag_drop);
xwm->seat_drag_drop.notify = seat_handle_drag_drop;
wl_signal_add(&drag->events.destroy, &xwm->seat_drag_destroy); wl_signal_add(&drag->events.destroy, &xwm->seat_drag_destroy);
xwm->seat_drag_destroy.notify = seat_handle_drag_destroy; xwm->seat_drag_destroy.notify = seat_handle_drag_destroy;
} }

View File

@ -943,7 +943,7 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
xwm_handle_net_wm_state_message(xwm, ev); xwm_handle_net_wm_state_message(xwm, ev);
} else if (ev->type == xwm->atoms[_NET_WM_MOVERESIZE]) { } else if (ev->type == xwm->atoms[_NET_WM_MOVERESIZE]) {
xwm_handle_net_wm_moveresize_message(xwm, ev); xwm_handle_net_wm_moveresize_message(xwm, ev);
} else { } else if (!xwm_handle_selection_client_message(xwm, ev)) {
wlr_log(L_DEBUG, "unhandled x11 client message %u", ev->type); wlr_log(L_DEBUG, "unhandled x11 client message %u", ev->type);
} }
} }