summaryrefslogtreecommitdiff
path: root/src/cocoa
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 08:41:51 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 08:41:51 +0300
commit3b8af02be94a510e385f44d58c35c86bb89424a6 (patch)
tree2573fb5ac41700d458109ee1cea4bfd875ecf1a2 /src/cocoa
parentf7fa0930cb46046f995fa1ab927aef62466e995e (diff)
refactor: simplify public API and isolate native extensions
Separate loop/timer and native interoperability APIs from the portable surface header. Unify dispatch, geometry queries, and timer callbacks; keep framebuffer bookkeeping and frame clocks private, and hide implementation symbols. Update backends, documentation, examples, and API/integration coverage. Verify exports, strict C/C++ installed consumers, and normal plus ASan/UBSan suites.
Diffstat (limited to 'src/cocoa')
-rw-r--r--src/cocoa/api.h7
-rw-r--r--src/cocoa/window.m99
2 files changed, 49 insertions, 57 deletions
diff --git a/src/cocoa/api.h b/src/cocoa/api.h
index 2fea415..59372cf 100644
--- a/src/cocoa/api.h
+++ b/src/cocoa/api.h
@@ -9,7 +9,6 @@ struct cocoa_surface;
struct cocoa_display *cocoa_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec);
void cocoa_display_close(struct cocoa_display *d);
uint32_t cocoa_display_caps(const struct cocoa_display *d);
-void cocoa_display_dispatch(struct cocoa_display *d);
int cocoa_display_dispatch_timeout(struct cocoa_display *d, int timeout_ms);
void cocoa_display_flush(struct cocoa_display *d);
int cocoa_display_modifiers(const struct cocoa_display *d);
@@ -17,7 +16,8 @@ void cocoa_display_copy(struct cocoa_display *d, enum yasl_selection sel, const
void cocoa_display_paste(struct cocoa_display *d, enum yasl_selection sel, struct cocoa_surface *target);
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 cocoa_display_drag_cancel(struct cocoa_display *d);
-struct cocoa_surface *cocoa_surface_create_toplevel(struct cocoa_display *d, const struct yasl_surface_spec *spec);
+struct cocoa_surface *cocoa_surface_create_toplevel(struct cocoa_display *d,
+ const struct yasl_surface_spec *spec, void *graphics_device);
struct cocoa_surface *cocoa_surface_create_popup(struct cocoa_surface *parent, const struct yasl_popup_spec *spec);
bool cocoa_surface_popup_reposition(struct cocoa_surface *popup, const struct yasl_popup_spec *spec);
void cocoa_surface_destroy(struct cocoa_surface *s);
@@ -27,8 +27,7 @@ void cocoa_surface_set_title(struct cocoa_surface *s, const char *title);
void cocoa_surface_schedule_redraw(struct cocoa_surface *s);
bool cocoa_surface_present(struct cocoa_surface *s, const struct yasl_framebuffer *fb, const struct yasl_damage_list *damage);
bool cocoa_surface_input_poll(struct cocoa_surface *s, struct yasl_input_event *ev);
-struct yasl_vector2i cocoa_surface_size(const struct cocoa_surface *s);
-uint32_t cocoa_surface_scale_120(const struct cocoa_surface *s);
+struct yasl_geometry cocoa_surface_geometry(const struct cocoa_surface *s);
uint32_t cocoa_surface_state(const struct cocoa_surface *s);
struct yasl_timing cocoa_surface_timing(const struct cocoa_surface *s);
uint64_t cocoa_surface_frame_time_ns(struct cocoa_surface *s, uint64_t now);
diff --git a/src/cocoa/window.m b/src/cocoa/window.m
index fc69412..6e1e457 100644
--- a/src/cocoa/window.m
+++ b/src/cocoa/window.m
@@ -3,7 +3,8 @@
#import <QuartzCore/QuartzCore.h>
#include "cocoa/api.h"
-#include "yasl/timing.h"
+#include "common/timing.h"
+#include "common/loop.h"
#include "cocoa/keycodes.h"
#include <assert.h>
@@ -70,6 +71,8 @@ struct cocoa_surface {
uint32_t *pixels;
size_t pixel_capacity;
+ id<CAMetalDrawable> drawable;
+ bool transaction;
struct yasl_frame frame;
struct yasl_damage_list damage;
bool did_present;
@@ -775,9 +778,7 @@ bool cocoa_surface_present(struct cocoa_surface *w, const struct yasl_framebuffe
{
if (!w || w->closed || !w->rendering || w->did_present || !fb || !damage ||
fb->pixels != w->frame.target.pixels || fb->size.x != w->size.x ||
- fb->size.y != w->size.y || fb->buffer != w->frame.target.buffer ||
- fb->transaction != w->frame.target.transaction ||
- !fb->native_drawable || fb->native_drawable != w->frame.target.native_drawable)
+ fb->size.y != w->size.y || !w->drawable)
return false;
if (w->software_queue) {
if (fb->pixels != w->pixels || fb->size.x != w->size.x || fb->size.y != w->size.y)
@@ -793,7 +794,7 @@ bool cocoa_surface_present(struct cocoa_surface *w, const struct yasl_framebuffe
id<MTLCommandBuffer> command = [w->software_queue commandBuffer];
id<MTLBlitCommandEncoder> blit = [command blitCommandEncoder];
if (!blit) { [buffer release]; return false; }
- id<CAMetalDrawable> drawable = (id<CAMetalDrawable>)fb->native_drawable;
+ id<CAMetalDrawable> drawable = w->drawable;
[blit copyFromBuffer:buffer sourceOffset:0 sourceBytesPerRow:row_bytes
sourceBytesPerImage:length sourceSize:MTLSizeMake(w->size.x, w->size.y, 1)
toTexture:drawable.texture destinationSlice:0 destinationLevel:0
@@ -827,6 +828,8 @@ static void render_and_commit(struct cocoa_surface *w)
w->frame_due = false;
w->did_present = false;
id<CAMetalDrawable> drawable = [w->layer nextDrawable];
+ w->drawable = drawable;
+ w->transaction = w->layer.presentsWithTransaction;
w->damage = (struct yasl_damage_list){0};
w->frame = (struct yasl_frame){
.surface = &w->base,
@@ -834,9 +837,6 @@ static void render_and_commit(struct cocoa_surface *w)
.generation = yasl_frame_begin(&w->base),
.pixels = w->software_queue ? w->pixels : NULL,
.size = w->size,
- .damage = &w->damage,
- .native_drawable = drawable,
- .transaction = w->layer.presentsWithTransaction,
},
};
if (drawable)
@@ -845,7 +845,7 @@ static void render_and_commit(struct cocoa_surface *w)
w->want_draw = true;
w->frames_skipped++;
}
- w->frame.target.native_drawable = NULL;
+ w->drawable = nil;
w->rendering = false;
darwin_ctx.depth--;
}
@@ -864,6 +864,14 @@ int cocoa_display_dispatch_timeout(struct cocoa_display *d, int timeout_ms)
assert([NSThread isMainThread]);
if (!d || d->pumping)
return -1;
+ for (int i = 0; i < d->count; i++) {
+ struct cocoa_surface *w = d->windows[i];
+ if (w->input.count || w->input.reset_pending ||
+ (w->want_draw && (!w->link || w->frame_due || w->unpaced))) {
+ timeout_ms = 0;
+ break;
+ }
+ }
d->pumping = true;
d->depth++;
int count = 0;
@@ -914,21 +922,6 @@ int cocoa_display_dispatch_timeout(struct cocoa_display *d, int timeout_ms)
return count;
}
-void cocoa_display_dispatch(struct cocoa_display *d)
-{
- if (!d) return;
- bool immediate = false;
- for (int i = 0; i < d->count; i++) {
- struct cocoa_surface *w = d->windows[i];
- if (w->input.count > 0 || w->input.reset_pending ||
- (w->want_draw && (!w->link || w->frame_due || w->unpaced))) {
- immediate = true;
- break;
- }
- }
- cocoa_display_dispatch_timeout(d, immediate ? 0 : -1);
-}
-
void cocoa_display_flush(struct cocoa_display *d)
{
assert([NSThread isMainThread]);
@@ -1061,7 +1054,7 @@ uint32_t cocoa_display_caps(const struct cocoa_display *d)
}
struct cocoa_surface *cocoa_surface_create_toplevel(struct cocoa_display *d,
- const struct yasl_surface_spec *spec)
+ const struct yasl_surface_spec *spec, void *graphics_device)
{
assert([NSThread isMainThread]);
if (!d || !d->open || !spec)
@@ -1104,8 +1097,8 @@ struct cocoa_surface *cocoa_surface_create_toplevel(struct cocoa_display *d,
w->view = [[YaslView alloc] initWithFrame:w->window.contentView.bounds];
w->window.contentView = w->view;
w->layer = (CAMetalLayer *)w->view.layer;
- if (spec->graphics_device) {
- w->layer.device = (id<MTLDevice>)spec->graphics_device;
+ if (graphics_device) {
+ w->layer.device = (id<MTLDevice>)graphics_device;
} else {
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
w->layer.device = device;
@@ -1311,14 +1304,12 @@ int cocoa_display_modifiers(const struct cocoa_display *d)
return (int)cocoa_mods(NSEvent.modifierFlags);
}
-struct yasl_vector2i cocoa_surface_size(const struct cocoa_surface *w)
+struct yasl_geometry cocoa_surface_geometry(const struct cocoa_surface *w)
{
- return w ? w->size : (struct yasl_vector2i){0};
-}
-
-uint32_t cocoa_surface_scale_120(const struct cocoa_surface *w)
-{
- return w ? w->scale_120 : YASL_SCALE_UNIT;
+ return (struct yasl_geometry){
+ .size = w ? w->size : (struct yasl_vector2i){0},
+ .scale_120 = w ? w->scale_120 : YASL_SCALE_UNIT,
+ };
}
struct cocoa_surface *cocoa_surface_create_popup(struct cocoa_surface *parent,
@@ -1367,12 +1358,12 @@ bool cocoa_surface_show_window_menu(struct cocoa_surface *s, struct yasl_vector2
void *cocoa_display_get_native_handle(struct cocoa_display *d)
{
- return d ? (void *)d : NULL;
+ return d ? (void *)NSApp : NULL;
}
void *cocoa_surface_get_native_handle(struct cocoa_surface *s)
{
- return s ? (void *)s->view : NULL;
+ return s ? (void *)s->window : NULL;
}
@@ -1431,11 +1422,6 @@ static uint32_t impl_display_caps(const struct yasl_display *d)
return cocoa_display_caps((const struct cocoa_display *)d);
}
-static void impl_display_dispatch(struct yasl_display *d)
-{
- cocoa_display_dispatch((struct cocoa_display *)d);
-}
-
static int impl_display_dispatch_timeout(struct yasl_display *d, int timeout_ms)
{
return cocoa_display_dispatch_timeout((struct cocoa_display *)d, timeout_ms);
@@ -1471,9 +1457,10 @@ static void impl_display_drag_cancel(struct yasl_display *d)
cocoa_display_drag_cancel((struct cocoa_display *)d);
}
-static struct yasl_surface *impl_surface_create_toplevel(struct yasl_display *d, const struct yasl_surface_spec *spec)
+static struct yasl_surface *impl_surface_create_toplevel(struct yasl_display *d,
+ const struct yasl_surface_spec *spec, void *graphics_device)
{
- struct cocoa_surface *result = cocoa_surface_create_toplevel((struct cocoa_display *)d, spec);
+ struct cocoa_surface *result = cocoa_surface_create_toplevel((struct cocoa_display *)d, spec, graphics_device);
return result ? &result->base : NULL;
}
@@ -1524,14 +1511,9 @@ static bool impl_surface_input_poll(struct yasl_surface *s, struct yasl_input_ev
return cocoa_surface_input_poll((struct cocoa_surface *)s, ev);
}
-static struct yasl_vector2i impl_surface_size(const struct yasl_surface *s)
+static struct yasl_geometry impl_surface_geometry(const struct yasl_surface *s)
{
- return cocoa_surface_size((const struct cocoa_surface *)s);
-}
-
-static uint32_t impl_surface_scale_120(const struct yasl_surface *s)
-{
- return cocoa_surface_scale_120((const struct cocoa_surface *)s);
+ return cocoa_surface_geometry((const struct cocoa_surface *)s);
}
static uint32_t impl_surface_state(const struct yasl_surface *s)
@@ -1609,12 +1591,23 @@ static void *impl_surface_get_native_handle(struct yasl_surface *s)
return cocoa_surface_get_native_handle((struct cocoa_surface *)s);
}
+static bool impl_surface_get_native_frame(struct yasl_surface *s,
+ const struct yasl_framebuffer *target, struct yasl_native_frame *out)
+{
+ struct cocoa_surface *w = (struct cocoa_surface *)s;
+ if (w->closed || !w->rendering || w->did_present || !w->drawable ||
+ target->pixels != w->frame.target.pixels ||
+ target->size.x != w->size.x || target->size.y != w->size.y)
+ return false;
+ *out = (struct yasl_native_frame){(void *)w->drawable, w->transaction};
+ return true;
+}
+
const struct yasl_backend_ops yasl_cocoa_backend = {
.type = YASL_BACKEND_COCOA,
.display_open = impl_display_open,
.display_close = impl_display_close,
.display_caps = impl_display_caps,
- .display_dispatch = impl_display_dispatch,
.display_dispatch_timeout = impl_display_dispatch_timeout,
.display_flush = impl_display_flush,
.display_modifiers = impl_display_modifiers,
@@ -1632,8 +1625,7 @@ const struct yasl_backend_ops yasl_cocoa_backend = {
.surface_schedule_redraw = impl_surface_schedule_redraw,
.surface_present = impl_surface_present,
.surface_input_poll = impl_surface_input_poll,
- .surface_size = impl_surface_size,
- .surface_scale_120 = impl_surface_scale_120,
+ .surface_geometry = impl_surface_geometry,
.surface_state = impl_surface_state,
.surface_timing = impl_surface_timing,
.surface_frame_time_ns = impl_surface_frame_time_ns,
@@ -1649,4 +1641,5 @@ const struct yasl_backend_ops yasl_cocoa_backend = {
.surface_place_under_pointer = impl_surface_place_under_pointer,
.display_get_native_handle = impl_display_get_native_handle,
.surface_get_native_handle = impl_surface_get_native_handle,
+ .surface_get_native_frame = impl_surface_get_native_frame,
};