From 5206933399775e5ff46baefbbb3a776c2a9bb84c Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Mon, 12 Oct 2026 10:53:22 +0300 Subject: feat: add type-safe native platform headers and portable drag support - Add include/yasl/native/{wayland,cocoa,x11}.h with type-safe handle accessors. - Unify drag-and-drop and window carry support across Wayland, X11, and Cocoa. - Preserve full ABI compatibility for capability flags. - Install native headers conditionally based on enabled backend. - Include missing tablet example and backend test suites. --- src/cocoa/window.m | 84 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 9 deletions(-) (limited to 'src/cocoa') diff --git a/src/cocoa/window.m b/src/cocoa/window.m index 6235b77..7b59865 100644 --- a/src/cocoa/window.m +++ b/src/cocoa/window.m @@ -3,6 +3,7 @@ #import #include "cocoa/api.h" +#include "yasl/native/cocoa.h" #include "common/timing.h" #include "common/loop.h" #include "cocoa/keycodes.h" @@ -112,6 +113,14 @@ struct cocoa_display { YaslAppDelegate *delegate; NSPoint cascade; struct cocoa_surface *dead; + struct { + bool active; + struct cocoa_surface *origin; + struct cocoa_surface *carried; + struct yasl_vector2i carry_offset; + struct yasl_drag_listener listener; + void *ud; + } drag; int depth; bool open; bool launched; @@ -121,6 +130,18 @@ struct cocoa_display { static struct cocoa_display darwin_ctx; +static void drag_end(struct cocoa_display *d, enum yasl_drag_end how) +{ + if (!d || !d->drag.active) return; + struct yasl_drag_listener l = d->drag.listener; + void *ud = d->drag.ud; + d->drag.active = false; + d->drag.origin = NULL; + d->drag.carried = NULL; + if (l.end) + l.end(ud, how); +} + static void render_and_commit(struct cocoa_surface *w); static void reap_dead(struct cocoa_display *d); @@ -341,6 +362,11 @@ static void push_pointer(struct cocoa_surface *w, NSEvent *ev, enum yasl_pointer }, }; input_queue_push(&w->input, &input_ev); + if (kind == YASL_PTR_MOTION && darwin_ctx.drag.active && darwin_ctx.drag.carried) { + cocoa_surface_place_under_pointer(darwin_ctx.drag.carried, darwin_ctx.drag.carry_offset); + } else if (kind == YASL_PTR_RELEASE && darwin_ctx.drag.active) { + drag_end(&darwin_ctx, YASL_DRAG_DROPPED); + } if (proximity) { w->tablet_device = YASL_PTR_DEV_MOUSE; w->tablet_down = false; @@ -1079,6 +1105,7 @@ struct cocoa_display *cocoa_display_open(struct yasl_loop *loop, const struct ya void cocoa_display_close(struct cocoa_display *d) { if (!d) return; + drag_end(d, YASL_DRAG_CANCELLED); assert(!d->count && "destroy every surface before its display"); reap_dead(d); if (d->key_up_monitor) { @@ -1101,7 +1128,8 @@ void cocoa_display_close(struct cocoa_display *d) uint32_t cocoa_display_caps(const struct cocoa_display *d) { - return d ? (YASL_CAP_PLACE_WINDOW | YASL_CAP_CSD | YASL_CAP_NATIVE_GRAPHICS | + return d ? (YASL_CAP_DRAG | YASL_CAP_DRAG_CARRY | YASL_CAP_PLACE_WINDOW | + YASL_CAP_CSD | YASL_CAP_NATIVE_GRAPHICS | YASL_CAP_FRAME_PACING | YASL_CAP_TABLET) : 0; } @@ -1220,6 +1248,8 @@ void cocoa_surface_destroy(struct cocoa_surface *w) { assert([NSThread isMainThread]); if (!w || w->destroyed) return; + if (darwin_ctx.drag.active && (darwin_ctx.drag.origin == w || darwin_ctx.drag.carried == w)) + drag_end(&darwin_ctx, YASL_DRAG_CANCELLED); darwin_ctx.depth++; bool native_closed = w->closed; static const struct yasl_surface_cbs no_callbacks = {0}; @@ -1374,22 +1404,40 @@ bool cocoa_surface_popup_reposition(struct cocoa_surface *popup, return false; } +bool cocoa_surface_start_interactive_move(struct cocoa_surface *s) +{ + if (!s || !s->window) return false; + [s->window performWindowDragWithEvent:[NSApp currentEvent]]; + return true; +} + bool cocoa_display_drag_start(struct cocoa_display *d, struct cocoa_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud) { - (void)d; (void)origin; (void)image; (void)l; (void)ud; - return false; + (void)image; + if (!d || !origin || d->drag.active || !l) + return false; + d->drag.active = true; + d->drag.origin = origin; + d->drag.carried = NULL; + d->drag.listener = *l; + d->drag.ud = ud; + return true; } -void cocoa_display_drag_cancel(struct cocoa_display *d) { (void)d; } -bool cocoa_surface_drag_carry(struct cocoa_surface *w, struct yasl_vector2i offset) { (void)w; (void)offset; return false; } +void cocoa_display_drag_cancel(struct cocoa_display *d) +{ + drag_end(d, YASL_DRAG_CANCELLED); +} -bool cocoa_surface_start_interactive_move(struct cocoa_surface *s) +bool cocoa_surface_drag_carry(struct cocoa_surface *w, struct yasl_vector2i offset) { - if (!s || !s->window) return false; - [s->window performWindowDragWithEvent:[NSApp currentEvent]]; - return true; + if (!w || w->closed || !darwin_ctx.drag.active) + return false; + darwin_ctx.drag.carried = w; + darwin_ctx.drag.carry_offset = offset; + return cocoa_surface_place_under_pointer(w, offset); } bool cocoa_surface_start_interactive_resize(struct cocoa_surface *s, enum yasl_resize_edge edge) @@ -1691,3 +1739,21 @@ const struct yasl_backend_ops yasl_cocoa_backend = { .surface_get_native_handle = impl_surface_get_native_handle, .surface_get_native_frame = impl_surface_get_native_frame, }; + +NSApplication *yasl_cocoa_display_get_application(struct yasl_display *d) +{ + return (d && yasl_display_backend(d) == YASL_BACKEND_COCOA) ? + (NSApplication *)yasl_display_get_native_handle(d) : nil; +} + +NSWindow *yasl_cocoa_surface_get_window(struct yasl_surface *s) +{ + return (s && s->display && yasl_display_backend(s->display) == YASL_BACKEND_COCOA) ? + (NSWindow *)yasl_surface_get_native_handle(s) : nil; +} + +NSView *yasl_cocoa_surface_get_view(struct yasl_surface *s) +{ + NSWindow *w = yasl_cocoa_surface_get_window(s); + return w ? w.contentView : nil; +} -- cgit v1.2.3