diff options
Diffstat (limited to 'include/yasl')
| -rw-r--r-- | include/yasl/yasl.h | 88 |
1 files changed, 75 insertions, 13 deletions
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h index 15bbe16..dab1091 100644 --- a/include/yasl/yasl.h +++ b/include/yasl/yasl.h @@ -27,6 +27,7 @@ extern "C" { #endif typedef struct yasl_surface yasl_surface; typedef struct yasl_event yasl_event; +typedef struct yasl_loop yasl_loop; /* Lifecycle */ enum yasl_backend { YASL_BACKEND_AUTO, YASL_BACKEND_WAYLAND, YASL_BACKEND_X11, YASL_BACKEND_COCOA }; @@ -36,11 +37,25 @@ enum yasl_feature { YASL_FEATURE_TEXT_INPUT = 64, YASL_FEATURE_LOCKED_CURSOR = 128, YASL_FEATURE_OPENGL = 256, YASL_FEATURE_VULKAN = 512 }; -/** Optional: the first surface initializes with AUTO and no app ID. app_id is a - * reverse-DNS name for window grouping and notifications. EALREADY once - * initialized; a failed initialization may be retried. */ -YASL_API int yasl_init(enum yasl_backend backend, const char *app_id); -/** Destroys every surface. EBUSY while a Vulkan surface exists. */ +/** Zero is the default: AUTO, no app ID, and yasl_wait_event delivers events. + * app_id is a reverse-DNS name for window grouping and notifications. Set loop + * and on_event together to run the display on an application loop: each + * yasl_loop_step then delivers events to on_event, and yasl_wait_event fails + * with EBUSY. */ +struct yasl_options { + enum yasl_backend backend; + const char *app_id; + yasl_loop *loop; + void (*on_event)(void *userdata, const yasl_event *event); + void *userdata; +}; +/** Optional: the first surface initializes with defaults; NULL options too. + * EINVAL when only one of loop and on_event is set; EPERM off the loop's + * thread. EALREADY once initialized with the same options, EBUSY with others; + * a failed initialization may be retried. */ +YASL_API int yasl_init(const struct yasl_options *options); +/** Destroys every surface; on_event is not called again. EBUSY inside a loop + * step or while a Vulkan surface exists. */ YASL_API int yasl_shutdown(void); /** AUTO and 0 before initialization. */ YASL_API enum yasl_backend yasl_get_backend(void); @@ -99,6 +114,10 @@ YASL_API int yasl_surface_set_title(yasl_surface *surface, const char *title); enum yasl_request { YASL_REQUEST_RESTORE, YASL_REQUEST_FULLSCREEN, YASL_REQUEST_MAXIMIZE, YASL_REQUEST_MINIMIZE }; YASL_API int yasl_surface_request(yasl_surface *surface, enum yasl_request request); YASL_API int yasl_surface_request_size(yasl_surface *surface, int width, int height); +/** Asks for a REFRESH when the window can show a new frame: at once when none + * is in flight, otherwise once the system shows the current one. Requests + * coalesce. Use it to pace animation; draw at once for input. */ +YASL_API int yasl_surface_request_frame(yasl_surface *surface); enum yasl_cursor { YASL_CURSOR_ARROW, YASL_CURSOR_TEXT, YASL_CURSOR_LINK, YASL_CURSOR_CROSSHAIR, YASL_CURSOR_MOVE, @@ -196,10 +215,11 @@ enum yasl_event_type { YASL_EVENT_DROP, /**< External data: x, y; action is a yasl_drop_action; * text on RELEASE is a text/uri-list. */ YASL_EVENT_DRAG, /**< A yasl_drag_start drag: x, y; action is a yasl_drop_action. */ - /** The display server went away. Before the next wait, destroy Vulkan - * surfaces and detach GL contexts on every thread; popups close. Wayland - * reconnects and sends DISPLAY_RESTORED: recreate them (GL contexts are new). - * Elsewhere loss is final and waits fail with ENOTCONN. */ + /** The display server went away; action is a yasl_lost. Before the next + * wait, or before returning to the loop, destroy Vulkan surfaces and detach + * GL contexts on every thread; popups close. On RECONNECTING, DISPLAY_RESTORED + * follows: recreate them (GL contexts are new). After FINAL, yasl_wait_event + * fails with ENOTCONN once no event is left. */ YASL_EVENT_DISPLAY_LOST, YASL_EVENT_DISPLAY_RESTORED }; @@ -218,6 +238,7 @@ enum yasl_scroll_source { YASL_SCROLL_UNKNOWN, YASL_SCROLL_WHEEL, YASL_SCROLL_FI enum yasl_scroll_phase { YASL_SCROLL_PHASE_NONE, YASL_SCROLL_BEGIN, YASL_SCROLL_UPDATE, YASL_SCROLL_END }; enum yasl_transfer { YASL_TRANSFER_OK, YASL_TRANSFER_UNAVAILABLE, YASL_TRANSFER_FAILED }; enum yasl_drop_action { YASL_DROP_OVER, YASL_DROP_LEAVE, YASL_DROP_RELEASE }; +enum yasl_lost { YASL_LOST_RECONNECTING, YASL_LOST_FINAL }; /** Physical key, layout labels (codepoint unshifted, shifted; 0 if none) and the * native code (evdev, X11 keycode or macOS virtual key). Type with TEXT, not this. */ @@ -256,7 +277,8 @@ struct yasl_event { uint64_t time_ns; unsigned action, mods; /**< mods: YASL_MOD_* for KEY, POINTER and SCROLL. */ double x, y; - const char *text; /**< NUL-terminated UTF-8 until the next wait, or NULL. */ + const char *text; /**< NUL-terminated UTF-8 until the next wait or until + * on_event returns, or NULL. */ size_t length; union { struct yasl_surface_info window; @@ -268,18 +290,58 @@ struct yasl_event { }; }; /** 1 with an event, 0 once timeout_ms passes or after yasl_wake. 0 polls and -1 - * waits forever. On failure out->type is NONE. */ + * waits forever. On failure out->type is NONE. EBUSY with on_event. */ YASL_API int yasl_wait_event(yasl_event *out, int timeout_ms); /** Makes a waiting, or the next, yasl_wait_event return 0 once no event is - * pending. Thread-safe. */ + * pending. With on_event, wakes the loop. Thread-safe. */ YASL_API void yasl_wake(void); /** Monotonic nanoseconds, the clock of event times. Thread-safe. */ YASL_API uint64_t yasl_time_ns(void); +/* Loop: one wait for the whole application. Give it to yasl_init to run the + * display on it; it also runs descriptors, timers and signals without one. + * Call it and get its callbacks on the thread that created it. */ +/** NULL with errno on failure. */ +YASL_API yasl_loop *yasl_loop_create(void); +/** EBUSY while a step runs or the display runs on it. Leaves descriptors open. */ +YASL_API int yasl_loop_destroy(yasl_loop *loop); +/** Waits at most timeout_ms (0 polls, -1 waits) and runs what is ready: + * display events, then descriptors, then due timers. Returns how many + * descriptor and timer callbacks ran. EBUSY inside a step; EPERM off the + * loop's thread. */ +YASL_API int yasl_loop_step(yasl_loop *loop, int timeout_ms); +/** Steps until yasl_loop_quit. A quit made before the run ends it at once. */ +YASL_API int yasl_loop_run(yasl_loop *loop); +YASL_API void yasl_loop_quit(yasl_loop *loop); +/** Calls callback with the poll(2) revents, errors and hangup included; it + * must consume them or change the watch. Returns an ID above zero. */ +YASL_API int yasl_loop_add_fd(yasl_loop *loop, int fd, short events, + void (*callback)(void *userdata, int fd, short revents), + void *userdata); +/** ENOENT for an unknown ID. Leaves the descriptor open. */ +YASL_API int yasl_loop_del_fd(yasl_loop *loop, int id); +YASL_API int yasl_loop_set_fd_events(yasl_loop *loop, int id, short events); +/** Calls callback after delay_ns, 0 meaning the next step. It returns the next + * delay, or 0 to stop. Returns an ID that is never reused, or 0 with errno. */ +YASL_API uint64_t yasl_loop_add_timer(yasl_loop *loop, uint64_t delay_ns, + uint64_t (*callback)(void *userdata, uint64_t id, + uint64_t delay_ns), + void *userdata); +/** True when it cancels an armed timer, also from its own callback. */ +YASL_API bool yasl_loop_del_timer(yasl_loop *loop, uint64_t id); +/** Calls callback on the loop's thread for each signal; repeats before the + * call coalesce. EBUSY when this loop already watches signals or another loop + * watches one of them. Unwatching restores the previous actions. */ +YASL_API int yasl_loop_watch_signals(yasl_loop *loop, const int *signals, int count, + void (*callback)(void *userdata, int signo), + void *userdata); +YASL_API void yasl_loop_unwatch_signals(yasl_loop *loop); + /* Rendering */ /** CPU surfaces: the window's pixel_width * pixel_height premultiplied * 0xAARRGGBB pixels, rows tightly packed. They persist, and a resize keeps the - * overlap and zeroes the rest. Valid until the next wait. Present to show them; + * overlap and zeroes the rest. Valid until the next wait, the return of the + * callback that got them, or the next yasl_cpu_ call. Present to show them; * the system may also show them when it redraws the window. */ struct yasl_damage { int x, y, width, height; |
