summaryrefslogtreecommitdiff
path: root/include/yasl
diff options
context:
space:
mode:
Diffstat (limited to 'include/yasl')
-rw-r--r--include/yasl/app.h87
-rw-r--r--include/yasl/yasl.h186
2 files changed, 178 insertions, 95 deletions
diff --git a/include/yasl/app.h b/include/yasl/app.h
index b7e1c13..78e62c4 100644
--- a/include/yasl/app.h
+++ b/include/yasl/app.h
@@ -21,74 +21,12 @@ extern "C" {
typedef enum yasl_app_result {
YASL_APP_CONTINUE = 0, /**< Continue running the application. */
YASL_APP_QUIT, /**< Request graceful termination of yasl_run(). */
+ YASL_APP_ERROR, /**< Request orderly cleanup and a failing run result. */
} yasl_app_result;
-/** Pacing mode governing when frame() callbacks are invoked. */
-typedef enum yasl_pacing_mode {
- /**
- * Reactive / on-demand presentation (ideal for IDEs, text editors, tools).
- * The application sleeps at 0% CPU when idle. frame() is only invoked when
- * explicitly requested via yasl_surface_request_frame() or upon OS window
- * expose/resize events.
- */
- YASL_PACING_ON_DEMAND = 0,
-
- /**
- * Continuous vsync-aligned tick (ideal for game engines and animations).
- * frame() is driven continuously at the display's native refresh rate
- * (e.g. 60/120/144 Hz) via DisplayLink, Wayland frame callbacks, or loop timers.
- */
- YASL_PACING_CONTINUOUS,
-} yasl_pacing_mode;
-
-/** Frame context provided to yasl_app_desc.frame() during presentation. */
-struct yasl_frame_context {
- struct yasl_surface *surface;
- uint64_t frame_index;
- uint64_t target_time_ns; /**< Monotonic timestamp aligned to display refresh. */
- struct yasl_vector2i size; /**< Surface content size in device pixels. */
- uint32_t scale_120;
-
- /** CPU software rendering target, if surface was created for CPU blitting. */
- struct {
- uint32_t *pixels; /**< Writable premultiplied 0xAARRGGBB device pixels. */
- int stride_bytes; /**< Row stride in bytes. */
- } cpu;
-
- /** Native GPU rendering layer/surface, if surface was created for GPU rendering. */
- struct {
- void *native_layer; /**< CAMetalLayer* on Cocoa, wl_surface* on Wayland, Window on X11. */
- } gpu;
-
- /** Internal handle used by yasl_frame_present_cpu. Applications must not touch. */
- void *internal_handle;
-};
-
-/**
- * Present CPU software target pixels.
- * @param ctx Active frame context passed to yasl_app_desc.frame().
- * @param dirty_rects Optional array of damaged rectangles in device pixels.
- * Pass NULL or count <= 0 to indicate full-surface damage.
- * @param count Number of rectangles in dirty_rects.
- * @return true if accepted, false on presentation failure.
- */
-YASL_API bool yasl_frame_present_cpu(struct yasl_frame_context *ctx,
- const struct yasl_rect2i *dirty_rects,
- int count);
-
-/**
- * Configure the presentation pacing mode for a surface.
- * @param s Surface.
- * @param mode YASL_PACING_ON_DEMAND for reactive UI, YASL_PACING_CONTINUOUS for games.
- */
-YASL_API void yasl_surface_set_pacing(struct yasl_surface *s, yasl_pacing_mode mode);
-
-/**
- * Mark a surface as needing a redraw on the next frame pass.
- * Wakes the event loop if sleeping under YASL_PACING_ON_DEMAND.
- * @param s Surface.
- */
-YASL_API void yasl_surface_request_frame(struct yasl_surface *s);
+/** Migration adapter; prefer yasl_frame_present() from yasl.h. */
+YASL_API bool yasl_frame_present_cpu(struct yasl_frame *frame,
+ const struct yasl_rect2i *dirty_rects, int count);
/**
* Safely post a custom user event to the main event loop from ANY thread.
@@ -99,7 +37,9 @@ YASL_API void yasl_surface_request_frame(struct yasl_surface *s);
* @param payload Arbitrary pointer passed through to the event.
* @param size Optional payload size.
* @return true if queued; false if memory failed or d is not run by yasl_run().
- * Applications that run their own loop use yasl_loop_post() instead.
+ * Migration adapter: keep s alive through the call, and stop producers before
+ * shutdown. Prefer yasl_display_post() with a captured ID and release callback
+ * in either loop style; legacy payloads have no cancellation cleanup.
*/
YASL_API bool yasl_post_event(struct yasl_display *d, struct yasl_surface *s,
uint32_t code, void *payload, size_t size);
@@ -159,15 +99,15 @@ struct yasl_app_desc {
/**
* Optional; called once after display and event machinery initialization.
* Use this to create further windows and initialize application resources.
- * Return YASL_APP_CONTINUE or YASL_APP_QUIT.
+ * Return YASL_APP_CONTINUE, YASL_APP_QUIT, or YASL_APP_ERROR.
*/
enum yasl_app_result (*init)(void *ud, struct yasl_display *d);
/**
- * Unified event handler for input, window and user events, in arrival order.
+ * Unified event handler for input, window and user events, in display-wide enqueue order.
* Event payloads and borrowed strings are valid for the duration of the callback.
* INPUT_RESET has no payload and requires clearing held application input.
- * Return YASL_APP_CONTINUE or YASL_APP_QUIT. Optional; without it, a
+ * Return YASL_APP_CONTINUE, YASL_APP_QUIT, or YASL_APP_ERROR. Optional; without it, a
* WINDOW_CLOSE request on any window stops yasl_run().
*/
enum yasl_app_result (*event)(void *ud, const struct yasl_event *ev);
@@ -176,7 +116,7 @@ struct yasl_app_desc {
* Invoked when a surface needs to present a frame.
* Synchronized automatically with display pacing and live window resizing.
*/
- void (*frame)(void *ud, struct yasl_surface *s, struct yasl_frame_context *ctx);
+ void (*frame)(void *ud, struct yasl_surface *s, struct yasl_frame *frame);
/**
* Called right before the display is closed and yasl_run() exits.
@@ -185,6 +125,11 @@ struct yasl_app_desc {
void (*quit)(void *ud, struct yasl_display *d);
};
+/** Request orderly exit from any display-thread callback; ERROR returns failure. */
+YASL_API void yasl_app_exit(struct yasl_display *d, enum yasl_app_result result);
+/** Borrow the optional desc.window surface during init or later; NULL if absent/destroyed. */
+YASL_API struct yasl_surface *yasl_app_window(struct yasl_display *d);
+
/**
* Run the application with the inverted lifecycle runner.
* Handles the display event loop, live-resizing, pacing, and cleanup.
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h
index f798304..889f70a 100644
--- a/include/yasl/yasl.h
+++ b/include/yasl/yasl.h
@@ -14,12 +14,15 @@
* handling is documented per function; it does not make freed pointers safe.
* Only functions explicitly documenting errno guarantee a diagnostic there.
* Other boolean results report success/availability; void setters are best effort.
+ * New window requests, clipboard operations, frame presentation, and posting
+ * document errno on failure. Event strings belong to the display queue.
*
* Toplevel creation sizes use logical pixels. Geometry, framebuffers, pointer
* positions, damage, IME carets, popup specs, and drag offsets use device pixels.
* Coordinates have their origin at the upper left; x grows right and y grows down.
* Scale is an integer ratio with YASL_SCALE_UNIT (120) representing 1x.
- * See the application guide for the dispatch/poll/flush cycle and backend limits.
+ * See the application guide for the display-wide dispatch/poll/flush cycle
+ * and backend limits. Legacy surface polling is an input-only filtered adapter.
*/
#ifndef YASL_H
#define YASL_H
@@ -211,6 +214,8 @@ struct yasl_framebuffer {
uint32_t *pixels;
/** Target extent in device pixels. */
struct yasl_vector2i size;
+ /** Row stride in bytes, populated for the active draw callback. */
+ int stride_bytes;
};
/** One draw invocation. Do not retain its pointer after the callback returns. */
@@ -219,8 +224,20 @@ struct yasl_frame {
struct yasl_surface *surface;
/** Target to initialize and present before returning. */
struct yasl_framebuffer target;
+ /** Zero-based index of this surface draw. */
+ uint64_t frame_index;
+ /** Estimated animation time; not confirmed presentation. */
+ uint64_t target_time_ns;
+ /** Device scale numerator, with 120 representing 1x. */
+ uint32_t scale_120;
};
+/** Coalesced redraw policy, valid with either loop style. */
+typedef enum yasl_pacing_mode {
+ YASL_PACING_ON_DEMAND = 0, /**< Draw only when invalidated or exposed. */
+ YASL_PACING_CONTINUOUS, /**< Draw continuously using native pacing or a timer. */
+} yasl_pacing_mode;
+
/* Drag and Drop */
/** Target notifications for YASL surface drags, separate from external file drops. */
enum yasl_drag_event {
@@ -338,11 +355,18 @@ enum yasl_event_type {
YASL_EVENT_DROP, /**< .text — dropped text/uri-list: CRLF-separated file URLs, not paths. */
YASL_EVENT_INPUT_RESET, /**< No payload. Input stream interrupted; clear held keys, buttons, strokes, IME. */
- /* Window and application: delivered only through yasl_app_desc.event().
- * Low-level users receive the same information via yasl_window_cbs. */
+ /* Window and application: part of the display FIFO, as well as runner delivery.
+ * Legacy window callbacks also receive matching native notifications. */
YASL_EVENT_WINDOW_RESIZE, /**< .resize — size and/or scale changed; reallocate and redraw. */
YASL_EVENT_WINDOW_CLOSE, /**< No payload. User asked to close the window. */
- YASL_EVENT_USER, /**< .user — posted with yasl_post_event(). */
+ YASL_EVENT_USER, /**< .user — posted application message. */
+ YASL_EVENT_WINDOW_STATE, /**< .state — reported state changed. */
+ YASL_EVENT_DRAG, /**< .drag — surface-drag target notification. */
+ YASL_EVENT_DROP_HOVER, /**< .drop — external drag hover/leave. */
+ YASL_EVENT_COMPOSITION, /**< .composition — preedit snapshot, including ending. */
+ YASL_EVENT_DISPLAY_QUIT, /**< No payload; system requested application quit. */
+ YASL_EVENT_DISPLAY_REOPEN, /**< No payload; system requested activation. */
+ YASL_EVENT_DISPLAY_LOST, /**< No payload; display connection failed. */
};
/** Physical keyboard transition with optional layout labels.
@@ -401,6 +425,43 @@ struct yasl_text_event {
size_t len;
};
+/** Clipboard transfer outcome. */
+enum yasl_transfer_status {
+ YASL_TRANSFER_OK = 0, /**< Text received successfully, including empty text. */
+ YASL_TRANSFER_UNAVAILABLE, /**< No text selection is available. */
+ YASL_TRANSFER_FAILED, /**< Transfer or decoding failed. */
+};
+
+/** Clipboard completion; data/len alias the legacy text payload. */
+struct yasl_paste_event {
+ const char *data; /**< Borrowed NUL-terminated UTF-8; empty on failure. */
+ size_t len; /**< Byte length excluding NUL. */
+ uint64_t request_id; /**< Zero for a legacy paste request. */
+ enum yasl_transfer_status status; /**< Completion outcome. */
+};
+
+/** Borrowed UTF-8 preedit snapshot, valid until the next successful display poll. */
+struct yasl_composition_event {
+ const char *data; /**< Borrowed NUL-terminated UTF-8 snapshot. */
+ size_t len; /**< Byte length excluding NUL. */
+ int begin; /**< UTF-8 byte offset, or -1 if unavailable. */
+ int end; /**< UTF-8 byte offset, or -1 if unavailable. */
+ bool active; /**< Whether composition text is present. */
+};
+
+/** Reported window-state change. */
+struct yasl_state_event { uint32_t flags; /**< Current YASL_STATE_* flags. */ };
+/** Surface-drag target notification; position is in device pixels. */
+struct yasl_drag_target_event {
+ enum yasl_drag_event action; /**< Hover, leave, or drop. */
+ struct yasl_vector2i pos; /**< Surface-relative device pixels. */
+};
+/** External drag hover notification; position is in device pixels. */
+struct yasl_drop_hover_event {
+ enum yasl_drop_event action; /**< Hover or leave. */
+ struct yasl_vector2i pos; /**< Surface-relative device pixels. */
+};
+
/** Keyboard focus transition. */
struct yasl_focus_event {
/** true on focus gain, false on loss. */
@@ -434,10 +495,19 @@ struct yasl_event {
struct yasl_surface *surface;
/** Monotonic timestamp in nanoseconds, same clock as yasl_loop_now_ns(). */
uint64_t time_ns;
+ /** Increasing display-wide enqueue order; zero for standalone private queues. */
+ uint64_t sequence;
+ /** Stable recipient identity; zero for display-wide events. */
+ uint64_t surface_id;
union {
struct yasl_key_event key; /**< KEY */
struct yasl_pointer_event pointer; /**< POINTER_* */
- struct yasl_text_event text; /**< TEXT, PASTE, DROP */
+ struct yasl_text_event text; /**< TEXT, legacy PASTE, DROP */
+ struct yasl_paste_event paste; /**< PASTE */
+ struct yasl_composition_event composition; /**< COMPOSITION */
+ struct yasl_state_event state; /**< WINDOW_STATE */
+ struct yasl_drag_target_event drag; /**< DRAG */
+ struct yasl_drop_hover_event drop; /**< DROP_HOVER */
struct yasl_focus_event focus; /**< FOCUS */
struct yasl_resize_event resize; /**< WINDOW_RESIZE */
struct yasl_user_event user; /**< USER */
@@ -633,15 +703,20 @@ struct yasl_window_spec {
/** Copied UTF-8 title; NULL uses backend defaults. */
const char *title;
/** Requested logical-pixel width and height; both must be positive. */
- struct yasl_vector2i size;
+ union {
+ struct yasl_vector2i size_logical; /**< Requested logical-pixel extent. */
+ struct yasl_vector2i size; /**< Migration alias for size_logical. */
+ };
/** Request initial fullscreen; actual state is reported asynchronously. */
bool fullscreen;
/** Permit unpaced presentation where supported; a hint, not a guarantee. */
bool tearing;
/** Copied optional window callbacks; NULL disables them. */
const struct yasl_window_cbs *cbs;
- /** Borrowed window callback userdata. */
+ /** Borrowed window callback userdata; ignored by the runner. */
void *ud;
+ /** Borrowed application data, independent of callbacks and available in either loop style. */
+ void *userdata;
};
/** Popup options, entirely in device pixels, including size.
@@ -718,14 +793,15 @@ YASL_API struct yasl_display *yasl_surface_display(const struct yasl_surface *s)
/**
* Replace the surface's callback table and userdata.
- * @param s Surface, or NULL for no action.
+ * @param s Surface.
* @param cbs Table copied by value; NULL removes all callbacks. NULL members are ignored.
* @param ud Borrowed userdata passed to the installed callbacks.
+ * @return true if replaced; false with EINVAL for NULL, EBUSY on a runner-owned surface.
* This call only replaces callbacks; it does not invoke them.
* Use yasl_surface_geometry() to read current geometry; do not rely on receiving
* an initial configure callback when registering.
*/
-YASL_API void yasl_surface_set_callbacks(struct yasl_surface *s,
+YASL_API bool yasl_surface_set_callbacks(struct yasl_surface *s,
const struct yasl_window_cbs *cbs, void *ud);
/**
* Replace the window title with copied UTF-8 text.
@@ -759,21 +835,16 @@ YASL_API void yasl_surface_schedule_redraw(struct yasl_surface *s);
*/
YASL_API bool yasl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer *fb,
const struct yasl_damage_list *damage);
-/* Event payload strings are library-owned, NUL-terminated, and valid until
- * the next SUCCESSFUL poll on this surface or surface destruction. Dispatch,
- * flush and unsuccessful polls do not invalidate them. Copy to keep longer. */
-/**
- * Remove one input event from a surface's queue without waiting.
- * @param s Surface whose queue to drain.
- * @param ev Required output event; unchanged when no event is available.
- * @return true for an event, false for an empty queue or NULL arguments.
- * Dispatch receives native input; polling only drains the queue. Only input
- * types (KEY through INPUT_RESET) are returned. Read the union member selected
- * by type. Payload strings are borrowed, NUL-terminated, and valid until the
- * next successful poll on this queue or its destruction; dispatch, flush, and
- * unsuccessful polls do not invalidate them. On Wayland, popup pointer and
- * keyboard input can be routed through the root parent's queue; inspect
- * ev->surface to identify the receiving surface.
+/**
+ * Migration adapter: consume one input event for a surface from the display FIFO.
+ * Popup input can belong to the root queue; inspect ev->surface. Returns false
+ * for empty/invalid arguments, leaving ev unchanged. Strings remain borrowed
+ * until the next successful display or surface poll, or display close. Pending
+ * recipient events are canceled on destruction. Prefer yasl_display_poll_event()
+ * to receive window, composition, and display events as well as input. This
+ * input-only adapter discards pending non-input events across the display
+ * (legacy callbacks already delivered lifecycle changes). Do not mix
+ * the two polling styles in one application. Use the display thread.
*/
YASL_API bool yasl_surface_poll_event(struct yasl_surface *s, struct yasl_event *ev);
/**
@@ -825,6 +896,73 @@ YASL_API bool yasl_surface_read_pixels(struct yasl_surface *s, uint32_t *out, si
*/
YASL_API bool yasl_surface_set_pointer_mode(struct yasl_surface *s, enum yasl_pointer_mode mode);
+/**
+ * Consume one event from the display-wide FIFO without waiting.
+ * Returns false for an empty queue or invalid arguments, leaving ev unchanged.
+ * Strings remain valid until the next successful poll or display close.
+ * Surface destruction cancels undelivered events, not the last polled payload.
+ * Use the display thread. Do not mix display and surface polling in one app.
+ */
+YASL_API bool yasl_display_poll_event(struct yasl_display *d, struct yasl_event *ev);
+
+/** Stable nonzero identity within a display; zero for NULL. Use on the display thread. */
+YASL_API uint64_t yasl_surface_id(const struct yasl_surface *s);
+/** Store borrowed application data independently of callback userdata. */
+YASL_API void yasl_surface_set_userdata(struct yasl_surface *s, void *userdata);
+/** Read borrowed application data, or NULL for NULL; use on the display thread. */
+YASL_API void *yasl_surface_userdata(const struct yasl_surface *s);
+
+/** Thread-safe message descriptor. Zero target_id means display-wide. */
+struct yasl_message {
+ uint64_t target_id; /**< Surface identity, or zero for the display. */
+ uint32_t code; /**< Application-defined message code. */
+ void *payload; /**< Borrowed until release; passed through unchanged. */
+ size_t size; /**< Application-defined payload length. */
+ /** Optional cleanup on display thread after delivery/cancellation, exactly once.
+ * May post messages, but must not dispatch, poll, or destroy YASL objects. */
+ void (*release)(void *payload);
+};
+/**
+ * Copy and enqueue a message from any thread; the display must stay alive.
+ * Stop producer threads before closing the display. On success release runs
+ * once after consumption or cancellation. On failure ownership stays with the
+ * caller; errno is EINVAL, ENOENT (retired identity), ENOMEM, or EOVERFLOW.
+ */
+YASL_API bool yasl_display_post(struct yasl_display *d, const struct yasl_message *message);
+
+/**
+ * Present the active frame once. NULL/0 means full damage; non-NULL/0 means none.
+ * Validate all rectangles; excess rectangles fall back to full damage.
+ * Returns false with EINVAL for invalid/stale targets, EALREADY for a consumed
+ * frame, or errno from the backend (EIO if unspecified).
+ * Frame and pixels expire at callback return; use the display thread.
+ */
+YASL_API bool yasl_frame_present(struct yasl_frame *frame,
+ const struct yasl_rect2i *rects, size_t count);
+/** Coalesce a redraw request; use on the display thread. NULL is ignored. */
+YASL_API void yasl_surface_request_frame(struct yasl_surface *s);
+/** Set drawing policy for either loop style. Returns false with errno on failure. */
+YASL_API bool yasl_surface_set_pacing(struct yasl_surface *s, yasl_pacing_mode mode);
+
+/** Request a positive logical-pixel size. Success means issued, not configured. */
+YASL_API bool yasl_surface_set_size(struct yasl_surface *s, struct yasl_vector2i size_logical);
+/** Request fullscreen state; returns acceptance, not confirmation. */
+YASL_API bool yasl_surface_set_fullscreen(struct yasl_surface *s, bool enabled);
+/** Request maximized state; returns acceptance, not confirmation. */
+YASL_API bool yasl_surface_set_maximized(struct yasl_surface *s, bool enabled);
+/** Request minimization. Window requests set errno on failure; display thread only. */
+YASL_API bool yasl_surface_minimize(struct yasl_surface *s);
+
+/** Offer copied UTF-8 text. Returns false with errno if invalid/unsupported/failed. */
+YASL_API bool yasl_clipboard_set(struct yasl_display *d, enum yasl_selection selection,
+ const char *text);
+/**
+ * Request text; returns a nonzero ID or zero with errno. One PASTE completion
+ * follows each accepted request unless its surface/display is destroyed.
+ * Inspect paste.status even when data is empty. Use the display thread.
+ */
+YASL_API uint64_t yasl_clipboard_request(struct yasl_surface *s, enum yasl_selection selection);
+
/* Current device-pixel size and scale, matching the configure callback. */
/**
* Read current device-pixel size and scale together.