summaryrefslogtreecommitdiff
path: root/src/common/surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/surface.c')
-rw-r--r--src/common/surface.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/src/common/surface.c b/src/common/surface.c
index 6b805be..683bbaa 100644
--- a/src/common/surface.c
+++ b/src/common/surface.c
@@ -669,6 +669,18 @@ int yasl_clipboard_request(yasl_surface *s, enum yasl_selection selection)
return -errno;
return STATUS(yasl_private_clipboard_request(s, (enum yasl_private_selection)selection) != 0);
}
+/* A drag that drops on no surface would end unheard, so its origin hears
+ * the end. ud is the origin's id: the origin may be gone by then. */
+static void drag_ended(void *ud, enum yasl_private_drag_end how)
+{
+ (void)how;
+ if (!display || display->drag_dropped)
+ return;
+ yasl_surface *origin = yasl_private_events_find(display, (uint64_t)(uintptr_t)ud);
+ if (origin)
+ yasl_private_surface_notify_drag(origin, YASL_PRIVATE_DRAG_CANCEL,
+ (struct yasl_private_vector2i){0, 0});
+}
int yasl_drag_start(yasl_surface *s, const struct yasl_drag_image *source)
{
if (!yasl_public_connected(s))
@@ -679,7 +691,10 @@ int yasl_drag_start(yasl_surface *s, const struct yasl_drag_image *source)
.pixels = source->pixels,
.size = {source->pixel_width, source->pixel_height},
.hotspot = {source->hotspot_x, source->hotspot_y}};
- return STATUS(yasl_private_display_drag_start(display, s, source ? &image : NULL, NULL, NULL));
+ display->drag_dropped = false;
+ const struct yasl_private_drag_listener listener = {.end = drag_ended};
+ return STATUS(yasl_private_display_drag_start(display, s, source ? &image : NULL, &listener,
+ (void *)(uintptr_t)s->id));
}
int yasl_drag_cancel(void)
{
@@ -886,9 +901,10 @@ static bool convert_event(const struct yasl_private_event *p, yasl_event *e)
return true;
case YASL_PRIVATE_EVENT_DRAG:
e->type = YASL_EVENT_DRAG;
- e->action = p->drag.action == YASL_PRIVATE_DRAG_OVER ? YASL_DROP_OVER
- : p->drag.action == YASL_PRIVATE_DRAG_LEAVE ? YASL_DROP_LEAVE
- : YASL_DROP_RELEASE;
+ e->action = p->drag.action == YASL_PRIVATE_DRAG_OVER ? YASL_DROP_OVER
+ : p->drag.action == YASL_PRIVATE_DRAG_LEAVE ? YASL_DROP_LEAVE
+ : p->drag.action == YASL_PRIVATE_DRAG_CANCEL ? YASL_DROP_CANCEL
+ : YASL_DROP_RELEASE;
e->x = p->drag.pos.x / scale;
e->y = p->drag.pos.y / scale;
return true;