summaryrefslogtreecommitdiff
path: root/include/yasl
diff options
context:
space:
mode:
Diffstat (limited to 'include/yasl')
-rw-r--r--include/yasl/yasl.h88
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;