From 6bf3bb97f59282886e18b98ae38e8a67a1c3a91d Mon Sep 17 00:00:00 2001 From: ARDiDo <90479315+ARDiDo@users.noreply.github.com> Date: Sun, 3 Oct 2021 13:33:38 -0400 Subject: [PATCH 1/3] implement basic drag and drop --- include/labwc.h | 5 +++++ src/cursor.c | 43 ++++++++++++++++++++++++++++++++++++++++++- src/output.c | 23 +++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/labwc.h b/include/labwc.h index 2da1deb9..f9ad4227 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -61,6 +61,7 @@ struct seat { struct wlr_keyboard_group *keyboard_group; struct wlr_cursor *cursor; struct wlr_xcursor_manager *xcursor_manager; + struct wlr_drag_icon *drag_icon; /* if set, views cannot receive focus */ struct wlr_layer_surface_v1 *focused_layer; @@ -81,6 +82,10 @@ struct seat { struct wl_listener keyboard_key; struct wl_listener keyboard_modifiers; + + struct wl_listener request_start_drag; + struct wl_listener start_drag; + struct wl_listener destroy_drag; }; struct server { diff --git a/src/cursor.c b/src/cursor.c index a6fae287..46d33ca1 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -57,6 +57,19 @@ request_set_primary_selection_notify(struct wl_listener *listener, void *data) event->serial); } +static void +request_start_drag_notify(struct wl_listener *listener, void *data) +{ + struct seat *seat = wl_container_of( + listener, seat, request_start_drag); + struct wlr_seat_request_start_drag_event *event = data; + if (wlr_seat_validate_pointer_grab_serial(seat->seat, event->origin, event->serial)) { + wlr_seat_start_pointer_drag(seat->seat, event->drag, event->serial); + } else { + wlr_data_source_destroy(event->drag->source); + } +} + static void process_cursor_move(struct server *server, uint32_t time) { @@ -190,7 +203,7 @@ process_cursor_motion(struct server *server, uint32_t time) * the pointer over a window. */ wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy); - if (!focus_changed) { + if (!focus_changed || server->seat.drag_icon) { /* * The enter event contains coordinates, so we only need * to notify on motion if the focus did not change. @@ -206,6 +219,15 @@ process_cursor_motion(struct server *server, uint32_t time) } } +void +start_drag(struct wl_listener *listener, void *data) +{ + struct seat *seat = wl_container_of(listener, seat, start_drag); + struct wlr_drag *wlr_drag = data; + seat->drag_icon = wlr_drag->icon; + wl_signal_add(&seat->drag_icon->events.destroy, &seat->destroy_drag); +} + static void cursor_motion(struct wl_listener *listener, void *data) { @@ -228,6 +250,18 @@ cursor_motion(struct wl_listener *listener, void *data) process_cursor_motion(seat->server, event->time_msec); } +void +destroy_drag(struct wl_listener *listener, void *data) +{ + struct seat *seat = wl_container_of(listener, seat, destroy_drag); + + if (!seat->drag_icon) { + return; + } + seat->drag_icon = NULL; + desktop_focus_topmost_mapped_view(seat->server); +} + void cursor_motion_absolute(struct wl_listener *listener, void *data) { @@ -442,6 +476,13 @@ cursor_init(struct seat *seat) seat->request_set_selection.notify = request_set_selection_notify; wl_signal_add(&seat->seat->events.request_set_selection, &seat->request_set_selection); + seat->request_start_drag.notify = request_start_drag_notify; + wl_signal_add(&seat->seat->events.request_start_drag, + &seat->request_start_drag); + seat->start_drag.notify = start_drag; + wl_signal_add(&seat->seat->events.start_drag, + &seat->start_drag); + seat->destroy_drag.notify = destroy_drag; seat->request_set_primary_selection.notify = request_set_primary_selection_notify; diff --git a/src/output.c b/src/output.c index 78d90c6c..5a7c9319 100644 --- a/src/output.c +++ b/src/output.c @@ -179,6 +179,26 @@ render_surface_iterator(struct output *output, struct wlr_surface *surface, render_texture(wlr_output, output_damage, texture, box, matrix); } +void +output_drag_icon_for_each_surface(struct output *output, struct seat *seat, + surface_iterator_func_t iterator, void *user_data) +{ + if (!seat->drag_icon || !seat->drag_icon->mapped) { + return; + } + output_surface_for_each_surface(output, seat->drag_icon->surface, + seat->cursor->x, seat->cursor->y, iterator, user_data); +} + +static void +render_drag_icon(struct output *output, pixman_region32_t *damage) +{ + struct render_data data = { + .damage = damage, + }; + output_drag_icon_for_each_surface(output, &output->server->seat, render_surface_iterator, &data); +} + #if HAVE_XWAYLAND void output_unmanaged_for_each_surface(struct output *output, @@ -290,6 +310,7 @@ output_for_each_surface(struct output *output, surface_iterator_func_t iterator, output_layer_for_each_surface(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], iterator, user_data); + output_drag_icon_for_each_surface(output, &output->server->seat, iterator, user_data); } struct send_frame_done_data { @@ -707,6 +728,8 @@ output_render(struct output *output, pixman_region32_t *damage) render_osd(output, damage, output->server); } + render_drag_icon(output, damage); + render_layer_toplevel(output, damage, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); render_layer_toplevel(output, damage, From 565f0daee90bcc755d9a85debe8d090e3d93241a Mon Sep 17 00:00:00 2001 From: ARDiDo <90479315+ARDiDo@users.noreply.github.com> Date: Sun, 3 Oct 2021 14:21:32 -0400 Subject: [PATCH 2/3] drag across monitor --- src/output.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/output.c b/src/output.c index 5a7c9319..a4d0ded0 100644 --- a/src/output.c +++ b/src/output.c @@ -186,8 +186,11 @@ output_drag_icon_for_each_surface(struct output *output, struct seat *seat, if (!seat->drag_icon || !seat->drag_icon->mapped) { return; } + double ox = seat->cursor->x, oy = seat->cursor->y; + wlr_output_layout_output_coords(output->server->output_layout, + output->wlr_output, &ox, &oy); output_surface_for_each_surface(output, seat->drag_icon->surface, - seat->cursor->x, seat->cursor->y, iterator, user_data); + ox, oy, iterator, user_data); } static void From 6b9d3f4083b4acfc5f265065fb383a84a990e4d4 Mon Sep 17 00:00:00 2001 From: ARDiDo <90479315+ARDiDo@users.noreply.github.com> Date: Sun, 3 Oct 2021 16:19:42 -0400 Subject: [PATCH 3/3] fix build errors --- src/xdg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/xdg.c b/src/xdg.c index 1eff1640..080cee42 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -35,7 +35,7 @@ has_ssd(struct view *view) * geometry.{x,y} seems to be greater than zero. We filter on that * on the assumption that this will remain true. */ - if (view->xdg_surface->geometry.x || view->xdg_surface->geometry.y) { + if (view->xdg_surface->current.geometry.x || view->xdg_surface->current.geometry.y) { return false; } return true; @@ -57,7 +57,7 @@ handle_commit(struct wl_listener *listener, void *data) view->padding.left = view->padding.right = size.x; uint32_t serial = view->pending_move_resize.configure_serial; - if (serial > 0 && serial >= view->xdg_surface->configure_serial) { + if (serial > 0 && serial >= view->xdg_surface->current.configure_serial) { if (view->pending_move_resize.update_x) { view->x = view->pending_move_resize.x + view->pending_move_resize.width - size.width; @@ -66,7 +66,7 @@ handle_commit(struct wl_listener *listener, void *data) view->y = view->pending_move_resize.y + view->pending_move_resize.height - size.height; } - if (serial == view->xdg_surface->configure_serial) { + if (serial == view->xdg_surface->current.configure_serial) { view->pending_move_resize.configure_serial = 0; } } @@ -258,8 +258,8 @@ position_xdg_toplevel_view(struct view *view) output_usable_area_from_cursor_coords(view->server); view->x = box.x; view->y = box.y; - view->w = view->xdg_surface->geometry.width; - view->h = view->xdg_surface->geometry.height; + view->w = view->xdg_surface->current.geometry.width; + view->h = view->xdg_surface->current.geometry.height; if (view->w && view->h) { view_center(view); } @@ -272,8 +272,8 @@ position_xdg_toplevel_view(struct view *view) assert(parent); int center_x = parent->x + parent->w / 2; int center_y = parent->y + parent->h / 2; - view->x = center_x - view->xdg_surface->geometry.width / 2; - view->y = center_y - view->xdg_surface->geometry.height / 2; + view->x = center_x - view->xdg_surface->current.geometry.width / 2; + view->y = center_y - view->xdg_surface->current.geometry.height / 2; } view->x += view->margin.left - view->padding.left; view->y += view->margin.top - view->padding.top;