diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-16 09:33:39 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-16 09:33:39 +0300 |
| commit | a075a2941f8fcdae155495da634cf63368c950b7 (patch) | |
| tree | a33b5636ef7b9e4879cb8ab52220e805a5e30348 /src/common/surface.c | |
| parent | c2832a63547e6328afde25bb3b8145267eadef47 (diff) | |
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 <noreply@anthropic.com>
Diffstat (limited to 'src/common/surface.c')
| -rw-r--r-- | src/common/surface.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/src/common/surface.c b/src/common/surface.c index 5c29a10..6b805be 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -451,7 +451,8 @@ int yasl_surface_request_frame(yasl_surface *s) { if (!yasl_public_connected(s)) return -errno; - return STATUS(yasl_private_surface_request_shown_frame(s)); + yasl_private_surface_request_shown_frame(s); + return 0; } int yasl_surface_set_cursor(yasl_surface *s, enum yasl_cursor cursor) { @@ -901,14 +902,10 @@ static bool convert_event(const struct yasl_private_event *p, yasl_event *e) return false; } } +/* Queued events go first: input reaches the application before it draws, and + * a queued REFRESH also pays one owed to the same surface. */ static int take_event(yasl_event *out) { - for (yasl_surface *s = display->surfaces; s; s = s->event_next) - if (s->refresh_owed && refresh_ready(s)) { - s->refresh_owed = false; - *out = (yasl_event){.type = YASL_EVENT_REFRESH, .surface = s, .time_ns = yasl_time_ns()}; - return 1; - } struct yasl_private_event p; while (yasl_private_display_poll_event(display, &p)) { /* Input method events from an older text field are stale. */ @@ -926,6 +923,12 @@ static int take_event(yasl_event *out) if (errno) return yasl_public_error(errno); } + for (yasl_surface *s = display->surfaces; s; s = s->event_next) + if (s->refresh_owed && refresh_ready(s)) { + s->refresh_owed = false; + *out = (yasl_event){.type = YASL_EVENT_REFRESH, .surface = s, .time_ns = yasl_time_ns()}; + return 1; + } return 0; } /* Internal wakeups, such as a redraw request, keep waiting; only an event, the deadline or |
