Merge pull request #1513 from emersion/fix-dnd
data-device: fix drag-and-drop
This commit is contained in:
commit
41af8d8459
|
@ -29,7 +29,7 @@ struct roots_seat {
|
||||||
struct wl_list views; // roots_seat_view::link
|
struct wl_list views; // roots_seat_view::link
|
||||||
bool has_focus;
|
bool has_focus;
|
||||||
|
|
||||||
struct wl_list drag_icons; // roots_drag_icon::link
|
struct roots_drag_icon *drag_icon; // can be NULL
|
||||||
|
|
||||||
struct wl_list keyboards;
|
struct wl_list keyboards;
|
||||||
struct wl_list pointers;
|
struct wl_list pointers;
|
||||||
|
@ -61,7 +61,6 @@ struct roots_seat_view {
|
||||||
struct roots_drag_icon {
|
struct roots_drag_icon {
|
||||||
struct roots_seat *seat;
|
struct roots_seat *seat;
|
||||||
struct wlr_drag_icon *wlr_drag_icon;
|
struct wlr_drag_icon *wlr_drag_icon;
|
||||||
struct wl_list link;
|
|
||||||
|
|
||||||
double x, y;
|
double x, y;
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ struct wlr_seat_pointer_state {
|
||||||
struct wlr_seat *seat;
|
struct wlr_seat *seat;
|
||||||
struct wlr_seat_client *focused_client;
|
struct wlr_seat_client *focused_client;
|
||||||
struct wlr_surface *focused_surface;
|
struct wlr_surface *focused_surface;
|
||||||
|
double sx, sy;
|
||||||
|
|
||||||
struct wlr_seat_pointer_grab *grab;
|
struct wlr_seat_pointer_grab *grab;
|
||||||
struct wlr_seat_pointer_grab *default_grab;
|
struct wlr_seat_pointer_grab *default_grab;
|
||||||
|
|
|
@ -101,8 +101,7 @@ static void seat_view_deco_button(struct roots_seat_view *view, double sx,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void roots_passthrough_cursor(struct roots_cursor *cursor,
|
static void roots_passthrough_cursor(struct roots_cursor *cursor,
|
||||||
int64_t time) {
|
uint32_t time) {
|
||||||
bool focus_changed;
|
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
struct roots_view *view = NULL;
|
struct roots_view *view = NULL;
|
||||||
struct roots_seat *seat = cursor->seat;
|
struct roots_seat *seat = cursor->seat;
|
||||||
|
@ -146,23 +145,26 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor,
|
||||||
cursor->wlr_surface = surface;
|
cursor->wlr_surface = surface;
|
||||||
|
|
||||||
if (surface) {
|
if (surface) {
|
||||||
focus_changed = (seat->seat->pointer_state.focused_surface != surface);
|
|
||||||
wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
|
wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
|
||||||
if (!focus_changed && time > 0) {
|
|
||||||
wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
|
wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
wlr_seat_pointer_clear_focus(seat->seat);
|
wlr_seat_pointer_clear_focus(seat->seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct roots_drag_icon *drag_icon;
|
if (seat->drag_icon != NULL) {
|
||||||
wl_list_for_each(drag_icon, &seat->drag_icons, link) {
|
roots_drag_icon_update_position(seat->drag_icon);
|
||||||
roots_drag_icon_update_position(drag_icon);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int64_t timespec_to_msec(const struct timespec *a) {
|
||||||
|
return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
void roots_cursor_update_focus(struct roots_cursor *cursor) {
|
void roots_cursor_update_focus(struct roots_cursor *cursor) {
|
||||||
roots_passthrough_cursor(cursor, -1);
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
roots_passthrough_cursor(cursor, timespec_to_msec(&now));
|
||||||
}
|
}
|
||||||
|
|
||||||
void roots_cursor_update_position(struct roots_cursor *cursor,
|
void roots_cursor_update_position(struct roots_cursor *cursor,
|
||||||
|
|
|
@ -136,10 +136,11 @@ static inline int64_t timespec_to_msec(const struct timespec *a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void input_update_cursor_focus(struct roots_input *input) {
|
void input_update_cursor_focus(struct roots_input *input) {
|
||||||
struct roots_seat *seat;
|
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
wl_list_for_each(seat, &input->seats, link) {
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
struct roots_seat *seat;
|
||||||
|
wl_list_for_each(seat, &input->seats, link) {
|
||||||
roots_cursor_update_position(seat->cursor, timespec_to_msec(&now));
|
roots_cursor_update_position(seat->cursor, timespec_to_msec(&now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,16 +120,15 @@ static void drag_icons_for_each_surface(struct roots_input *input,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
struct roots_seat *seat;
|
struct roots_seat *seat;
|
||||||
wl_list_for_each(seat, &input->seats, link) {
|
wl_list_for_each(seat, &input->seats, link) {
|
||||||
struct roots_drag_icon *drag_icon;
|
struct roots_drag_icon *drag_icon = seat->drag_icon;
|
||||||
wl_list_for_each(drag_icon, &seat->drag_icons, link) {
|
if (drag_icon == NULL || !drag_icon->wlr_drag_icon->mapped) {
|
||||||
if (!drag_icon->wlr_drag_icon->mapped) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
surface_for_each_surface(drag_icon->wlr_drag_icon->surface,
|
surface_for_each_surface(drag_icon->wlr_drag_icon->surface,
|
||||||
drag_icon->x, drag_icon->y, 0, layout_data,
|
drag_icon->x, drag_icon->y, 0, layout_data,
|
||||||
iterator, user_data);
|
iterator, user_data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void layer_for_each_surface(struct wl_list *layer,
|
static void layer_for_each_surface(struct wl_list *layer,
|
||||||
|
|
|
@ -594,7 +594,9 @@ static void roots_drag_icon_handle_destroy(struct wl_listener *listener,
|
||||||
wl_container_of(listener, icon, destroy);
|
wl_container_of(listener, icon, destroy);
|
||||||
roots_drag_icon_damage_whole(icon);
|
roots_drag_icon_damage_whole(icon);
|
||||||
|
|
||||||
wl_list_remove(&icon->link);
|
assert(icon->seat->drag_icon == icon);
|
||||||
|
icon->seat->drag_icon = NULL;
|
||||||
|
|
||||||
wl_list_remove(&icon->surface_commit.link);
|
wl_list_remove(&icon->surface_commit.link);
|
||||||
wl_list_remove(&icon->unmap.link);
|
wl_list_remove(&icon->unmap.link);
|
||||||
wl_list_remove(&icon->destroy.link);
|
wl_list_remove(&icon->destroy.link);
|
||||||
|
@ -622,7 +624,8 @@ static void roots_seat_handle_new_drag_icon(struct wl_listener *listener,
|
||||||
icon->destroy.notify = roots_drag_icon_handle_destroy;
|
icon->destroy.notify = roots_drag_icon_handle_destroy;
|
||||||
wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
|
wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
|
||||||
|
|
||||||
wl_list_insert(&seat->drag_icons, &icon->link);
|
assert(seat->drag_icon == NULL);
|
||||||
|
seat->drag_icon = icon;
|
||||||
|
|
||||||
roots_drag_icon_update_position(icon);
|
roots_drag_icon_update_position(icon);
|
||||||
}
|
}
|
||||||
|
@ -706,7 +709,6 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
|
||||||
wl_list_init(&seat->tablet_pads);
|
wl_list_init(&seat->tablet_pads);
|
||||||
wl_list_init(&seat->switches);
|
wl_list_init(&seat->switches);
|
||||||
wl_list_init(&seat->views);
|
wl_list_init(&seat->views);
|
||||||
wl_list_init(&seat->drag_icons);
|
|
||||||
|
|
||||||
seat->input = input;
|
seat->input = input;
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ static void drag_end(struct wlr_drag *drag) {
|
||||||
drag_icon_set_mapped(drag->icon, false);
|
drag_icon_set_mapped(drag->icon, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(drag->seat->drag == drag);
|
||||||
|
drag->seat->drag = NULL;
|
||||||
|
|
||||||
wlr_signal_emit_safe(&drag->events.destroy, drag);
|
wlr_signal_emit_safe(&drag->events.destroy, drag);
|
||||||
free(drag);
|
free(drag);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +177,9 @@ static uint32_t drag_handle_pointer_button(struct wlr_seat_pointer_grab *grab,
|
||||||
};
|
};
|
||||||
wlr_signal_emit_safe(&drag->events.drop, &event);
|
wlr_signal_emit_safe(&drag->events.drop, &event);
|
||||||
} else if (drag->source->impl->dnd_finish) {
|
} else if (drag->source->impl->dnd_finish) {
|
||||||
|
// This will end the grab and free `drag`
|
||||||
wlr_data_source_destroy(drag->source);
|
wlr_data_source_destroy(drag->source);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,6 +437,13 @@ bool seat_client_start_drag(struct wlr_seat_client *client,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (seat->drag != NULL) {
|
||||||
|
wlr_log(WLR_DEBUG, "Refusing to start drag, "
|
||||||
|
"another drag is already in progress");
|
||||||
|
free(drag);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (icon_surface) {
|
if (icon_surface) {
|
||||||
int32_t touch_id = (point ? point->touch_id : 0);
|
int32_t touch_id = (point ? point->touch_id : 0);
|
||||||
struct wlr_drag_icon *icon =
|
struct wlr_drag_icon *icon =
|
||||||
|
|
|
@ -187,6 +187,13 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat,
|
||||||
|
|
||||||
wlr_seat->pointer_state.focused_client = client;
|
wlr_seat->pointer_state.focused_client = client;
|
||||||
wlr_seat->pointer_state.focused_surface = surface;
|
wlr_seat->pointer_state.focused_surface = surface;
|
||||||
|
if (surface != NULL) {
|
||||||
|
wlr_seat->pointer_state.sx = sx;
|
||||||
|
wlr_seat->pointer_state.sy = sy;
|
||||||
|
} else {
|
||||||
|
wlr_seat->pointer_state.sx = NAN;
|
||||||
|
wlr_seat->pointer_state.sy = NAN;
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_seat_pointer_focus_change_event event = {
|
struct wlr_seat_pointer_focus_change_event event = {
|
||||||
.seat = wlr_seat,
|
.seat = wlr_seat,
|
||||||
|
@ -209,6 +216,10 @@ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlr_seat->pointer_state.sx == sx && wlr_seat->pointer_state.sy == sy) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
wl_resource_for_each(resource, &client->pointers) {
|
wl_resource_for_each(resource, &client->pointers) {
|
||||||
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
|
if (wlr_seat_client_from_pointer_resource(resource) == NULL) {
|
||||||
|
@ -218,6 +229,9 @@ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time,
|
||||||
wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx),
|
wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx),
|
||||||
wl_fixed_from_double(sy));
|
wl_fixed_from_double(sy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlr_seat->pointer_state.sx = sx;
|
||||||
|
wlr_seat->pointer_state.sy = sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
|
uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time,
|
||||||
|
|
Loading…
Reference in New Issue