summaryrefslogtreecommitdiff
path: root/src/cocoa
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 10:53:22 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 10:53:22 +0300
commit5206933399775e5ff46baefbbb3a776c2a9bb84c (patch)
treee7549216ac626c1f3ac22345f79fbf80cc5a90fb /src/cocoa
parent881fb6cb1d64868132287bd9637f4ae1cbc3504c (diff)
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.
Diffstat (limited to 'src/cocoa')
-rw-r--r--src/cocoa/window.m84
1 files changed, 75 insertions, 9 deletions
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 <QuartzCore/QuartzCore.h>
#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;
+}