From df0a8d3abe6a7a8cd010e07f078c0e92ea2fb516 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sun, 15 Oct 2017 11:06:03 -0400 Subject: [PATCH] wlr-data-device: drag icons --- include/rootston/input.h | 11 +++++++ include/wlr/types/wlr_data_device.h | 3 ++ rootston/cursor.c | 49 +++++++++++++++++++++++++++++ rootston/input.c | 2 ++ rootston/main.c | 4 +-- rootston/output.c | 15 +++++++++ types/wlr_data_device.c | 8 +++-- types/wlr_surface.c | 2 ++ 8 files changed, 89 insertions(+), 5 deletions(-) diff --git a/include/rootston/input.h b/include/rootston/input.h index fbabbdb6..8b4fc3b3 100644 --- a/include/rootston/input.h +++ b/include/rootston/input.h @@ -70,6 +70,15 @@ struct roots_input_event { struct wlr_input_device *device; }; +struct roots_drag_icon { + struct wlr_surface *surface; + struct wl_list link; // roots_input::drag_icons + bool mapped; + + struct wl_listener surface_destroy; + struct wl_listener surface_commit; +}; + struct roots_input { struct roots_config *config; struct roots_server *server; @@ -80,6 +89,7 @@ struct roots_input { struct wlr_xcursor *xcursor; struct wlr_seat *wl_seat; struct roots_view *client_cursor_view; + struct wl_list drag_icons; enum roots_cursor_mode mode; struct roots_view *active_view, *last_active_view; @@ -107,6 +117,7 @@ struct roots_input { struct wl_listener cursor_tool_axis; struct wl_listener cursor_tool_tip; + struct wl_listener pointer_grab_begin; struct wl_listener pointer_grab_end; struct wl_listener request_set_cursor; diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index cb867741..6c5dc097 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -4,6 +4,9 @@ #include #include +extern const struct +wlr_pointer_grab_interface wlr_data_device_pointer_drag_interface; + struct wlr_data_device_manager { struct wl_global *global; }; diff --git a/rootston/cursor.c b/rootston/cursor.c index 8790934c..19f015aa 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -1,8 +1,10 @@ #define _XOPEN_SOURCE 700 +#include #include #include #include #include +#include #ifdef __linux__ #include #elif __FreeBSD__ @@ -11,6 +13,7 @@ #include #include #include +#include #include "rootston/config.h" #include "rootston/input.h" #include "rootston/desktop.h" @@ -289,6 +292,49 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { (uint32_t)(event->time_usec / 1000), BTN_LEFT, event->state); } +static void handle_drag_icon_destroy(struct wl_listener *listener, void *data) { + struct roots_drag_icon *drag_icon = + wl_container_of(listener, drag_icon, surface_destroy); + wl_list_remove(&drag_icon->link); + wl_list_remove(&drag_icon->surface_destroy.link); + wl_list_remove(&drag_icon->surface_commit.link); + free(drag_icon); +} + +static void handle_drag_icon_commit(struct wl_listener *listener, void *data) { + struct roots_drag_icon *drag_icon = + wl_container_of(listener, drag_icon, surface_commit); + // TODO the spec hints at rules that can determine whether the drag icon is + // mapped here, but it is not completely clear so we need to test more + // toolkits to see how we should interpret the surface state here. + drag_icon->mapped = drag_icon->surface->texture->valid; +} + +static void handle_pointer_grab_begin(struct wl_listener *listener, + void *data) { + struct roots_input *input = + wl_container_of(listener, input, pointer_grab_begin); + struct wlr_seat_pointer_grab *grab = data; + + if (grab->interface == &wlr_data_device_pointer_drag_interface) { + struct wlr_drag *drag = grab->data; + if (drag->icon) { + struct roots_drag_icon *drag_icon = + calloc(1, sizeof(struct roots_drag_icon)); + drag_icon->surface = drag->icon; + wl_list_insert(&input->drag_icons, &drag_icon->link); + + wl_signal_add(&drag->icon->events.destroy, + &drag_icon->surface_destroy); + drag_icon->surface_destroy.notify = handle_drag_icon_destroy; + + wl_signal_add(&drag->icon->events.commit, + &drag_icon->surface_commit); + drag_icon->surface_commit.notify = handle_drag_icon_commit; + } + } +} + static void handle_pointer_grab_end(struct wl_listener *listener, void *data) { struct roots_input *input = wl_container_of(listener, input, pointer_grab_end); @@ -358,6 +404,9 @@ void cursor_initialize(struct roots_input *input) { wl_signal_add(&input->wl_seat->events.pointer_grab_end, &input->pointer_grab_end); input->pointer_grab_end.notify = handle_pointer_grab_end; + wl_signal_add(&input->wl_seat->events.pointer_grab_begin, &input->pointer_grab_begin); + input->pointer_grab_begin.notify = handle_pointer_grab_begin; + wl_list_init(&input->request_set_cursor.link); wl_signal_add(&input->wl_seat->events.request_set_cursor, &input->request_set_cursor); diff --git a/rootston/input.c b/rootston/input.c index 86a87e24..f08b735a 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -110,6 +110,8 @@ struct roots_input *input_create(struct roots_server *server, cursor_load_config(config, input->cursor, input, server->desktop); + wl_list_init(&input->drag_icons); + return input; } diff --git a/rootston/main.c b/rootston/main.c index 81343dfc..f262a30f 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -19,11 +19,11 @@ int main(int argc, char **argv) { assert(server.backend = wlr_backend_autocreate(server.wl_display)); assert(server.renderer = wlr_gles2_renderer_create(server.backend)); + server.data_device_manager = + wlr_data_device_manager_create(server.wl_display); wl_display_init_shm(server.wl_display); server.desktop = desktop_create(&server, server.config); server.input = input_create(&server, server.config); - server.data_device_manager = - wlr_data_device_manager_create(server.wl_display); const char *socket = wl_display_add_socket_auto(server.wl_display); if (!socket) { diff --git a/rootston/output.c b/rootston/output.c index 39a90fe3..b431cbc3 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -150,6 +150,21 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { render_view(view, desktop, wlr_output, &now); } + struct roots_drag_icon *drag_icon = NULL; + wl_list_for_each(drag_icon, &server->input->drag_icons, link) { + if (!drag_icon->mapped) { + continue; + } + + struct wlr_surface *icon = drag_icon->surface; + struct wlr_cursor *cursor = server->input->cursor; + // TODO should also use the hotspot to determine the location, but + // hotspot is broken right now. + double icon_x = cursor->x - icon->current->sx; + double icon_y = cursor->y - icon->current->sy; + render_surface(icon, desktop, wlr_output, &now, icon_x, icon_y, 0); + } + wlr_renderer_end(server->renderer); wlr_output_swap_buffers(wlr_output); diff --git a/types/wlr_data_device.c b/types/wlr_data_device.c index e9c0aa10..5c6d5717 100644 --- a/types/wlr_data_device.c +++ b/types/wlr_data_device.c @@ -495,7 +495,8 @@ static void pointer_drag_cancel(struct wlr_seat_pointer_grab *grab) { wlr_drag_end(drag); } -static const struct wlr_pointer_grab_interface pointer_drag_interface = { +const struct +wlr_pointer_grab_interface wlr_data_device_pointer_drag_interface = { .enter = pointer_drag_enter, .motion = pointer_drag_motion, .button = pointer_drag_button, @@ -521,7 +522,8 @@ static bool seat_handle_start_drag(struct wlr_seat_handle *handle, return false; } - if (drag->icon) { + if (icon) { + drag->icon = icon; drag->icon_destroy.notify = drag_handle_icon_destroy; wl_signal_add(&icon->events.destroy, &drag->icon_destroy); drag->icon = icon; @@ -535,7 +537,7 @@ static bool seat_handle_start_drag(struct wlr_seat_handle *handle, drag->handle = handle; drag->pointer_grab.data = drag; - drag->pointer_grab.interface = &pointer_drag_interface; + drag->pointer_grab.interface = &wlr_data_device_pointer_drag_interface; wlr_seat_pointer_clear_focus(handle->wlr_seat); diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 9e38d701..6e56d6aa 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -269,6 +269,8 @@ static void wlr_surface_move_state(struct wlr_surface *surface, struct wlr_surfa wlr_surface_state_release_buffer(state); wlr_surface_state_set_buffer(state, next->buffer); wlr_surface_state_reset_buffer(next); + state->sx = next->sx; + state->sy = next->sy; update_size = true; } if (update_size) {