From a075a2941f8fcdae155495da634cf63368c950b7 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Fri, 16 Oct 2026 09:33:39 +0300 Subject: Pace frame requests by the frame presented after them A frame request now only records intent. Each loop step resolves it after the callbacks that present, so a request made before the present waits for that frame. An animation that asked first got two REFRESH events per frame on X11 and with GL. With no frame in flight, the REFRESH comes one refresh interval after the last present or answer, so a request without a present cannot spin. Queued events now go before an owed REFRESH. Input reaches the application before it draws, and a queued REFRESH pays an owed one for the same surface. The loop prepare only peeks at a lost event, so deliver can report it as a final loss. A failed push from another thread wakes the loop. Signals and posts run at the end of a step, after descriptors and timers. A signal handler now sees the output that came with it. A render-thread GL swap counts as in flight on Wayland. Co-Authored-By: Claude Opus 5.5 --- src/platform/posix/loop.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/platform/posix/loop.c') diff --git a/src/platform/posix/loop.c b/src/platform/posix/loop.c index 6624575..38f504d 100644 --- a/src/platform/posix/loop.c +++ b/src/platform/posix/loop.c @@ -122,15 +122,13 @@ static void run_signals(struct yasl_loop *l) } } +/* Only wakes the wait; the step runs posts and signals last. */ static void loop_wake_cb(void *ud, int fd, short revents) { - (void)revents; + (void)ud; (void)revents; char buf[128]; ssize_t n; while ((n = read(fd, buf, sizeof(buf))) > 0 || (n < 0 && errno == EINTR)) {} - struct yasl_loop *l = ud; - run_posts(l); - run_signals(l); } static bool open_wake_pipe(int p[2]) @@ -575,7 +573,12 @@ static int step(struct yasl_loop *l, int timeout_ms) if (d && d->deliver) d->deliver(d->ud); int fds = dispatch_fds(l); if (fds < 0) return fds; - return fds + fire_timers(l); + int timers = fire_timers(l); + /* Last, so a signal sees what came with it: a child's final output is + * read before its exit is handled. */ + run_posts(l); + run_signals(l); + return fds + timers; } int yasl_loop_step(yasl_loop *l, int timeout_ms) -- cgit v1.2.3