summaryrefslogtreecommitdiff
path: root/src/wayland/drag.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wayland/drag.c')
-rw-r--r--src/wayland/drag.c241
1 files changed, 0 insertions, 241 deletions
diff --git a/src/wayland/drag.c b/src/wayland/drag.c
deleted file mode 100644
index 989dbb6..0000000
--- a/src/wayland/drag.c
+++ /dev/null
@@ -1,241 +0,0 @@
-#include "internal.h"
-
-static void icon_clear(struct drag_icon *icon)
-{
- if (icon->viewport) wp_viewport_destroy(icon->viewport);
- if (icon->surface) wl_surface_destroy(icon->surface);
- if (icon->buffer) wl_buffer_destroy(icon->buffer);
- if (icon->pool) wl_shm_pool_destroy(icon->pool);
- if (icon->mapping) munmap(icon->mapping, icon->size);
- if (icon->pool) close(icon->fd);
- *icon = (struct drag_icon){0};
-}
-
-static bool icon_create(struct wayland_display *c, const struct yasl_drag_image *image)
-{
- struct drag_icon *icon = &c->drag.icon;
- size_t bytes;
- if (!image->pixels || !buffer_size(image->size.x, image->size.y, &bytes))
- return false;
- int fd = memfd_create("yasl_drag_icon", MFD_CLOEXEC | MFD_ALLOW_SEALING);
- if (fd < 0)
- return false;
- void *mapping = MAP_FAILED;
- if (ftruncate(fd, (off_t)bytes) == 0 &&
- fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK) == 0)
- mapping = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (mapping == MAP_FAILED) {
- close(fd);
- return false;
- }
- memcpy(mapping, image->pixels, bytes);
- icon->mapping = mapping;
- icon->size = bytes;
- icon->pool = wl_shm_create_pool(c->shm, fd, (int32_t)bytes);
- if (!icon->pool) {
- close(fd);
- icon_clear(icon);
- return false;
- }
- icon->fd = fd;
- icon->buffer = wl_shm_pool_create_buffer(icon->pool, 0, image->size.x,
- image->size.y, image->size.x * 4, WL_SHM_FORMAT_ARGB8888);
- icon->surface = wl_compositor_create_surface(c->compositor);
- if (!icon->buffer || !icon->surface) {
- icon_clear(icon);
- return false;
- }
- return true;
-}
-
-static void icon_show(struct wayland_display *c, const struct yasl_drag_image *image)
-{
- struct drag_icon *icon = &c->drag.icon;
- uint32_t scale = c->drag.scale_120;
- if (c->viewporter) {
- icon->viewport = wp_viewporter_get_viewport(c->viewporter, icon->surface);
- if (icon->viewport)
- wp_viewport_set_destination(icon->viewport,
- yasl_scale_to_logical(image->size.x, scale),
- yasl_scale_to_logical(image->size.y, scale));
- } else if (scale % YASL_SCALE_UNIT == 0 &&
- wl_proxy_get_version((struct wl_proxy *)icon->surface) >=
- WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) {
- wl_surface_set_buffer_scale(icon->surface, (int32_t)(scale / YASL_SCALE_UNIT));
- }
- if (wl_proxy_get_version((struct wl_proxy *)icon->surface) >=
- WL_SURFACE_OFFSET_SINCE_VERSION)
- wl_surface_offset(icon->surface,
- -yasl_scale_to_logical(image->hotspot.x, scale),
- -yasl_scale_to_logical(image->hotspot.y, scale));
- wl_surface_attach(icon->surface, icon->buffer, 0, 0);
- wl_surface_damage_buffer(icon->surface, 0, 0, image->size.x, image->size.y);
- wl_surface_commit(icon->surface);
-}
-
-static void drag_clear(struct wayland_display *c, bool ended)
-{
- struct conn_drag *d = &c->drag;
- if (d->toplevel) {
- if (ended)
- xdg_toplevel_drag_v1_destroy(d->toplevel);
- else
- wl_proxy_destroy((struct wl_proxy *)d->toplevel);
- }
- if (d->source)
- wl_data_source_destroy(d->source);
- icon_clear(&d->icon);
- *d = (struct conn_drag){0};
-}
-
-static void drag_finish(struct wayland_display *c, enum yasl_drag_end how, bool ended)
-{
- struct yasl_drag_listener l = c->drag.listener;
- void *ud = c->drag.ud;
- drag_clear(c, ended);
- if (l.end)
- l.end(ud, how);
-}
-
-void conn_drag_end(struct wayland_display *c)
-{
- if (c && c->drag.source)
- drag_finish(c, YASL_DRAG_CANCELLED, false);
-}
-
-static void source_target(void *ud, struct wl_data_source *s, const char *mime) { (void)ud; (void)s; (void)mime; }
-static void source_send(void *ud, struct wl_data_source *s, const char *mime, int32_t fd) { (void)ud; (void)s; (void)mime; close(fd); }
-static void source_action(void *ud, struct wl_data_source *s, uint32_t action) { (void)ud; (void)s; (void)action; }
-
-static void source_cancelled(void *ud, struct wl_data_source *s)
-{
- (void)s;
- struct wayland_display *c = ud;
- bool released = c->drag.dropped;
- drag_finish(c, released ? YASL_DRAG_DROPPED : YASL_DRAG_CANCELLED, true);
-}
-
-static void source_dropped(void *ud, struct wl_data_source *s)
-{
- (void)s;
- ((struct wayland_display *)ud)->drag.dropped = true;
-}
-
-static void source_finished(void *ud, struct wl_data_source *s)
-{
- (void)s;
- drag_finish(ud, YASL_DRAG_DROPPED, true);
-}
-
-static const struct wl_data_source_listener source_listener = {
- .target = source_target,
- .send = source_send,
- .cancelled = source_cancelled,
- .dnd_drop_performed = source_dropped,
- .dnd_finished = source_finished,
- .action = source_action,
-};
-
-static struct seat *drag_seat(struct wayland_display *c, struct wayland_surface *origin)
-{
- struct wayland_surface *root = surface_root(origin);
- struct seat *active = conn_active_seat(c);
- if (active && active->press_serial &&
- surface_root(active->press_surface) == root)
- return active;
- for (struct seat *s = c->seats; s; s = s->next)
- if (s->press_serial && surface_root(s->press_surface) == root)
- return s;
- return NULL;
-}
-
-bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surface *origin,
- const struct yasl_drag_image *image,
- const struct yasl_drag_listener *l, void *ud)
-{
- if (!c || !origin || origin->conn != c || !l || c->drag.source)
- return false;
- struct seat *seat = drag_seat(c, origin);
- if (!seat)
- return false;
- struct wl_data_device *device = clipboard_data_device(seat->clipboard);
- if (!device || wl_data_device_get_version(device) < 3)
- return false;
- c->drag.scale_120 = origin->scale_120;
- if (image && !icon_create(c, image))
- return false;
- struct wl_data_source *s = wl_data_device_manager_create_data_source(c->data_manager);
- if (!s) {
- icon_clear(&c->drag.icon);
- return false;
- }
- c->drag.source = s;
- c->drag.seat = seat;
- c->drag.listener = *l;
- c->drag.ud = ud;
- wl_data_source_add_listener(s, &source_listener, c);
- wl_data_source_offer(s, clipboard_drag_mime());
- wl_data_source_set_actions(s, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE);
- if (c->toplevel_drag_mgr)
- c->drag.toplevel = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(
- c->toplevel_drag_mgr, s);
- wl_data_device_start_drag(device, s, seat->press_surface->surface,
- c->drag.icon.surface, seat->press_serial);
- if (image)
- icon_show(c, image);
- wl_display_flush(c->wl);
- return true;
-}
-
-void wayland_display_drag_cancel(struct wayland_display *c)
-{
- if (c && c->drag.source)
- drag_finish(c, YASL_DRAG_CANCELLED, false);
-}
-
-bool wayland_surface_drag_carry(struct wayland_surface *w, struct yasl_vector2i offset)
-{
- struct wayland_display *c = w ? w->conn : NULL;
- if (!c || !c->drag.source || !c->drag.toplevel || !w->toplevel)
- return false;
- uint32_t scale = c->drag.scale_120;
- xdg_toplevel_drag_v1_attach(c->drag.toplevel, w->toplevel,
- yasl_scale_to_logical(offset.x, scale),
- yasl_scale_to_logical(offset.y, scale));
- c->drag.carrying = true;
- return true;
-}
-
-bool wayland_surface_place_under_pointer(struct wayland_surface *w, struct yasl_vector2i at)
-{
- (void)w;
- (void)at;
- return false;
-}
-
-static struct yasl_vector2i drag_device_pos(const struct wayland_surface *w, double x, double y)
-{
- double dx = x * w->scale_factor, dy = y * w->scale_factor;
- return (struct yasl_vector2i){
- .x = (int)(dx < 0 ? dx - 0.5 : dx + 0.5),
- .y = (int)(dy < 0 ? dy - 0.5 : dy + 0.5),
- };
-}
-
-void conn_drop_target(struct wayland_display *c, enum yasl_drop_event ev,
- struct wl_surface *on, double x, double y)
-{
- struct wayland_surface *w = conn_surface_for(c, on);
- if (!w || w->parent || !w->cbs->drop)
- return;
- w->cbs->drop(&w->base, ev, drag_device_pos(w, x, y), w->ud);
-}
-
-void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev,
- struct wl_surface *on, double x, double y)
-{
- struct wayland_surface *w = conn_surface_for(c, on);
- if (!w || w->parent || !w->cbs->drag)
- return;
- w->cbs->drag(&w->base, ev, drag_device_pos(w, x, y), w->ud);
-}