diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 21:23:03 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 21:23:03 +0300 |
| commit | dd1775a9927922c14f8679ccbc4d3ca8d5917e20 (patch) | |
| tree | 3acc442bb4a3470364b74aa82ff67cb84d555c45 /include | |
| parent | ecb81aeea4c0c880b3a60a0dc8418c4bf2a7cf85 (diff) | |
public api refactor
Diffstat (limited to 'include')
| -rw-r--r-- | include/yasl/app.h | 87 | ||||
| -rw-r--r-- | include/yasl/yasl.h | 186 |
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. |
