]> git.mdlowis.com Git - proto/labwc.git/commitdiff
implement basic drag and drop
authorARDiDo <90479315+ARDiDo@users.noreply.github.com>
Sun, 3 Oct 2021 17:33:38 +0000 (13:33 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 3 Oct 2021 20:50:29 +0000 (21:50 +0100)
include/labwc.h
src/cursor.c
src/output.c

index 2da1deb9604bf68abee4647087abb4c5df2c18b4..f9ad4227bc21deb81a9301ecadcbb7cdceff0fac 100644 (file)
@@ -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 {
index a6fae2878017695817dd3f595155d607760375f9..46d33ca1c63bd9067848c596bee3cfec36f32c93 100644 (file)
@@ -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;
index 78d90c6c3ef26487d274adfd8605cc1237621622..5a7c9319861667cf3d17854cc5f736ec404e53cd 100644 (file)
@@ -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,