summaryrefslogtreecommitdiff
path: root/include/yasl/yasl.h
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /include/yasl/yasl.h
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff)
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'include/yasl/yasl.h')
-rw-r--r--include/yasl/yasl.h1203
1 files changed, 133 insertions, 1070 deletions
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h
index 889f70a..350339b 100644
--- a/include/yasl/yasl.h
+++ b/include/yasl/yasl.h
@@ -1,1089 +1,152 @@
-/**
- * @file
- * Portable desktop surfaces, CPU drawing, input, and display dispatch.
- *
- * 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
- * popups before parents, surfaces before displays, displays before borrowed loops.
- * Surface destruction from its own callback is supported; stop using it immediately.
- *
- * Zero-initialize option and callback structs before setting fields. Pointers to
- * destroyed objects are invalid, even for getters and destroy functions. NULL
- * 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 display-wide dispatch/poll/flush cycle
- * and backend limits. Legacy surface polling is an input-only filtered adapter.
- */
+/** @file Windows, input and events. The first surface starts the backend; use the
+ * creating thread (main on Cocoa) for every call except yasl_wake. Coordinates are
+ * logical units unless named pixel. */
#ifndef YASL_H
#define YASL_H
-
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-#include <limits.h>
-#include <float.h>
-#include <math.h>
-
-#include "yasl/timing.h"
#include "yasl/keycodes.h"
-
+#if defined(__GNUC__)
+#define YASL_API __attribute__((visibility("default")))
+#else
+#define YASL_API
+#endif
#ifdef __cplusplus
extern "C" {
#endif
-
-/** Public shared-library symbol visibility annotation. */
-#if defined(_WIN32) || defined(__CYGWIN__)
- #if defined(YASL_BUILD_SHARED)
- #define YASL_API __declspec(dllexport)
- #elif defined(YASL_SHARED)
- #define YASL_API __declspec(dllimport)
- #else
- #define YASL_API
- #endif
-#elif defined(__GNUC__) && __GNUC__ >= 4
- #define YASL_API __attribute__((visibility("default")))
-#else
- #define YASL_API
-#endif
-
-struct yasl_display;
-struct yasl_surface;
-struct yasl_loop;
-
-/* Geometry */
-/** A two-dimensional integer size, position, or offset; units depend on the caller. */
-struct yasl_vector2i {
- /** Horizontal coordinate or width. */
- int x;
- /** Vertical coordinate or height. */
- int y;
-};
-
-/** Two-dimensional fractional offset; units depend on the containing structure. */
-struct yasl_vector2d {
- /** Horizontal component. */
- double x;
- /** Vertical component. */
- double y;
-};
-
-/** Integer rectangle; origin is upper left and extents must be nonnegative. */
-struct yasl_rect2i {
- /** Left coordinate. */
- int x;
- /** Top coordinate. */
- int y;
- /** Nonnegative horizontal extent. */
- int width;
- /** Nonnegative vertical extent. */
- int height;
-};
-
-/** Scale numerator representing 1x. */
-#define YASL_SCALE_UNIT 120
-/** Backend minimum logical dimension used when constraining toplevel sizes. */
-#define YASL_MIN_LOGICAL_PX 64
-
-/* Nearest integer, ties away from zero. Zero scale returns zero; finite
- * out-of-range results saturate. Non-finite logical coordinates return zero. */
-/** Convert a logical coordinate to device pixels, rounding ties away from zero.
- * @param logical Logical coordinate; non-finite values return zero.
- * @param scale_120 Scale numerator; zero returns zero.
- * @return Rounded device coordinate, saturated to the range of int.
- */
-static inline int yasl_scale_to_device(double logical, uint32_t scale_120)
-{
- if (!scale_120 || !(logical >= -DBL_MAX && logical <= DBL_MAX)) return 0;
- double px = (scale_120 == YASL_SCALE_UNIT) ? logical : (logical * ((double)scale_120 / YASL_SCALE_UNIT));
- if (px >= INT_MAX) return INT_MAX;
- if (px <= INT_MIN) return INT_MIN;
- return (int)(px + copysign(0.5, px));
-}
-
-/** Convert a device coordinate to logical pixels, rounding ties away from zero.
- * @param device Device coordinate.
- * @param scale_120 Scale numerator; zero returns zero.
- * @return Rounded logical coordinate, saturated to the range of int.
- */
-static inline int yasl_scale_to_logical(int device, uint32_t scale_120)
-{
- if (!scale_120) return 0;
- if (scale_120 == YASL_SCALE_UNIT) return device;
- int64_t px = (int64_t)device * YASL_SCALE_UNIT;
- int64_t half = (int64_t)(scale_120 / 2);
- int64_t bias = (px < 0) ? -half : half;
- px = (px + bias) / scale_120;
- if (px > INT_MAX) return INT_MAX;
- if (px < INT_MIN) return INT_MIN;
- return (int)px;
-}
-
-/* Capabilities */
-/** Optional backend/server features, returned as a bitmask by yasl_display_caps(). */
-enum yasl_display_cap : uint32_t {
- YASL_CAP_POPUPS = 1 << 0, /**< Popup creation and placement. */
- YASL_CAP_DRAG = 1 << 1, /**< Surface-drag source and target support. */
- YASL_CAP_DRAG_CARRY = 1 << 2, /**< Carry a toplevel during a drag. */
- YASL_CAP_PLACE_WINDOW = 1 << 3, /**< Place a window relative to the pointer. */
- YASL_CAP_PRIMARY_SELECTION = 1 << 4, /**< Separate primary selection. */
- YASL_CAP_CSD = 1 << 5, /**< Backend advertises client decoration support; check each action result. */
- YASL_CAP_NATIVE_GRAPHICS = 1 << 6, /**< Application-managed native rendering. */
- YASL_CAP_FRAME_PACING = 1 << 7, /**< Compositor/display-driven draws. */
- /* Backend/protocol supports tablet axes, independent of attached hardware. */
- YASL_CAP_TABLET = 1 << 8, /**< Tablet protocol support, independent of attached hardware. */
-};
-
-/** Independent selections. An unsupported selection never aliases the clipboard. */
-enum yasl_selection : uint8_t {
- YASL_CLIPBOARD, /**< Explicit copy/paste selection. */
- YASL_PRIMARY, /**< Independent primary selection, if supported. */
-};
-
-/** Reported surface state flags; absent flags may also mean unsupported state. */
-enum yasl_surface_state : uint32_t {
- YASL_STATE_FULLSCREEN = 1 << 0, /**< Fullscreen. */
- YASL_STATE_MAXIMIZED = 1 << 1, /**< Maximized. */
- YASL_STATE_ACTIVATED = 1 << 2, /**< Active window. */
- YASL_STATE_SUSPENDED = 1 << 3, /**< Compositor reports suspension. */
- YASL_STATE_CSD = 1 << 4, /**< Backend reports client-side decorations. */
- YASL_STATE_TILED = 1 << 5, /**< At least one edge is tiled; currently reported by Wayland. */
-};
-
-/** System cursor shapes. HIDDEN preserves pointer input; NONE is its compatibility alias. */
-enum yasl_cursor {
- YASL_CURSOR_ARROW, /**< Default arrow. */
- YASL_CURSOR_TEXT, /**< Text insertion. */
- YASL_CURSOR_LINK, /**< Link/pointer hand. */
- YASL_CURSOR_CROSSHAIR, /**< Crosshair. */
- YASL_CURSOR_MOVE, /**< Move in any direction. */
- YASL_CURSOR_RESIZE_NWSE, /**< Northwest/southeast resize. */
- YASL_CURSOR_RESIZE_NESW, /**< Northeast/southwest resize. */
- YASL_CURSOR_RESIZE_EW, /**< Horizontal resize. */
- YASL_CURSOR_RESIZE_NS, /**< Vertical resize. */
- YASL_CURSOR_HIDDEN, /**< Hidden system cursor; pointer input continues. */
- YASL_CURSOR_NONE = YASL_CURSOR_HIDDEN, /**< Compatibility alias for HIDDEN. */
-};
-
-/** Valid interactive resize edges; combinations are restricted to the named values. */
-enum yasl_resize_edge : uint32_t {
- YASL_EDGE_NONE = 0, /**< No resize edge; rejected by interactive resize. */
- YASL_EDGE_TOP = 1, /**< Top edge. */
- YASL_EDGE_BOTTOM = 2, /**< Bottom edge. */
- YASL_EDGE_LEFT = 4, /**< Left edge. */
- YASL_EDGE_TOP_LEFT = 5, /**< Top-left corner. */
- YASL_EDGE_BOTTOM_LEFT = 6, /**< Bottom-left corner. */
- YASL_EDGE_RIGHT = 8, /**< Right edge. */
- YASL_EDGE_TOP_RIGHT = 9, /**< Top-right corner. */
- YASL_EDGE_BOTTOM_RIGHT = 10, /**< Bottom-right corner. */
-};
-
-/* Damage & Framebuffer
- * CPU pixels are tightly packed premultiplied ARGB8888 (0xAARRGGBB).
- * Size, pointer positions, IME caret and damage use device pixels; surface
- * toplevel creation sizes use logical pixels. Damage is a hint: backends may upload
- * the whole frame. Every pixel must contain valid content on each draw.
- */
-/** Maximum number of damage rectangles in one presentation. */
-#define YASL_DAMAGE_MAX 64
-
-/** Damage hints for one presentation; every target still needs complete valid pixels. */
-struct yasl_damage_list {
- /** -1: full target; 0: no damaged rectangles; otherwise number of rects. */
- int n;
- /** Reserved hint; callers may leave zero. Core presentation uses rects. */
- struct yasl_rect2i bounds;
- /** First n rectangles, in device pixels; ignored for n == -1. */
- struct yasl_rect2i rects[YASL_DAMAGE_MAX];
-};
-
-/** Borrowed draw target, valid only for the current draw callback. Never free pixels. */
-struct yasl_framebuffer {
- /** Opaque draw identity. Preserve it and all target fields when copying. */
- uint64_t generation;
- /** Writable premultiplied ARGB8888, row stride size.x * sizeof(uint32_t); may be NULL for native rendering. */
- 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. */
-struct yasl_frame {
- /** Surface being drawn. */
- 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 {
- YASL_DRAG_OVER, /**< Surface drag entered or moved over the target. */
- YASL_DRAG_LEAVE, /**< Surface drag left the target. */
- YASL_DRAG_DROP, /**< Surface drag dropped on the target. */
-};
-
-/** External text/file drag hover notifications; completed data arrives through input. */
-enum yasl_drop_event {
- YASL_DROP_OVER, /**< External data drag entered or moved over the target. */
- YASL_DROP_LEAVE, /**< External data drag left the target. */
-};
-
-/** Source-side drag completion; DROPPED does not prove application-level acceptance. */
-enum yasl_drag_end {
- YASL_DRAG_DROPPED, /**< Drag ended in a drop; not an application acceptance receipt. */
- YASL_DRAG_CANCELLED, /**< Drag canceled, including display close. */
-};
-
-/** Copied drag icon in tightly packed premultiplied 0xAARRGGBB device pixels. */
-struct yasl_drag_image {
- /** Copied pixel array; required when an image is supplied. */
- const uint32_t *pixels;
- /** Positive width and height in device pixels. */
- struct yasl_vector2i size;
- /** Pointer position within the image, in device pixels. */
- struct yasl_vector2i hotspot;
-};
-
-/** Copied drag completion listener; userdata remains owned by the application. */
-struct yasl_drag_listener {
- /** Called exactly once after a successful start, possibly synchronously on cancel/close. */
- void (*end)(void *ud, enum yasl_drag_end how);
-};
-
-/** Configured device-pixel content size and the corresponding display scale. */
-struct yasl_geometry {
- /** Current content extent in device pixels. */
- struct yasl_vector2i size;
- /** Positive scale numerator; 120 means 1x and 180 means 1.5x. */
- uint32_t scale_120;
-};
-
-/* Input Model */
-/** Keyboard press, release, or autorepeat; releases must not insert text. */
-enum yasl_key_action {
- YASL_KEY_PRESS, /**< Key pressed. */
- YASL_KEY_RELEASE, /**< Key released. */
- YASL_KEY_REPEAT, /**< Key autorepeat. */
-};
-
-/** Modifier bitmask. SUPER is Command on macOS. */
-enum yasl_mod : uint32_t {
- YASL_MOD_SHIFT = 1 << 0, /**< Shift modifier. */
- YASL_MOD_ALT = 1 << 1, /**< Alt/Option modifier. */
- YASL_MOD_CTRL = 1 << 2, /**< Control modifier. */
- YASL_MOD_SUPER = 1 << 3, /**< Super/Command modifier. */
- YASL_MOD_CAPS = 1 << 4, /**< Caps Lock modifier. */
-};
-
-/** Pointer source class; capability support does not imply an attached device. */
-enum yasl_pointer_device {
- YASL_PTR_DEV_MOUSE, /**< Mouse or trackpad pointer. */
- YASL_PTR_DEV_TOUCH, /**< Touch translated into pointer input. */
- YASL_PTR_DEV_PEN, /**< Tablet stylus. */
- YASL_PTR_DEV_ERASER, /**< Tablet eraser tool. */
-};
-
-/** Pointer button; meaningful only for POINTER_DOWN and POINTER_UP. */
-enum yasl_pointer_button {
- YASL_BUTTON_PRIMARY = 0, /**< Left button, pen tip, or touch contact. */
- YASL_BUTTON_MIDDLE = 1, /**< Middle button / wheel click. */
- YASL_BUTTON_SECONDARY = 2, /**< Right button or pen barrel button. */
- YASL_BUTTON_BACK = 3, /**< Side "back" button. */
- YASL_BUTTON_FORWARD = 4, /**< Side "forward" button. */
-};
-
-/** Bit for a yasl_pointer_button in yasl_pointer_event.buttons. */
+typedef struct yasl_surface yasl_surface;
+typedef struct yasl_event yasl_event;
+enum yasl_backend { YASL_BACKEND_AUTO, YASL_BACKEND_WAYLAND, YASL_BACKEND_X11, YASL_BACKEND_COCOA };
+enum yasl_surface_flags { YASL_SURFACE_CPU=1u, YASL_SURFACE_HIDDEN=2u, YASL_SURFACE_UNDECORATED=4u, YASL_SURFACE_FIXED_SIZE=8u };
+enum yasl_error { YASL_ERROR_NONE, YASL_ERROR_INVALID, YASL_ERROR_UNSUPPORTED, YASL_ERROR_NO_MEMORY,
+ YASL_ERROR_NOT_INITIALIZED, YASL_ERROR_BUSY, YASL_ERROR_WRONG_THREAD, YASL_ERROR_CONTEXT_EXPIRED, YASL_ERROR_IO };
+enum yasl_selection { YASL_CLIPBOARD, YASL_PRIMARY };
+enum yasl_key_action { YASL_KEY_PRESS, YASL_KEY_RELEASE, YASL_KEY_REPEAT };
+enum yasl_mod { YASL_MOD_SHIFT=1u, YASL_MOD_ALT=2u, YASL_MOD_CTRL=4u, YASL_MOD_SUPER=8u, YASL_MOD_CAPS=16u };
+enum yasl_pointer_action { YASL_POINTER_MOVE, YASL_POINTER_DOWN, YASL_POINTER_UP, YASL_POINTER_LEAVE };
+enum yasl_pointer_mode { YASL_POINTER_NORMAL, YASL_POINTER_RELATIVE };
+enum yasl_button { YASL_BUTTON_PRIMARY, YASL_BUTTON_MIDDLE, YASL_BUTTON_SECONDARY, YASL_BUTTON_BACK, YASL_BUTTON_FORWARD };
#define YASL_BUTTON_BIT(button) (1u << (button))
-
-/** Pointer capture mode for a surface. */
-enum yasl_pointer_mode {
- YASL_POINTER_NORMAL = 0, /**< Absolute positions; cursor per yasl_surface_set_cursor(). */
- /** Cursor hidden and locked in place while the surface has focus. POINTER_MOTION
- * reports unbounded relative motion in delta; pos stays at the lock position.
- * The lock is released on focus loss and re-acquired on focus gain. */
- YASL_POINTER_RELATIVE,
-};
-
-/** Normalized tablet axes; zero for unavailable axes and non-tablet devices. */
-struct yasl_pointer_pen {
- /** 0..65535 normalized to device range. Zero alone does not end contact. */
- uint16_t pressure;
- /** Degrees in -90..90; positive right. */
- int8_t tilt_x;
- /** Degrees in -90..90; positive down. */
- int8_t tilt_y;
-};
-
-/** Event tag. Each tag lists the union member it selects. */
-enum yasl_event_type {
- YASL_EVENT_NONE = 0,
-
- /* Input: produced by backends, returned by yasl_surface_poll_event(). */
- YASL_EVENT_KEY, /**< .key */
- YASL_EVENT_TEXT, /**< .text — committed UTF-8; insert this, not key codepoints. */
- YASL_EVENT_POINTER_DOWN, /**< .pointer — button/tip pressed; button valid. */
- YASL_EVENT_POINTER_UP, /**< .pointer — button/tip released; button valid. */
- YASL_EVENT_POINTER_MOTION, /**< .pointer — position, relative motion, or pen axes changed. */
- YASL_EVENT_POINTER_SCROLL, /**< .pointer — scroll valid. */
- YASL_EVENT_POINTER_LEAVE, /**< .pointer — last known pos/device; cancel hover state. */
- YASL_EVENT_FOCUS, /**< .focus — keyboard focus changed; cancel held state on loss. */
- YASL_EVENT_PASTE, /**< .text — UTF-8 from yasl_display_paste(). */
- 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: 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 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.
- * key is independent of modifiers/layout and stable between press and release.
- * codepoint and shifted are optional single Unicode scalars for the current
- * layout at levels zero/one, not text input. Zero means unavailable, a control
- * key, or a layout mapping that produces multiple characters. Insert committed
- * YASL_EVENT_TEXT into documents instead. */
-struct yasl_key_event {
- /** Portable physical key; YASL_KEY_UNKNOWN when unmapped. */
- enum yasl_key key;
- /** Press, release, or autorepeat. */
- enum yasl_key_action action;
- /** yasl_mod bitmask at this event. */
- uint32_t mods;
- /** Optional unshifted layout Unicode scalar; zero if unavailable. */
- uint32_t codepoint;
- /** Optional shifted layout Unicode scalar; zero if unavailable. */
- uint32_t shifted;
- /** Native code: Wayland evdev, X11 server keycode, Cocoa virtual keycode. */
- uint32_t native_code;
-};
-
-/** Pointer sample shared by all POINTER_* events. Pen and eraser share it with
- * mouse input. Track contact with DOWN/UP of the primary button, not pressure.
- * This is not a multi-contact touch API. */
-struct yasl_pointer_event {
- /** Surface-relative device-pixel position. Frozen while YASL_POINTER_RELATIVE is locked. */
- struct yasl_vector2i pos;
- /** MOTION: device-pixel movement since the previous sample on this surface.
- * Unbounded under YASL_POINTER_RELATIVE; zero after enter, leave, or reset. */
- struct yasl_vector2d delta;
- /** SCROLL: fractional line offsets after system preferences; positive right/down. */
- struct yasl_vector2d scroll;
- /** DOWN/UP: which button changed. */
- enum yasl_pointer_button button;
- /** YASL_BUTTON_BIT() mask of buttons held after this event, on every
- * POINTER_* type. Tracked from this queue's DOWN and UP events for all
- * devices; INPUT_RESET clears it. On Wayland LEAVE clears it too, since the
- * compositor sends leave during a press only when it takes the pointer.
- * X11 and Cocoa keep sending motion and the release after LEAVE. */
- uint32_t buttons;
- /** Mouse, touch, pen, or eraser. */
- enum yasl_pointer_device device;
- /** yasl_mod bitmask at this event. */
- uint32_t mods;
- /** Current tablet axes, including on pressure-only motion; missing axes are zero. */
- struct yasl_pointer_pen pen;
-};
-
-/** Borrowed NUL-terminated UTF-8, shared by TEXT, PASTE and DROP. */
-struct yasl_text_event {
- /** Borrowed NUL-terminated bytes; see yasl_surface_poll_event() for lifetime. */
- const char *data;
- /** Length in bytes excluding the terminating NUL. */
- 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. */
- bool focused;
-};
-
-/** New configured geometry for a surface. */
-struct yasl_resize_event {
- /** Content size in device pixels and display scale. */
- struct yasl_geometry geometry;
- /** true when scale_120 differs from the previous resize of this surface. */
- bool scale_changed;
-};
-
-/** Application message posted with yasl_post_event(). */
-struct yasl_user_event {
- /** Application-defined message code. */
- uint32_t code;
- /** Pointer passed through unchanged; ownership stays with the application. */
- void *payload;
- /** Optional payload size, passed through unchanged. */
- size_t size;
-};
-
-/** One tagged event; read only the union member selected by type. */
+enum yasl_pen_tool { YASL_PEN_UNKNOWN, YASL_PEN_PEN, YASL_PEN_ERASER, YASL_PEN_BRUSH, YASL_PEN_AIRBRUSH, YASL_PEN_PENCIL };
+enum yasl_pen_action { YASL_PEN_ENTER, YASL_PEN_LEAVE, YASL_PEN_MOVE, YASL_PEN_DOWN, YASL_PEN_UP, YASL_PEN_BUTTON, YASL_PEN_CANCEL };
+enum yasl_pen_axis { YASL_PEN_PRESSURE=1u, YASL_PEN_TILT=2u, YASL_PEN_ROTATION=4u, YASL_PEN_DISTANCE=8u, YASL_PEN_TANGENTIAL=16u, YASL_PEN_WHEEL=32u };
+enum yasl_scroll_valid { YASL_SCROLL_LINES=1u, YASL_SCROLL_PIXELS=2u };
+enum yasl_scroll_source { YASL_SCROLL_UNKNOWN, YASL_SCROLL_WHEEL, YASL_SCROLL_FINGER, YASL_SCROLL_CONTINUOUS };
+enum yasl_scroll_phase { YASL_SCROLL_PHASE_UNKNOWN, YASL_SCROLL_BEGIN, YASL_SCROLL_UPDATE, YASL_SCROLL_END };
+enum yasl_transfer_status { YASL_TRANSFER_OK, YASL_TRANSFER_UNAVAILABLE, YASL_TRANSFER_FAILED };
+enum yasl_text_purpose { YASL_TEXT_NORMAL, YASL_TEXT_PASSWORD, YASL_TEXT_NUMBER, YASL_TEXT_TERMINAL };
+enum yasl_cursor { YASL_CURSOR_ARROW, YASL_CURSOR_TEXT, YASL_CURSOR_LINK, YASL_CURSOR_CROSSHAIR, YASL_CURSOR_MOVE,
+ YASL_CURSOR_RESIZE_NWSE, YASL_CURSOR_RESIZE_NESW, YASL_CURSOR_RESIZE_EW, YASL_CURSOR_RESIZE_NS, YASL_CURSOR_HIDDEN };
+enum yasl_surface_state { YASL_STATE_FULLSCREEN=1u, YASL_STATE_MAXIMIZED=2u, YASL_STATE_ACTIVATED=4u,
+ YASL_STATE_SUSPENDED=8u, YASL_STATE_CSD=16u, YASL_STATE_TILED=32u };
+enum yasl_feature { YASL_CAP_POPUPS=1u, YASL_CAP_DRAG=2u, YASL_CAP_DRAG_CARRY=4u, YASL_CAP_PLACE_WINDOW=8u,
+ YASL_CAP_PRIMARY_SELECTION=16u, YASL_CAP_CSD=32u, YASL_CAP_NATIVE_GRAPHICS=64u, YASL_CAP_FRAME_PACING=128u,
+ YASL_CAP_TABLET=256u, YASL_CAP_OPENGL=512u, YASL_CAP_VULKAN=1024u, YASL_CAP_TEXT_INPUT=2048u };
+enum yasl_popup_edge { YASL_POPUP_CENTER, YASL_POPUP_TOP, YASL_POPUP_BOTTOM, YASL_POPUP_LEFT,
+ YASL_POPUP_RIGHT, YASL_POPUP_TOP_LEFT, YASL_POPUP_BOTTOM_LEFT, YASL_POPUP_TOP_RIGHT, YASL_POPUP_BOTTOM_RIGHT };
+enum yasl_popup_constraint { YASL_POPUP_SLIDE_X=1u, YASL_POPUP_SLIDE_Y=2u, YASL_POPUP_FLIP_X=4u,
+ YASL_POPUP_FLIP_Y=8u, YASL_POPUP_RESIZE_X=16u, YASL_POPUP_RESIZE_Y=32u };
+enum yasl_resize_edge { YASL_EDGE_TOP=1, YASL_EDGE_BOTTOM=2, YASL_EDGE_LEFT=4, YASL_EDGE_TOP_LEFT=5,
+ YASL_EDGE_BOTTOM_LEFT=6, YASL_EDGE_RIGHT=8, YASL_EDGE_TOP_RIGHT=9, YASL_EDGE_BOTTOM_RIGHT=10 };
+enum yasl_event_type { YASL_EVENT_NONE, YASL_EVENT_CLOSE, YASL_EVENT_QUIT, YASL_EVENT_REOPEN, YASL_EVENT_WINDOW,
+ YASL_EVENT_REFRESH, YASL_EVENT_KEY, YASL_EVENT_TEXT, YASL_EVENT_POINTER, YASL_EVENT_SCROLL, YASL_EVENT_PEN,
+ YASL_EVENT_INPUT_RESET, YASL_EVENT_COMPOSITION, YASL_EVENT_TEXT_EDIT, YASL_EVENT_CLIPBOARD, YASL_EVENT_DROP,
+ YASL_EVENT_DRAG, YASL_EVENT_DISPLAY_LOST };
+enum yasl_drop_action { YASL_DROP_OVER, YASL_DROP_LEAVE, YASL_DROP_DATA };
+enum yasl_drag_action { YASL_DRAG_OVER, YASL_DRAG_LEAVE, YASL_DRAG_DROP };
+/** Read the union member named by type. Strings stay valid until the next wait.
+ * CLOSE: the user closed this window. QUIT: the system asked the app to quit.
+ * WINDOW: size, scale or state changed. REFRESH: draw now; sent once the window
+ * has a size, after every resize and when the system needs the contents again.
+ * INPUT_RESET: forget held keys, buttons and strokes. DROP: external data over
+ * the window, delivered as DATA. DRAG: another YASL surface dragged over. */
struct yasl_event {
- /** Selects the valid union member. */
enum yasl_event_type type;
- /** Recipient surface, or NULL for display-wide events. Can differ from the
- * polled surface for routed popup input. */
- struct yasl_surface *surface;
- /** Monotonic timestamp in nanoseconds, same clock as yasl_loop_now_ns(). */
+ yasl_surface *surface;
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, 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 */
- };
-};
-
-/* Ownership and threading
- * All calls and callbacks run on the display's opening thread (main thread on
- * Cocoa). Displays borrow supplied loops; destroy surfaces before displays,
- * popups before parents, and displays before their supplied loop.
- * Specs, strings, callback tables and drag listeners are copied during calls.
- * Userdata is borrowed until callbacks are removed or the object/drag ends.
- * Surface destruction is allowed from its callbacks; display/loop destruction
- * during dispatch or callbacks is not supported.
- */
-
-/* Callbacks */
-/** Optional display notifications. NULL callback members are ignored. */
-struct yasl_display_cbs {
- /** Application quit request; arrange orderly shutdown after dispatch returns. */
- void (*quit)(void *ud);
- /** Application reopen/activation request, currently Cocoa. */
- void (*reopen)(void *ud);
- /** Display connection lost; arrange cleanup after dispatch returns. */
- void (*lost)(void *ud);
-};
-
-/** Optional window/popup notifications, copied from yasl_window_spec.cbs or by
-yasl_surface_set_callbacks().
-Callbacks may destroy their surface. They must then return without further use
-of the surface or draw target. NULL members are ignored. */
-struct yasl_window_cbs {
- /** Initialize the entire target and optionally present. Requested through schedule_redraw/flush. */
- void (*draw)(struct yasl_surface *s, struct yasl_frame *frame, void *ud);
- /** Configured size/scale changed; reallocate application content and request a redraw. */
- void (*configure)(struct yasl_surface *s, struct yasl_geometry geometry, void *ud);
- /** Window/popup close request; application is responsible for destruction. */
- void (*close)(struct yasl_surface *s, void *ud);
- /** Reported yasl_surface_state bitmask changed; matches yasl_surface_state(s). */
- void (*state)(struct yasl_surface *s, uint32_t state, void *ud);
- /** YASL surface-drag target hover, leave, or drop; pos is in device pixels. */
- void (*drag)(struct yasl_surface *s, enum yasl_drag_event ev,
- struct yasl_vector2i pos, void *ud);
- /** External data-drag hover or leave; pos is in device pixels. */
- void (*drop)(struct yasl_surface *s, enum yasl_drop_event ev,
- struct yasl_vector2i pos, void *ud);
-};
-
-/* Display Lifecycle */
-/** Runtime backend choice. AUTO selects a native backend and allows fallback. */
-enum yasl_backend {
- YASL_BACKEND_AUTO = 0, /**< Choose native backend with fallback. */
- YASL_BACKEND_WAYLAND, /**< Require Wayland. */
- YASL_BACKEND_X11, /**< Require X11. */
- YASL_BACKEND_COCOA, /**< Require Cocoa. */
-};
-
-/** Display options. Zero-initialize for automatic backend selection. */
-struct yasl_display_spec {
- /** Copied application identifier, conventionally a reverse-domain UTF-8 string; NULL uses backend defaults. */
- const char *app_id;
- /** Copied optional display callbacks; NULL disables them. */
- const struct yasl_display_cbs *cbs;
- /** Borrowed display callback userdata. */
- void *ud;
-
- /** Zero/AUTO chooses native backend; explicit choices never fall back. */
- enum yasl_backend backend;
-};
-
-/* Return NULL and set errno if the requested backend cannot open. */
-/**
- * Open a desktop connection and its event machinery.
- * @param loop Borrowed loop, or NULL to create a display-owned loop.
- * @param spec Copied options, or NULL for automatic backend selection and defaults.
- * @return An owned display, or NULL with errno set. EINVAL means an invalid backend;
- * ENOSYS means the requested backend was not built; ENODEV is the fallback when
- * opening fails without a more specific platform error. Explicit choices never
- * fall back. Close with yasl_display_close() after destroying its surfaces.
- */
-YASL_API struct yasl_display *yasl_display_open(struct yasl_loop *loop,
- const struct yasl_display_spec *spec);
-/**
- * Read the selected backend.
- * @param d Display, or NULL.
- * @return The actual backend, or YASL_BACKEND_AUTO for NULL.
- */
-YASL_API enum yasl_backend yasl_display_backend(const struct yasl_display *d);
-/**
- * Close a display and release its owned loop, if any.
- * @param d Display to close, or NULL for no action.
- * Destroy all surfaces first. Cancels an active drag and may invoke its end
- * listener. Must not be called during dispatch or from a callback.
- */
-YASL_API void yasl_display_close(struct yasl_display *d);
-/**
- * Query currently available optional features.
- * @param d Display, or NULL.
- * @return A bitmask of yasl_display_cap values, or zero for NULL.
- * Capabilities describe backend/server support, not attached input hardware or
- * permission to perform an operation at any arbitrary moment.
- */
-YASL_API uint32_t yasl_display_caps(const struct yasl_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_display_flush() after updating application state. Do not dispatch recursively.
- */
-YASL_API int yasl_display_dispatch(struct yasl_display *d, int timeout_ms);
-/**
- * Draw scheduled surfaces and send pending display requests.
- * @param d Display, or NULL for no action.
- * May synchronously invoke draw and other callbacks. A paced surface may wait
- * for its next display/compositor signal. This is not a GPU completion wait.
- */
-YASL_API void yasl_display_flush(struct yasl_display *d);
-/**
- * Read the latest modifier state known to the backend.
- * @param d Display, or NULL.
- * @return A bitmask of yasl_mod values, or zero for NULL.
- * For an individual event use its own mods field instead.
- */
-YASL_API int yasl_display_modifiers(const struct yasl_display *d);
-/** Double-click interval used when the system reports none. */
-#define YASL_DOUBLE_CLICK_MS_DEFAULT 400
-/**
- * Read the system's double-click interval.
- * @param d Display, or NULL.
- * @return Maximum milliseconds between the clicks of a double click, or
- * YASL_DOUBLE_CLICK_MS_DEFAULT when d is NULL or the system reports none.
- * X11 reads the XSETTINGS Net/DoubleClickTime value. Wayland, and X11 without
- * XSETTINGS, read the KDE or GNOME setting through the XDG Settings portal,
- * which needs D-Bus and can wait briefly. Cocoa reads the system interval.
- * The user can change it at any time; read it again when a window gains focus
- * rather than on every click.
- */
-YASL_API int yasl_display_double_click_ms(const struct yasl_display *d);
-/* Unsupported/invalid selections are no-ops, never clipboard aliases. */
-/**
- * Offer a copy of a NUL-terminated UTF-8 string as a selection.
- * @param d Display, or NULL for no action.
- * @param sel YASL_CLIPBOARD or YASL_PRIMARY.
- * @param text Text copied during this call; NULL does nothing.
- * Unsupported selections do nothing. The void return does not confirm that the
- * system accepted the offer; Wayland may require a recent input serial.
- */
-YASL_API void yasl_display_copy(struct yasl_display *d, enum yasl_selection sel, const char *text);
-/**
- * Request text delivery to a particular surface.
- * @param d Display that owns target.
- * @param sel YASL_CLIPBOARD or YASL_PRIMARY.
- * @param target Destination surface; NULL or a surface on another display does nothing.
- * Results arrive as YASL_EVENT_PASTE, possibly during a later dispatch. No result
- * is promised for unavailable data or a failed transfer. Destroying target cancels
- * delivery. Unsupported selections do nothing.
- */
-YASL_API void yasl_display_paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target);
-
-/* A successful drag invokes the copied listener's non-NULL end once, including
- * cancel and display close. Failed starts do not invoke it. */
-/**
- * Start a surface drag from a recent pointer press.
- * @param d Display that owns origin.
- * @param origin Origin surface.
- * @param image Optional copied premultiplied ARGB8888 drag image, or NULL.
- * @param l Optional copied completion listener, or NULL.
- * @param ud Borrowed listener userdata until completion.
- * @return true if started; false if unsupported, invalid, or not currently permitted.
- * A successful start invokes a non-NULL end callback exactly once, including
- * cancellation or display close. Failed starts do not invoke it. This API carries
- * surfaces, not arbitrary MIME payloads; use application state to identify the item.
- */
-YASL_API bool yasl_display_drag_start(struct yasl_display *d, struct yasl_surface *origin,
- const struct yasl_drag_image *image,
- const struct yasl_drag_listener *l, void *ud);
-/**
- * Cancel the active surface drag, if any.
- * @param d Display, or NULL for no action.
- * May invoke the end listener synchronously.
- */
-YASL_API void yasl_display_drag_cancel(struct yasl_display *d);
-
-/* Surface Lifecycle */
-/** Toplevel options. Zero-initialize, then supply a positive logical-pixel size. */
-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. */
union {
- struct yasl_vector2i size_logical; /**< Requested logical-pixel extent. */
- struct yasl_vector2i size; /**< Migration alias for size_logical. */
+ struct { int width,height,pixel_width,pixel_height; double scale; unsigned state; } window;
+ struct { enum yasl_key key; enum yasl_key_action action; unsigned mods;
+ uint32_t codepoint, shifted, native_code; } key;
+ struct { const char *data; size_t length; } text;
+ struct { double x,y,dx,dy; enum yasl_pointer_action action; unsigned button,buttons,mods; } pointer;
+ struct { double x,y,lines_x,lines_y,pixels_x,pixels_y; unsigned valid,source,phase,mods; bool momentum; } scroll;
+ struct { uint64_t device_id,tool_id; double x,y,pressure,tilt_x,tilt_y,rotation,distance,tangential,wheel_degrees;
+ unsigned axes_valid,axes_changed,buttons,changed_button,tool,action; bool in_contact; } pen;
+ struct { const char *data; size_t length; int begin,end; bool active; uint64_t revision,generation; } composition;
+ struct { const char *data; size_t length,begin,end; uint64_t revision,generation; } text_edit;
+ struct { const char *data; size_t length; uint64_t request_id; enum yasl_transfer_status status; } clipboard;
+ /** DATA carries a text/uri-list for yasl_drop_next_path; x/y are set for OVER. */
+ struct { enum yasl_drop_action action; double x,y; const char *data; size_t length; } drop;
+ struct { enum yasl_drag_action action; double x,y; } drag;
};
- /** 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; 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.
-The content rectangle excludes transparent margins/shadows used for placement.
-An axis of content_size equal to zero extends to that axis of size. The offset
-and resolved content size must fit in size. Anchor extents must be nonnegative.
-Dimensions must be positive, at most 32767, and fit an INT32_MAX-byte buffer;
-backends may impose further limits after scaling or resolving placement. */
-struct yasl_popup_spec {
- /** Full popup framebuffer extent in device pixels, including transparent margins. */
- struct yasl_vector2i size;
- /** Rectangle in parent framebuffer coordinates, in device pixels. */
- struct yasl_rect2i anchor;
- /** true prefers right of anchor; false prefers below. Placement may flip/slide. */
- bool beside;
- /** Top-left content offset within the popup, in device pixels. */
- struct yasl_vector2i content_offset;
- /** Content extent; zero per axis extends to the corresponding size edge. */
- struct yasl_vector2i content_size;
-};
-
-/**
- * Create a resizable desktop window with CPU drawing targets.
- * @param d Owning display.
- * @param spec Required copied options; size is in logical pixels.
- * @return An owned surface, or NULL with errno set. EINVAL means invalid options,
- * including a nonpositive dimension, a dimension above 32767, or a buffer above
- * INT32_MAX bytes. ENODEV is the fallback backend failure. Actual configured
- * size may differ from the request. The callback table in spec->cbs is copied;
- * spec->ud stays borrowed until callbacks are replaced or the surface is destroyed.
- * This window's callbacks cannot run before creation returns. Use
- * yasl_surface_geometry() for initial geometry; an initial configure callback
- * is not guaranteed. Schedule an initial redraw after setting up application state.
- * On a display owned by yasl_run(), the runner installs its own callbacks instead;
- * use yasl_app_desc.event and yasl_app_desc.frame for application notifications.
- */
-YASL_API struct yasl_surface *yasl_surface_create_toplevel(struct yasl_display *d,
- const struct yasl_window_spec *spec);
-/**
- * Create an owned popup attached to a parent surface.
- * @param parent Borrowed parent; destroy the popup before the parent.
- * @param spec Required copied options, entirely in device pixels.
- * @return A popup, or NULL with errno set: EINVAL for invalid options, ENOTSUP
- * for missing popup support, or a backend error (ENODEV if none was supplied).
- * Wayland requires a recent input serial for its popup grab. The backend may
- * flip or slide placement to fit the screen. See yasl_popup_spec.
- */
-YASL_API struct yasl_surface *yasl_surface_create_popup(struct yasl_surface *parent,
- const struct yasl_popup_spec *spec);
-/**
- * Update a popup's geometry and placement.
- * @param popup An existing popup.
- * @param spec Required copied replacement options, in device pixels.
- * @return true on success; false with errno set: EINVAL for invalid options,
- * ENOTSUP for missing popup support, or a backend error (ENODEV if unspecified).
- * Older Wayland popup protocol versions can reject repositioning.
- */
-YASL_API bool yasl_surface_popup_reposition(struct yasl_surface *popup,
- const struct yasl_popup_spec *spec);
-/**
- * Destroy a surface and cancel its surface timers and pending input.
- * @param s Surface, or NULL for no action.
- * Destroy child popups first. May be called from a surface callback; return from
- * that callback without further use of the surface or its draw target. Every
- * pointer or native handle obtained from this surface becomes invalid.
- */
-YASL_API void yasl_surface_destroy(struct yasl_surface *s);
-/**
- * Get the display that owns a surface.
- * @param s Surface, or NULL.
- * @return A borrowed display, or NULL.
- */
-YASL_API struct yasl_display *yasl_surface_display(const struct yasl_surface *s);
-
-/**
- * Replace the surface's callback table and userdata.
- * @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 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.
- * @param s Surface.
- * @param title NUL-terminated UTF-8 title. Pass an empty string to clear it.
- * Backends may truncate the title.
- */
-YASL_API void yasl_surface_set_title(struct yasl_surface *s, const char *title);
-/**
- * Request a future draw callback, coalescing repeated requests.
- * @param s Surface, or NULL for no action.
- * Call yasl_display_flush() to service the request. Schedule again from draw to
- * animate. Without YASL_CAP_FRAME_PACING, throttle animation with a timer.
- */
-YASL_API void yasl_surface_schedule_redraw(struct yasl_surface *s);
-/* Present exactly the target supplied to the current draw callback, at most
- * once. Targets expire when that callback returns or the surface is destroyed.
- * damage is required: n must be -1 or 0..YASL_DAMAGE_MAX. Rectangles must have
- * nonnegative extents; they are clipped to the target. Invalid input returns
- * false without consuming the frame. See yasl/native.h for native rendering. */
-/**
- * Submit the current draw target at most once.
- * @param s Surface currently being drawn.
- * @param fb Exact target from the current draw callback, including its generation.
- * @param damage Required damage hint: n is -1 for all pixels or 0..YASL_DAMAGE_MAX.
- * @return true if accepted; false for invalid, stale, already presented, or failed targets.
- * Rectangles must have nonnegative extents and are clipped to the target. Invalid
- * input does not consume the frame. All pixels must be initialized even with
- * partial damage. The backend may upload all pixels. Success records submission,
- * not confirmed scanout. The target expires when draw returns or s is destroyed.
- */
-YASL_API bool yasl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer *fb,
- const struct yasl_damage_list *damage);
-/**
- * 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);
-/**
- * Decode the next local file path from a YASL_EVENT_DROP payload.
- * @param cursor Required in/out position in the NUL-terminated list. Start it
- * at event.text.data; a NULL *cursor returns zero.
- * @param out Output for the NUL-terminated path, or NULL when cap is zero.
- * @param cap Size of out in bytes.
- * @return Path length in bytes, excluding the NUL, or zero when no paths remain.
- * When the result is less than cap, out holds the path and *cursor moves past
- * it. Otherwise out and *cursor are unchanged; call again with a buffer of at
- * least the result plus one.
- * Accepts file:///path, file:/path, and file://host/path when host is
- * localhost or this machine's name. Percent escapes decode to raw bytes, and
- * a '?' or '#' ends the path. Skips blank lines, comments, other schemes,
- * other hosts, and lines with a malformed escape or an escaped NUL. May be
- * called from any thread.
- */
-YASL_API size_t yasl_drop_next_path(const char **cursor, char *out, size_t cap);
-/**
- * Copy the last frame presented from the surface's CPU target.
- * @param s Surface.
- * @param out Output for size->x * size->y premultiplied ARGB8888 pixels with
- * tightly packed rows, or NULL when cap is zero.
- * @param cap Capacity of out in pixels.
- * @param size Required output: the frame extent in device pixels, or zero when
- * no frame is available.
- * @return true if copied. false leaves out unchanged; when *size is nonzero,
- * out was too small, so allocate size->x * size->y pixels and call again.
- * A frame is available from a successful yasl_surface_present() until the
- * next draw callback starts, and again once that draw presents. After a draw
- * that does not present or a resize that replaces the target, no frame may be
- * available; native rendering never has one. Call outside draw callbacks. This copies YASL's frame, not
- * the composited screen: decorations, other windows, and color conversion are
- * not included.
- */
-YASL_API bool yasl_surface_read_pixels(struct yasl_surface *s, uint32_t *out, size_t cap,
- struct yasl_vector2i *size);
-/**
- * Select absolute or relative (locked) pointer input for a surface.
- * @param s Surface.
- * @param mode YASL_POINTER_NORMAL or YASL_POINTER_RELATIVE.
- * @return true if the mode is supported; false leaves the current mode.
- * RELATIVE hides the cursor and locks it while the surface is focused;
- * POINTER_MOTION then carries unbounded delta. Returning to NORMAL restores
- * the cursor selected with yasl_surface_set_cursor(). RELATIVE is supported on
- * Wayland compositors with the relative-pointer and pointer-constraints
- * protocols; X11 and Cocoa return false.
- */
-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.
- * @param s Surface, or NULL.
- * @return Geometry matching configure callbacks; NULL gives zero size and unit scale.
- */
-YASL_API struct yasl_geometry yasl_surface_geometry(const struct yasl_surface *s);
-/**
- * Read current window state.
- * @param s Surface, or NULL.
- * @return A bitmask of yasl_surface_state values, or zero for NULL.
- * Flags are reported state, not requests; unsupported states are absent.
- * Flags may coexist. Windowed and floating have no separate flags. Suspension
- * does not imply minimization, and no minimized flag is reported.
- */
-YASL_API uint32_t yasl_surface_state(const struct yasl_surface *s);
-/* Timing uses monotonic nanoseconds. Check source before treating timestamps
- * as presentation confirmation. refresh/next_present are estimates. Without
- * YASL_CAP_FRAME_PACING, redraws run on flush without display synchronization.
- * Tearing may bypass pacing even when the capability is present. */
-/**
- * Read frame timing estimates and their provenance.
- * @param s Surface, or NULL.
- * @return Current timing, or a zero-initialized result for NULL.
- * Timestamps use monotonic nanoseconds. Inspect source before treating a timestamp
- * as confirmation of presentation. Refresh and next-present values are estimates.
- */
-YASL_API struct yasl_timing yasl_surface_timing(const struct yasl_surface *s);
-/**
- * Get a nondecreasing animation timestamp aligned to estimated refresh.
- * @param s Surface, or NULL.
- * @param now Current monotonic nanoseconds, usually from yasl_loop_now_ns().
- * @return Animation timestamp, or zero for NULL. Before timing is known, returns now.
- * Use this to advance animations; it is not presentation feedback.
- */
-YASL_API uint64_t yasl_surface_frame_time_ns(struct yasl_surface *s, uint64_t now);
-/* Set the mouse and tablet cursor for this surface, including future entries.
- * YASL_CURSOR_HIDDEN stays hidden until another cursor is selected. */
-/**
- * Select the surface's system mouse and tablet cursor.
- * @param s Surface.
- * @param cursor Cursor shape; YASL_CURSOR_HIDDEN hides the cursor without disabling input.
- * The choice persists across motion and re-entry until another shape is selected.
- */
-YASL_API void yasl_surface_set_cursor(struct yasl_surface *s, enum yasl_cursor cursor);
-/**
- * Set a backend window background hint.
- * @param s Surface.
- * @param bg Packed 0xAARRGGBB color; backends may ignore alpha or the entire hint.
- * Does not initialize framebuffer pixels or replace drawing.
- */
-YASL_API void yasl_surface_set_background_color(struct yasl_surface *s, uint32_t bg);
-
-/* IME Support: preedit is borrowed until the next dispatch or destruction. */
-/**
- * Read the current uncommitted UTF-8 composition text.
- * @param s Surface, or NULL.
- * @return Borrowed NUL-terminated text, or NULL if absent/unsupported.
- * Copy to retain across the next dispatch or surface destruction. Composition
- * changes can schedule a redraw. Insert committed YASL_EVENT_TEXT into documents,
- * not preedit text.
- */
-YASL_API const char *yasl_surface_ime_preedit(const struct yasl_surface *s);
-/**
- * Read the cursor/selection range in the preedit string.
- * @param s Surface.
- * @param begin Required output UTF-8 byte offset for the range start.
- * @param end Required output UTF-8 byte offset for the range end.
- * @return true if available; false without changing outputs otherwise.
- * Currently available on Wayland; Cocoa preedit text has no range result.
- */
-YASL_API bool yasl_surface_ime_preedit_cursor(const struct yasl_surface *s, int *begin, int *end);
-/**
- * Place the composition candidate window near the application caret.
- * @param s Surface.
- * @param caret Caret rectangle relative to the surface, in device pixels.
- * Update after caret motion or scale changes. Unsupported backends ignore it.
- */
-YASL_API void yasl_surface_set_ime_caret(struct yasl_surface *s, struct yasl_rect2i caret);
-
-/* Client-Side Decorations (CSD) Actions */
-/**
- * Ask the window system to begin an interactive move.
- * @param s Toplevel surface, normally during handling of a pointer press.
- * @return true if the request was issued; false if unsupported or not permitted.
- * A recent input serial may be required. Success does not confirm a final position.
- */
-YASL_API bool yasl_surface_start_interactive_move(struct yasl_surface *s);
-/**
- * Ask the window system to begin an interactive resize.
- * @param s Toplevel surface, normally during handling of a pointer press.
- * @param edge One nonzero yasl_resize_edge enumerator.
- * @return true if issued; false for an invalid edge, missing support, or rejected request.
- */
-YASL_API bool yasl_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_resize_edge edge);
-/**
- * Ask the window system to display its window management menu.
- * @param s Toplevel surface.
- * @param pos Surface-relative position in device pixels.
- * @return true if issued; false if unsupported or not currently permitted.
- */
-YASL_API bool yasl_surface_show_window_menu(struct yasl_surface *s, struct yasl_vector2i pos);
-
-/* Drag Support */
-/**
- * Attach a toplevel surface to the current surface drag.
- * @param s Surface to carry; check YASL_CAP_DRAG_CARRY first.
- * @param offset Device-pixel offset of the pointer within the carried surface.
- * @return true if accepted; false if unsupported or no compatible drag is active.
- */
-YASL_API bool yasl_surface_drag_carry(struct yasl_surface *s, struct yasl_vector2i offset);
-/**
- * Place a toplevel surface relative to the current pointer.
- * @param s Surface; check YASL_CAP_PLACE_WINDOW first.
- * @param at Device-pixel position within the surface to place under the pointer.
- * @return true if issued; false if unsupported or unavailable.
- */
-YASL_API bool yasl_surface_place_under_pointer(struct yasl_surface *s, struct yasl_vector2i at);
-
+/** Last error on this thread; success does not clear it. */
+YASL_API enum yasl_error yasl_get_error(const char **description);
+YASL_API int yasl_get_native_error(void);
+/** Only before the first surface is created. */
+YASL_API bool yasl_set_app_id(const char *app_id);
+YASL_API bool yasl_set_backend(enum yasl_backend backend);
+/** Flags zero creates a surface for your own Vulkan or Metal renderer. */
+YASL_API yasl_surface *yasl_surface_create(const char *title, int width, int height, unsigned flags);
+/** Also destroys its popups. */
+YASL_API void yasl_surface_destroy(yasl_surface *surface);
+/** Destroys all surfaces. Release your GPU objects first. */
+YASL_API void yasl_shutdown(void);
+/** 1 event, 0 none (timeout or wake), -1 failure. timeout_ms zero polls, negative
+ * waits forever. Without an event, out->type is NONE. */
+YASL_API int yasl_wait_event(yasl_event *out, int timeout_ms);
+/** Makes a waiting yasl_wait_event return. Thread-safe. */
+YASL_API void yasl_wake(void);
+YASL_API uint64_t yasl_time_ns(void);
+YASL_API enum yasl_backend yasl_surface_backend(const yasl_surface *surface);
+YASL_API unsigned yasl_surface_features(const yasl_surface *surface);
+YASL_API void yasl_surface_get_size(const yasl_surface *surface, int *width, int *height);
+YASL_API void yasl_surface_get_framebuffer_size(const yasl_surface *surface, int *width, int *height);
+YASL_API double yasl_surface_get_scale(const yasl_surface *surface);
+YASL_API unsigned yasl_surface_state(const yasl_surface *surface);
+YASL_API void *yasl_surface_userdata(const yasl_surface *surface);
+YASL_API void yasl_surface_set_userdata(yasl_surface *surface, void *userdata);
+YASL_API bool yasl_surface_set_title(yasl_surface *surface, const char *title);
+/** Requests; the result arrives as a WINDOW event. */
+YASL_API bool yasl_surface_request_size(yasl_surface *surface, int width, int height);
+YASL_API bool yasl_surface_request_fullscreen(yasl_surface *surface, bool enabled);
+YASL_API bool yasl_surface_request_maximized(yasl_surface *surface, bool enabled);
+YASL_API bool yasl_surface_request_minimize(yasl_surface *surface);
+YASL_API bool yasl_surface_set_cursor(yasl_surface *surface, enum yasl_cursor cursor);
+YASL_API bool yasl_surface_set_pointer_mode(yasl_surface *surface, enum yasl_pointer_mode mode);
+/** Draws during native modal loops such as a live resize. The callback may render
+ * but must not wait, create or destroy surfaces, or shut down. */
+YASL_API void yasl_surface_set_refresh_callback(yasl_surface *surface, void (*refresh)(yasl_surface *,void *), void *userdata);
+YASL_API int yasl_double_click_ms(void);
+YASL_API bool yasl_clipboard_set(enum yasl_selection selection, const char *text);
+/** Returns a request ID; the text arrives as a CLIPBOARD event. Zero on failure. */
+YASL_API uint64_t yasl_clipboard_request(yasl_surface *target, enum yasl_selection selection);
+/** IME support for a text field. */
+YASL_API bool yasl_surface_set_text_input(yasl_surface *surface, bool active, enum yasl_text_purpose purpose);
+/** UTF-8; selection offsets are bytes. */
+YASL_API bool yasl_surface_set_surrounding_text(yasl_surface *surface, const char *text, size_t length,
+ size_t selection_begin, size_t selection_end, uint64_t revision);
+YASL_API bool yasl_surface_set_ime_caret(yasl_surface *surface, double x, double y, double width, double height);
+/** Anchor picks a point on the x/y/anchor rectangle of the parent; gravity is the
+ * direction the popup grows. Functions taking a trigger need a recent press event. */
+YASL_API yasl_surface *yasl_popup_create(yasl_surface *parent, int width, int height,
+ double x, double y, double anchor_width, double anchor_height, enum yasl_popup_edge anchor,
+ enum yasl_popup_edge gravity, unsigned constraints, const yasl_event *trigger);
+YASL_API bool yasl_popup_reposition(yasl_surface *popup, int width, int height,
+ double x, double y, double anchor_width, double anchor_height, enum yasl_popup_edge anchor,
+ enum yasl_popup_edge gravity, unsigned constraints);
+YASL_API bool yasl_surface_start_interactive_move(yasl_surface *surface, const yasl_event *trigger);
+YASL_API bool yasl_surface_start_interactive_resize(yasl_surface *surface, enum yasl_resize_edge edge, const yasl_event *trigger);
+YASL_API bool yasl_surface_show_window_menu(yasl_surface *surface, double x, double y, const yasl_event *trigger);
+YASL_API bool yasl_drag_start(yasl_surface *origin, const yasl_event *trigger,
+ const uint32_t *pixels, int width, int height, int hotspot_x, int hotspot_y);
+YASL_API void yasl_drag_cancel(void);
+YASL_API bool yasl_surface_drag_carry(yasl_surface *surface, double x, double y);
+YASL_API bool yasl_surface_place_under_pointer(yasl_surface *surface, double x, double y);
+YASL_API size_t yasl_drop_next_path(const char **cursor, char *out, size_t capacity);
#ifdef __cplusplus
}
#endif
-
-#endif /* YASL_H */
+#endif