diff --git a/output.c b/output.c index e222c5d..d90c102 100644 --- a/output.c +++ b/output.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,25 @@ render_surface(struct wlr_surface *surface, int sx, int sy, void *data) wlr_surface_send_frame_done(surface, rdata->when); } +static void +drag_icons_for_each_surface(struct cg_server *server, wlr_surface_iterator_func_t iterator, + void *data) +{ + struct render_data *rdata = data; + + struct cg_drag_icon *drag_icon; + wl_list_for_each(drag_icon, &server->seat->drag_icons, link) { + if (!drag_icon->wlr_drag_icon->mapped) { + continue; + } + rdata->x = drag_icon->x; + rdata->y = drag_icon->y; + wlr_surface_for_each_surface(drag_icon->wlr_drag_icon->surface, + iterator, + data); + } +} + static void handle_output_frame(struct wl_listener *listener, void *data) { @@ -119,6 +139,8 @@ handle_output_frame(struct wl_listener *listener, void *data) } } + drag_icons_for_each_surface(output->server, render_surface, &rdata); + wlr_renderer_end(renderer); wlr_output_swap_buffers(output->wlr_output, NULL, NULL); } diff --git a/seat.c b/seat.c index 468ca3c..4c7ccec 100644 --- a/seat.c +++ b/seat.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #include "server.h" #include "view.h" +static void drag_icon_update_position(struct cg_drag_icon *drag_icon); + bool have_dialogs_open(struct cg_server *server) { @@ -496,6 +499,11 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time) } } + struct cg_drag_icon *drag_icon; + wl_list_for_each(drag_icon, &seat->drag_icons, link) { + drag_icon_update_position(drag_icon); + } + wlr_idle_notify_activity(seat->server->idle, seat->seat); } @@ -521,6 +529,57 @@ handle_cursor_motion(struct wl_listener *listener, void *data) wlr_idle_notify_activity(seat->server->idle, seat->seat); } +static void +drag_icon_update_position(struct cg_drag_icon *drag_icon) +{ + struct wlr_drag_icon *wlr_icon = drag_icon->wlr_drag_icon; + struct cg_seat *seat = drag_icon->seat; + + if (wlr_icon->is_pointer) { + drag_icon->x = seat->cursor->x; + drag_icon->y = seat->cursor->y; + } else { + struct wlr_touch_point *point = + wlr_seat_touch_get_point(seat->seat, wlr_icon->touch_id); + if (!point) { + return; + } + drag_icon->x = seat->touch_x; + drag_icon->y = seat->touch_y; + } +} + +static void +handle_drag_icon_destroy(struct wl_listener *listener, void *data) +{ + struct cg_drag_icon *drag_icon = wl_container_of(listener, drag_icon, destroy); + + wl_list_remove(&drag_icon->link); + wl_list_remove(&drag_icon->destroy.link); + free(drag_icon); +} + +static void +handle_new_drag_icon(struct wl_listener *listener, void *data) +{ + struct cg_seat *seat = wl_container_of(listener, seat, new_drag_icon); + struct wlr_drag_icon *wlr_drag_icon = data; + + struct cg_drag_icon *drag_icon = calloc(1, sizeof(struct cg_drag_icon)); + if (!drag_icon) { + return; + } + drag_icon->seat = seat; + drag_icon->wlr_drag_icon = wlr_drag_icon; + + drag_icon->destroy.notify = handle_drag_icon_destroy; + wl_signal_add(&wlr_drag_icon->events.destroy, &drag_icon->destroy); + + wl_list_insert(&seat->drag_icons, &drag_icon->link); + + drag_icon_update_position(drag_icon); +} + static void handle_destroy(struct wl_listener *listener, void *data) { @@ -620,6 +679,10 @@ cg_seat_create(struct cg_server *server) seat->new_input.notify = handle_new_input; wl_signal_add(&server->backend->events.new_input, &seat->new_input); + wl_list_init(&seat->drag_icons); + seat->new_drag_icon.notify = handle_new_drag_icon; + wl_signal_add(&seat->seat->events.new_drag_icon, &seat->new_drag_icon); + return seat; } diff --git a/seat.h b/seat.h index cb012eb..ab84abf 100644 --- a/seat.h +++ b/seat.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -37,6 +38,9 @@ struct cg_seat { struct wl_listener touch_up; struct wl_listener touch_motion; + struct wl_list drag_icons; + struct wl_listener new_drag_icon; + struct wl_listener request_set_cursor; }; @@ -66,6 +70,17 @@ struct cg_touch { struct wl_listener destroy; }; +struct cg_drag_icon { + struct wl_list link; // seat::drag_icons + struct cg_seat *seat; + struct wlr_drag_icon *wlr_drag_icon; + double x; + double y; + + struct wl_listener surface_commit; + struct wl_listener destroy; +}; + struct cg_seat *cg_seat_create(struct cg_server *server); void cg_seat_destroy(struct cg_seat *seat); struct cg_view *seat_get_focus(struct cg_seat *seat);