From c2832a63547e6328afde25bb3b8145267eadef47 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Thu, 15 Oct 2026 20:38:14 +0300 Subject: Make the loop public and let the display drive it An application that has its own descriptors and timers needed a second loop next to yasl's, and could not see yasl's key-repeat timer, clipboard pipes or reconnect timer. Now there is one wait: the application owns a yasl_loop, and yasl_init can run the display on it. - Public yasl_loop_*: descriptors, timers and signals. Descriptor callbacks return void. Timer IDs are 64 bits and never reused; a zero delay runs in the next step. A nested step or run fails with EBUSY, a step off the loop's thread with EPERM, and a quit made before a run ends it at once. An interrupted wait keeps its deadline. Creating a loop fails when it cannot make its wake pipe. - The display drives the loop through prepare, wait and check hooks instead of wrapping its step. Wayland finishes its read before any callback runs, so loop callbacks may create surfaces and do roundtrips. Readiness (queued events, an owed REFRESH) is derived in the step, so the wait never blocks over pending work. A draw that cannot proceed for want of a buffer is no longer counted as work. - yasl_init takes struct yasl_options. With loop and on_event, each step delivers events to on_event and yasl_wait_event fails with EBUSY. EALREADY only for the same options, EBUSY for others. - yasl_surface_request_frame: a REFRESH once the window can show a new frame, for pacing animation. - DISPLAY_LOST reports whether the display reconnects. Pull waits still fail with ENOTCONN after a final loss. - Events pushed from another thread wake the loop. Co-Authored-By: Claude Opus 5.5 --- src/common/types.h | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'src/common/types.h') diff --git a/src/common/types.h b/src/common/types.h index 3fffd47..8d00d0b 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -4,8 +4,9 @@ * * All calls and callbacks use the display's opening thread (the main thread on * Cocoa), unless explicitly documented otherwise. Userdata is borrowed; callback - * tables and creation specs are copied. Do not recursively dispatch/flush or - * destroy a display/loop while dispatch or a callback is active. Destroy child + * tables and creation specs are copied. The display drives its loop: each + * yasl_loop_step dispatches it. Do not recursively step or flush, or destroy a + * display/loop while a step or a callback is active. Destroy child * popups before parents, surfaces before displays, displays before borrowed loops. * Surface destruction from its own callback is supported; stop using it immediately. * @@ -43,7 +44,7 @@ extern "C" { struct yasl_private_display; struct yasl_surface; -struct yasl_private_loop; +struct yasl_loop; /* Geometry */ /** A two-dimensional integer size, position, or offset; units depend on the caller. */ @@ -569,7 +570,7 @@ struct yasl_private_display_spec { * opening fails without a more specific platform error. Explicit choices never * fall back. Close with yasl_private_display_close() after destroying its surfaces. */ -struct yasl_private_display *yasl_private_display_open(struct yasl_private_loop *loop, +struct yasl_private_display *yasl_private_display_open(struct yasl_loop *loop, const struct yasl_private_display_spec *spec); /** * Read the selected backend. @@ -592,19 +593,6 @@ void yasl_private_display_close(struct yasl_private_display *d); * permission to perform an operation at any arbitrary moment. */ uint32_t yasl_private_display_caps(const struct yasl_private_display *d); -/* Process events, waiting at most timeout_ms: zero polls, negative waits. - * Pending input or redraw work returns immediately. Returns -1 on failure. */ -/** - * Receive events and run ready loop sources. - * @param d Display to dispatch. - * @param timeout_ms Maximum wait in milliseconds: zero polls, negative waits indefinitely. - * @return A nonnegative backend-specific work count on success, or -1 with errno - * set on failure (EINVAL for NULL, EIO if no specific backend error is available). - * Do not interpret the count as the number of queued input events. Pending input - * or runnable redraw work prevents waiting. Drain input and call - * yasl_private_display_flush() after updating application state. Do not dispatch recursively. - */ -int yasl_private_display_dispatch(struct yasl_private_display *d, int timeout_ms); /** * Draw scheduled surfaces and send pending display requests. * @param d Display, or NULL for no action. @@ -886,6 +874,9 @@ bool yasl_private_frame_present(struct yasl_private_frame *frame, const struct yasl_private_rect2i *rects, size_t count); /** Coalesce a redraw request; use on the display thread. NULL is ignored. */ void yasl_private_surface_request_frame(struct yasl_surface *s); +/** Owe s a REFRESH once the system shows its frame in flight, or at once when + * none is. False with errno when the fallback timer cannot start. */ +bool yasl_private_surface_request_shown_frame(struct yasl_surface *s); /** Set drawing policy for either loop style. Returns false with errno on failure. */ bool yasl_private_surface_set_pacing(struct yasl_surface *s, yasl_private_pacing_mode mode); -- cgit v1.2.3