summaryrefslogtreecommitdiff
path: root/src/platform/cocoa/window.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/cocoa/window.m')
-rw-r--r--src/platform/cocoa/window.m79
1 files changed, 47 insertions, 32 deletions
diff --git a/src/platform/cocoa/window.m b/src/platform/cocoa/window.m
index a78c2ce..c5022dd 100644
--- a/src/platform/cocoa/window.m
+++ b/src/platform/cocoa/window.m
@@ -129,7 +129,7 @@ struct cocoa_display {
int count;
int capacity;
char *app_id;
- struct yasl_private_loop *loop;
+ struct yasl_loop *loop;
id key_up_monitor;
NSCursor *hidden_cursor;
YaslAppDelegate *delegate;
@@ -1413,10 +1413,18 @@ bool cocoa_surface_present(struct cocoa_surface *w, const struct yasl_private_fr
return true;
}
+/* render_and_commit draws only when this holds; readiness uses it too, so a
+ * window that cannot draw never keeps the loop from waiting. */
+static bool draw_possible(const struct cocoa_surface *w)
+{
+ return w->base.presenter == YASL_PRIVATE_PRESENTER_CPU && !w->destroyed && !w->closed &&
+ w->cbs->draw && !w->rendering && w->size.x > 0 && w->size.y > 0 &&
+ !(w->base.state & YASL_PRIVATE_STATE_SUSPENDED);
+}
+
static void render_and_commit(struct cocoa_surface *w)
{
- if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU || w->destroyed || w->closed || !w->cbs->draw || w->rendering || w->size.x <= 0 || w->size.y <= 0 ||
- (w->base.state & YASL_PRIVATE_STATE_SUSPENDED))
+ if (!draw_possible(w))
return;
size_t count = (size_t)w->size.x * (size_t)w->size.y;
@@ -1482,7 +1490,7 @@ static void loop_ready(CFFileDescriptorRef fd, CFOptionFlags flags, void *info)
/* A kqueue mirroring the loop's poll set, or -1. complete is false when some
* descriptor could not be registered. */
-static int loop_kqueue(struct yasl_private_loop *loop, bool *complete)
+static int loop_kqueue(struct yasl_loop *loop, bool *complete)
{
*complete = true;
int kq = kqueue();
@@ -1511,30 +1519,30 @@ static bool is_loop_wake(NSEvent *ev)
return ev.type == NSEventTypeApplicationDefined && ev.subtype == LOOP_WAKE_SUBTYPE;
}
-int cocoa_display_dispatch_timeout(struct cocoa_display *d, int timeout_ms)
+/* Before the wait: draw due windows. True when a window can draw now. */
+bool cocoa_display_prepare(struct cocoa_display *d)
{
assert([NSThread isMainThread]);
- if (!d || d->pumping)
- return -1;
+ cocoa_display_flush(d);
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;
- }
+ if (w->want_draw && (!w->link || w->frame_due || w->unpaced) && draw_possible(w))
+ return true;
}
+ return false;
+}
+
+/* The loop's wait. The loop has already shortened timeout_ms to its next
+ * timer, and reads descriptor readiness after this returns. */
+int cocoa_display_wait(struct cocoa_display *d, int timeout_ms)
+{
+ assert([NSThread isMainThread]);
+ if (d->pumping)
+ return -EBUSY;
d->pumping = true;
d->depth++;
int count = 0;
@try {
- if (d->loop) {
- int timer_to = yasl_private_loop_next_timeout_ms(d->loop);
- if (timer_to >= 0 && (timeout_ms < 0 || timer_to < timeout_ms)) {
- timeout_ms = timer_to;
- }
- }
-
/* AppKit waits on Mach ports, not on loop descriptors. While waiting,
* a run loop source on a kqueue of the loop's descriptors posts a wake
* event, so kicks, posts, signals, and watches end the wait. */
@@ -1592,10 +1600,6 @@ int cocoa_display_dispatch_timeout(struct cocoa_display *d, int timeout_ms)
dequeue:YES];
}
}
-
- if (d->loop) {
- yasl_private_loop_step(d->loop, 0);
- }
} @finally {
d->depth--;
d->pumping = false;
@@ -1632,8 +1636,7 @@ void cocoa_surface_schedule_redraw(struct cocoa_surface *w)
w->frame_due = true;
w->link.paused = NO;
}
- if (darwin_ctx.loop)
- yasl_private_loop_kick(darwin_ctx.loop);
+ yasl_private_loop_wake(darwin_ctx.loop);
}
static void app_init(const char *app_name)
@@ -1688,7 +1691,7 @@ static void place_window(NSWindow *window)
darwin_ctx.cascade = [window cascadeTopLeftFromPoint:darwin_ctx.cascade];
}
-struct cocoa_display *cocoa_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec)
+struct cocoa_display *cocoa_display_open(struct yasl_loop *loop, const struct yasl_private_display_spec *spec)
{
if (![NSThread isMainThread]) {
errno = EPERM;
@@ -1701,7 +1704,7 @@ struct cocoa_display *cocoa_display_open(struct yasl_private_loop *loop, const s
darwin_ctx.base.native_handle = (__bridge void *)[NSApplication sharedApplication];
darwin_ctx.open = true;
if (!loop) {
- darwin_ctx.loop = yasl_private_loop_create();
+ darwin_ctx.loop = yasl_loop_create();
darwin_ctx.owns_loop = true;
} else {
darwin_ctx.loop = loop;
@@ -1726,7 +1729,7 @@ void cocoa_display_close(struct cocoa_display *d)
d->key_up_monitor = nil;
}
if (d->owns_loop && d->loop) {
- yasl_private_loop_destroy(d->loop);
+ yasl_loop_destroy(d->loop);
d->loop = NULL;
d->base.loop = NULL;
}
@@ -2538,7 +2541,7 @@ struct yasl_private_timing cocoa_surface_timing(const struct cocoa_surface *w)
return timing;
}
-static struct yasl_private_display *impl_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec)
+static struct yasl_private_display *impl_display_open(struct yasl_loop *loop, const struct yasl_private_display_spec *spec)
{
struct cocoa_display *result = cocoa_display_open(loop, spec);
return result ? &result->base : NULL;
@@ -2554,9 +2557,19 @@ static uint32_t impl_display_caps(const struct yasl_private_display *d)
return cocoa_display_caps((const struct cocoa_display *)d);
}
-static int impl_display_dispatch_timeout(struct yasl_private_display *d, int timeout_ms)
+static bool impl_display_prepare(struct yasl_private_display *d)
+{
+ return cocoa_display_prepare((struct cocoa_display *)d);
+}
+
+static int impl_display_wait(struct yasl_private_display *d, int timeout_ms)
+{
+ return cocoa_display_wait((struct cocoa_display *)d, timeout_ms);
+}
+
+static void impl_display_check(struct yasl_private_display *d)
{
- return cocoa_display_dispatch_timeout((struct cocoa_display *)d, timeout_ms);
+ (void)d;
}
static void impl_display_flush(struct yasl_private_display *d)
@@ -2787,7 +2800,9 @@ const struct yasl_private_backend_ops yasl_private_cocoa_backend = {
.display_open = impl_display_open,
.display_close = impl_display_close,
.display_caps = impl_display_caps,
- .display_dispatch_timeout = impl_display_dispatch_timeout,
+ .display_prepare = impl_display_prepare,
+ .display_wait = impl_display_wait,
+ .display_check = impl_display_check,
.display_flush = impl_display_flush,
.display_modifiers = impl_display_modifiers,
.display_double_click_ms = impl_display_double_click_ms,