diff options
Diffstat (limited to 'src/common/types.h')
| -rw-r--r-- | src/common/types.h | 1101 |
1 files changed, 1101 insertions, 0 deletions
diff --git a/src/common/types.h b/src/common/types.h new file mode 100644 index 0000000..91f8a47 --- /dev/null +++ b/src/common/types.h @@ -0,0 +1,1101 @@ +/** + * @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_PRIVATE_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. + */ +#ifndef YASL_PRIVATE_H +#define YASL_PRIVATE_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <limits.h> +#include <float.h> +#include <math.h> + +#include "common/private_timing.h" +#include "yasl/yasl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct yasl_private_display; +struct yasl_surface; +struct yasl_private_loop; + +/* Geometry */ +/** A two-dimensional integer size, position, or offset; units depend on the caller. */ +struct yasl_private_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_private_vector2d { + /** Horizontal component. */ + double x; + /** Vertical component. */ + double y; +}; + +/** Integer rectangle; origin is upper left and extents must be nonnegative. */ +struct yasl_private_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_PRIVATE_SCALE_UNIT 120 +/** Backend minimum logical dimension used when constraining toplevel sizes. */ +#define YASL_PRIVATE_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_private_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_PRIVATE_SCALE_UNIT) ? logical : (logical * ((double)scale_120 / YASL_PRIVATE_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_private_scale_to_logical(int device, uint32_t scale_120) +{ + if (!scale_120) return 0; + if (scale_120 == YASL_PRIVATE_SCALE_UNIT) return device; + int64_t px = (int64_t)device * YASL_PRIVATE_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_private_display_caps(). */ +enum yasl_private_display_cap : uint32_t { + YASL_PRIVATE_CAP_POPUPS = 1 << 0, /**< Popup creation and placement. */ + YASL_PRIVATE_CAP_DRAG = 1 << 1, /**< Surface-drag source and target support. */ + YASL_PRIVATE_CAP_DRAG_CARRY = 1 << 2, /**< Carry a toplevel during a drag. */ + YASL_PRIVATE_CAP_PLACE_WINDOW = 1 << 3, /**< Place a window relative to the pointer. */ + YASL_PRIVATE_CAP_PRIMARY_SELECTION = 1 << 4, /**< Separate primary selection. */ + YASL_PRIVATE_CAP_CSD = 1 << 5, /**< Backend advertises client decoration support; check each action result. */ + YASL_PRIVATE_CAP_NATIVE_GRAPHICS = 1 << 6, /**< Application-managed native rendering. */ + YASL_PRIVATE_CAP_FRAME_PACING = 1 << 7, /**< Compositor/display-driven draws. */ + /* Backend/protocol supports tablet axes, independent of attached hardware. */ + YASL_PRIVATE_CAP_TABLET = 1 << 8, + YASL_PRIVATE_CAP_TEXT_INPUT = 1 << 11, /**< Tablet protocol support, independent of attached hardware. */ +}; + +/** Independent selections. An unsupported selection never aliases the clipboard. */ +enum yasl_private_selection : uint8_t { + YASL_PRIVATE_CLIPBOARD, /**< Explicit copy/paste selection. */ + YASL_PRIVATE_PRIMARY, /**< Independent primary selection, if supported. */ +}; + +/** Reported surface state flags; absent flags may also mean unsupported state. */ +enum yasl_private_surface_state : uint32_t { + YASL_PRIVATE_STATE_FULLSCREEN = 1 << 0, /**< Fullscreen. */ + YASL_PRIVATE_STATE_MAXIMIZED = 1 << 1, /**< Maximized. */ + YASL_PRIVATE_STATE_ACTIVATED = 1 << 2, /**< Active window. */ + YASL_PRIVATE_STATE_SUSPENDED = 1 << 3, /**< Compositor reports suspension. */ + YASL_PRIVATE_STATE_CSD = 1 << 4, /**< Backend reports client-side decorations. */ + YASL_PRIVATE_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_private_cursor { + YASL_PRIVATE_CURSOR_ARROW, /**< Default arrow. */ + YASL_PRIVATE_CURSOR_TEXT, /**< Text insertion. */ + YASL_PRIVATE_CURSOR_LINK, /**< Link/pointer hand. */ + YASL_PRIVATE_CURSOR_CROSSHAIR, /**< Crosshair. */ + YASL_PRIVATE_CURSOR_MOVE, /**< Move in any direction. */ + YASL_PRIVATE_CURSOR_RESIZE_NWSE, /**< Northwest/southeast resize. */ + YASL_PRIVATE_CURSOR_RESIZE_NESW, /**< Northeast/southwest resize. */ + YASL_PRIVATE_CURSOR_RESIZE_EW, /**< Horizontal resize. */ + YASL_PRIVATE_CURSOR_RESIZE_NS, /**< Vertical resize. */ + YASL_PRIVATE_CURSOR_HIDDEN, /**< Hidden system cursor; pointer input continues. */ + YASL_PRIVATE_CURSOR_NONE = YASL_PRIVATE_CURSOR_HIDDEN, /**< Compatibility alias for HIDDEN. */ +}; + +/** Valid interactive resize edges; combinations are restricted to the named values. */ +enum yasl_private_resize_edge : uint32_t { + YASL_PRIVATE_EDGE_NONE = 0, /**< No resize edge; rejected by interactive resize. */ + YASL_PRIVATE_EDGE_TOP = 1, /**< Top edge. */ + YASL_PRIVATE_EDGE_BOTTOM = 2, /**< Bottom edge. */ + YASL_PRIVATE_EDGE_LEFT = 4, /**< Left edge. */ + YASL_PRIVATE_EDGE_TOP_LEFT = 5, /**< Top-left corner. */ + YASL_PRIVATE_EDGE_BOTTOM_LEFT = 6, /**< Bottom-left corner. */ + YASL_PRIVATE_EDGE_RIGHT = 8, /**< Right edge. */ + YASL_PRIVATE_EDGE_TOP_RIGHT = 9, /**< Top-right corner. */ + YASL_PRIVATE_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_PRIVATE_DAMAGE_MAX 64 + +/** Damage hints for one presentation; every target still needs complete valid pixels. */ +struct yasl_private_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_private_rect2i bounds; + /** First n rectangles, in device pixels; ignored for n == -1. */ + struct yasl_private_rect2i rects[YASL_PRIVATE_DAMAGE_MAX]; +}; + +/** Borrowed draw target, valid only for the current draw callback. Never free pixels. */ +struct yasl_private_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_private_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_private_frame { + /** Surface being drawn. */ + struct yasl_surface *surface; + /** Target to initialize and present before returning. */ + struct yasl_private_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_private_pacing_mode { + YASL_PRIVATE_PACING_ON_DEMAND = 0, /**< Draw only when invalidated or exposed. */ + YASL_PRIVATE_PACING_CONTINUOUS, /**< Draw continuously using native pacing or a timer. */ +} yasl_private_pacing_mode; + +/* Drag and Drop */ +/** Target notifications for YASL surface drags, separate from external file drops. */ +enum yasl_private_drag_event { + YASL_PRIVATE_DRAG_OVER, /**< Surface drag entered or moved over the target. */ + YASL_PRIVATE_DRAG_LEAVE, /**< Surface drag left the target. */ + YASL_PRIVATE_DRAG_DROP, /**< Surface drag dropped on the target. */ +}; + +/** External text/file drag hover notifications; completed data arrives through input. */ +enum yasl_private_drop_event { + YASL_PRIVATE_DROP_OVER, /**< External data drag entered or moved over the target. */ + YASL_PRIVATE_DROP_LEAVE, /**< External data drag left the target. */ +}; + +/** Source-side drag completion; DROPPED does not prove application-level acceptance. */ +enum yasl_private_drag_end { + YASL_PRIVATE_DRAG_DROPPED, /**< Drag ended in a drop; not an application acceptance receipt. */ + YASL_PRIVATE_DRAG_CANCELLED, /**< Drag canceled, including display close. */ +}; + +/** Copied drag icon in tightly packed premultiplied 0xAARRGGBB device pixels. */ +struct yasl_private_drag_image { + /** Copied pixel array; required when an image is supplied. */ + const uint32_t *pixels; + /** Positive width and height in device pixels. */ + struct yasl_private_vector2i size; + /** Pointer position within the image, in device pixels. */ + struct yasl_private_vector2i hotspot; +}; + +/** Copied drag completion listener; userdata remains owned by the application. */ +struct yasl_private_drag_listener { + /** Called exactly once after a successful start, possibly synchronously on cancel/close. */ + void (*end)(void *ud, enum yasl_private_drag_end how); +}; + +/** Configured device-pixel content size and the corresponding display scale. */ +struct yasl_private_geometry { + /** Current content extent in device pixels. */ + struct yasl_private_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_private_key_action { + YASL_PRIVATE_KEY_PRESS, /**< Key pressed. */ + YASL_PRIVATE_KEY_RELEASE, /**< Key released. */ + YASL_PRIVATE_KEY_REPEAT, /**< Key autorepeat. */ +}; + +/** Modifier bitmask. SUPER is Command on macOS. */ +enum yasl_private_mod : uint32_t { + YASL_PRIVATE_MOD_SHIFT = 1 << 0, /**< Shift modifier. */ + YASL_PRIVATE_MOD_ALT = 1 << 1, /**< Alt/Option modifier. */ + YASL_PRIVATE_MOD_CTRL = 1 << 2, /**< Control modifier. */ + YASL_PRIVATE_MOD_SUPER = 1 << 3, /**< Super/Command modifier. */ + YASL_PRIVATE_MOD_CAPS = 1 << 4, /**< Caps Lock modifier. */ +}; + +/** Pointer source class; capability support does not imply an attached device. */ +enum yasl_private_pointer_device { + YASL_PRIVATE_PTR_DEV_MOUSE, /**< Mouse or trackpad pointer. */ + YASL_PRIVATE_PTR_DEV_TOUCH, /**< Touch translated into pointer input. */ + YASL_PRIVATE_PTR_DEV_PEN, /**< Tablet stylus. */ + YASL_PRIVATE_PTR_DEV_ERASER, /**< Tablet eraser tool. */ +}; + +/** Pointer button; meaningful only for POINTER_DOWN and POINTER_UP. */ +enum yasl_private_pointer_button { + YASL_PRIVATE_BUTTON_PRIMARY = 0, /**< Left button, pen tip, or touch contact. */ + YASL_PRIVATE_BUTTON_MIDDLE = 1, /**< Middle button / wheel click. */ + YASL_PRIVATE_BUTTON_SECONDARY = 2, /**< Right button or pen barrel button. */ + YASL_PRIVATE_BUTTON_BACK = 3, /**< Side "back" button. */ + YASL_PRIVATE_BUTTON_FORWARD = 4, /**< Side "forward" button. */ +}; + +/** Bit for a yasl_private_pointer_button in yasl_private_pointer_event.buttons. */ +#define YASL_PRIVATE_BUTTON_BIT(button) (1u << (button)) + +/** Pointer capture mode for a surface. */ +enum yasl_private_pointer_mode { + YASL_PRIVATE_POINTER_NORMAL = 0, /**< Absolute positions; cursor per yasl_private_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_PRIVATE_POINTER_RELATIVE, +}; + +/** Normalized tablet axes; zero for unavailable axes and non-tablet devices. */ +struct yasl_private_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_private_event_type { + YASL_PRIVATE_EVENT_NONE = 0, + + /* Input: produced by backends, returned by yasl_private_surface_poll_event(). */ + YASL_PRIVATE_EVENT_KEY, /**< .key */ + YASL_PRIVATE_EVENT_TEXT, /**< .text — committed UTF-8; insert this, not key codepoints. */ + YASL_PRIVATE_EVENT_POINTER_DOWN, /**< .pointer — button/tip pressed; button valid. */ + YASL_PRIVATE_EVENT_POINTER_UP, /**< .pointer — button/tip released; button valid. */ + YASL_PRIVATE_EVENT_POINTER_MOTION, /**< .pointer — position, relative motion, or pen axes changed. */ + YASL_PRIVATE_EVENT_POINTER_SCROLL, /**< .pointer — scroll valid. */ + YASL_PRIVATE_EVENT_POINTER_LEAVE, /**< .pointer — last known pos/device; cancel hover state. */ + YASL_PRIVATE_EVENT_FOCUS, /**< .focus — keyboard focus changed; cancel held state on loss. */ + YASL_PRIVATE_EVENT_PASTE, /**< .text — UTF-8 from yasl_private_display_paste(). */ + YASL_PRIVATE_EVENT_DROP, /**< .text — dropped text/uri-list: CRLF-separated file URLs, not paths. */ + YASL_PRIVATE_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_PRIVATE_EVENT_WINDOW_RESIZE, /**< .resize — size and/or scale changed; reallocate and redraw. */ + YASL_PRIVATE_EVENT_WINDOW_CLOSE, /**< No payload. User asked to close the window. */ + YASL_PRIVATE_EVENT_USER, /**< .user — posted application message. */ + YASL_PRIVATE_EVENT_WINDOW_STATE, /**< .state — reported state changed. */ + YASL_PRIVATE_EVENT_DRAG, /**< .drag — surface-drag target notification. */ + YASL_PRIVATE_EVENT_DROP_HOVER, /**< .drop — external drag hover/leave. */ + YASL_PRIVATE_EVENT_COMPOSITION, /**< .composition — preedit snapshot, including ending. */ + YASL_PRIVATE_EVENT_DISPLAY_QUIT, /**< No payload; system requested application quit. */ + YASL_PRIVATE_EVENT_DISPLAY_REOPEN, /**< No payload; system requested activation. */ + YASL_PRIVATE_EVENT_DISPLAY_LOST, + YASL_PRIVATE_EVENT_PEN, + YASL_PRIVATE_EVENT_TEXT_EDIT, + YASL_PRIVATE_EVENT_REFRESH, /**< 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_PRIVATE_EVENT_TEXT into documents instead. */ +struct yasl_private_key_event { + /** Portable physical key; YASL_KEY_UNKNOWN when unmapped. */ + enum yasl_key key; + /** Press, release, or autorepeat. */ + enum yasl_key_action action; + /** yasl_private_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_private_pointer_event { + struct yasl_private_vector2d pixel_scroll; + unsigned scroll_valid, scroll_source, scroll_phase; + bool scroll_momentum; + double precise_x, precise_y; + bool precise_position; + /** Surface-relative device-pixel position. Frozen while YASL_PRIVATE_POINTER_RELATIVE is locked. */ + struct yasl_private_vector2i pos; + /** MOTION: device-pixel movement since the previous sample on this surface. + * Unbounded under YASL_PRIVATE_POINTER_RELATIVE; zero after enter, leave, or reset. */ + struct yasl_private_vector2d delta; + /** SCROLL: fractional line offsets after system preferences; positive right/down. */ + struct yasl_private_vector2d scroll; + /** DOWN/UP: which button changed. */ + enum yasl_private_pointer_button button; + /** YASL_PRIVATE_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_private_pointer_device device; + /** yasl_private_mod bitmask at this event. */ + uint32_t mods; + /** Current tablet axes, including on pressure-only motion; missing axes are zero. */ + struct yasl_private_pointer_pen pen; +}; + +/** Borrowed NUL-terminated UTF-8, shared by TEXT, PASTE and DROP. */ +struct yasl_private_text_event { + /** Borrowed NUL-terminated bytes; see yasl_private_surface_poll_event() for lifetime. */ + const char *data; + /** Length in bytes excluding the terminating NUL. */ + size_t len; +}; + +/** Clipboard transfer outcome. */ +enum yasl_private_transfer_status { + YASL_PRIVATE_TRANSFER_OK = 0, /**< Text received successfully, including empty text. */ + YASL_PRIVATE_TRANSFER_UNAVAILABLE, /**< No text selection is available. */ + YASL_PRIVATE_TRANSFER_FAILED, /**< Transfer or decoding failed. */ +}; + +/** Clipboard completion; data/len alias the legacy text payload. */ +struct yasl_private_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_private_transfer_status status; /**< Completion outcome. */ +}; + +/** Borrowed UTF-8 preedit snapshot, valid until the next successful display poll. */ +struct yasl_private_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. */ + uint64_t revision, generation; +}; + +/** Reported window-state change. */ +struct yasl_private_state_event { uint32_t flags; /**< Current YASL_PRIVATE_STATE_* flags. */ }; +/** Surface-drag target notification; position is in device pixels. */ +struct yasl_private_drag_target_event { + enum yasl_private_drag_event action; /**< Hover, leave, or drop. */ + struct yasl_private_vector2i pos; /**< Surface-relative device pixels. */ +}; +/** External drag hover notification; position is in device pixels. */ +struct yasl_private_drop_hover_event { + enum yasl_private_drop_event action; /**< Hover or leave. */ + struct yasl_private_vector2i pos; /**< Surface-relative device pixels. */ +}; + +/** Keyboard focus transition. */ +struct yasl_private_focus_event { + /** true on focus gain, false on loss. */ + bool focused; +}; + +/** New configured geometry for a surface. */ +struct yasl_private_resize_event { + /** Content size in device pixels and display scale. */ + struct yasl_private_geometry geometry; + /** true when scale_120 differs from the previous resize of this surface. */ + bool scale_changed; +}; + +/** Application message posted with yasl_private_post_event(). */ +struct yasl_private_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_private_surface_flags { YASL_PRIVATE_SURFACE_CPU = 1u, YASL_PRIVATE_SURFACE_HIDDEN = 2u, YASL_PRIVATE_SURFACE_UNDECORATED = 4u, YASL_PRIVATE_SURFACE_FIXED_SIZE = 8u }; +enum yasl_private_pen_action { YASL_PRIVATE_PEN_ENTER, YASL_PRIVATE_PEN_LEAVE, YASL_PRIVATE_PEN_MOVE, YASL_PRIVATE_PEN_DOWN, YASL_PRIVATE_PEN_UP, YASL_PRIVATE_PEN_BUTTON, YASL_PRIVATE_PEN_CANCEL }; +enum yasl_private_pen_axis { YASL_PRIVATE_PEN_PRESSURE = 1u, YASL_PRIVATE_PEN_TILT = 2u, YASL_PRIVATE_PEN_ROTATION = 4u, YASL_PRIVATE_PEN_DISTANCE = 8u, YASL_PRIVATE_PEN_TANGENTIAL = 16u, YASL_PRIVATE_PEN_WHEEL = 32u }; +enum yasl_private_presenter { YASL_PRIVATE_PRESENTER_NONE, YASL_PRIVATE_PRESENTER_CPU, YASL_PRIVATE_PRESENTER_GL, YASL_PRIVATE_PRESENTER_VULKAN, YASL_PRIVATE_PRESENTER_METAL }; +struct yasl_private_pen_sample { + uint64_t device_id, tool_id; + double x, y, pressure, tilt_x, tilt_y, rotation, distance, tangential, wheel_degrees; + uint32_t axes_valid, axes_changed, buttons, changed_button; + bool in_contact; + unsigned tool, action; +}; +struct yasl_private_event { + /** Selects the valid union member. */ + enum yasl_private_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_private_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_private_pen_sample pen; + struct { const char *data; size_t len; uint64_t revision, generation; size_t begin, end; } text_edit; + struct yasl_private_key_event key; /**< KEY */ + struct yasl_private_pointer_event pointer; /**< POINTER_* */ + struct yasl_private_text_event text; /**< TEXT, legacy PASTE, DROP */ + struct yasl_private_paste_event paste; /**< PASTE */ + struct yasl_private_composition_event composition; /**< COMPOSITION */ + struct yasl_private_state_event state; /**< WINDOW_STATE */ + struct yasl_private_drag_target_event drag; /**< DRAG */ + struct yasl_private_drop_hover_event drop; /**< DROP_HOVER */ + struct yasl_private_focus_event focus; /**< FOCUS */ + struct yasl_private_resize_event resize; /**< WINDOW_RESIZE */ + struct yasl_private_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_private_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_private_window_spec.cbs or by +yasl_private_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_private_window_cbs { + /** Initialize the entire target and optionally present. Requested through schedule_redraw/flush. */ + void (*draw)(struct yasl_surface *s, struct yasl_private_frame *frame, void *ud); + /** Configured size/scale changed; reallocate application content and request a redraw. */ + void (*configure)(struct yasl_surface *s, struct yasl_private_geometry geometry, void *ud); + /** Window/popup close request; application is responsible for destruction. */ + void (*close)(struct yasl_surface *s, void *ud); + /** Reported yasl_private_surface_state bitmask changed; matches yasl_private_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_private_drag_event ev, + struct yasl_private_vector2i pos, void *ud); + /** External data-drag hover or leave; pos is in device pixels. */ + void (*drop)(struct yasl_surface *s, enum yasl_private_drop_event ev, + struct yasl_private_vector2i pos, void *ud); +}; + +/* Display Lifecycle */ +/** Runtime backend choice. AUTO selects a native backend and allows fallback. */ +enum yasl_private_backend { + YASL_PRIVATE_BACKEND_AUTO = 0, /**< Choose native backend with fallback. */ + YASL_PRIVATE_BACKEND_WAYLAND, /**< Require Wayland. */ + YASL_PRIVATE_BACKEND_X11, /**< Require X11. */ + YASL_PRIVATE_BACKEND_COCOA, /**< Require Cocoa. */ +}; + +/** Display options. Zero-initialize for automatic backend selection. */ +struct yasl_private_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_private_display_cbs *cbs; + /** Borrowed display callback userdata. */ + void *ud; + + /** Zero/AUTO chooses native backend; explicit choices never fall back. */ + enum yasl_private_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_private_display_close() after destroying its surfaces. + */ +struct yasl_private_display *yasl_private_display_open(struct yasl_private_loop *loop, + const struct yasl_private_display_spec *spec); +/** + * Read the selected backend. + * @param d Display, or NULL. + * @return The actual backend, or YASL_PRIVATE_BACKEND_AUTO for NULL. + */ +enum yasl_private_backend yasl_private_display_backend(const struct yasl_private_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. + */ +void yasl_private_display_close(struct yasl_private_display *d); +/** + * Query currently available optional features. + * @param d Display, or NULL. + * @return A bitmask of yasl_private_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. + */ +uint32_t yasl_private_display_caps(const struct yasl_private_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_private_display_flush() after updating application state. Do not dispatch recursively. + */ +int yasl_private_display_dispatch(struct yasl_private_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. + */ +void yasl_private_display_flush(struct yasl_private_display *d); +/** + * Read the latest modifier state known to the backend. + * @param d Display, or NULL. + * @return A bitmask of yasl_private_mod values, or zero for NULL. + * For an individual event use its own mods field instead. + */ +int yasl_private_display_modifiers(const struct yasl_private_display *d); +/** Double-click interval used when the system reports none. */ +#define YASL_PRIVATE_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_PRIVATE_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. + */ +int yasl_private_display_double_click_ms(const struct yasl_private_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_PRIVATE_CLIPBOARD or YASL_PRIVATE_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. + */ +void yasl_private_display_copy(struct yasl_private_display *d, enum yasl_private_selection sel, const char *text); +/** + * Request text delivery to a particular surface. + * @param d Display that owns target. + * @param sel YASL_PRIVATE_CLIPBOARD or YASL_PRIVATE_PRIMARY. + * @param target Destination surface; NULL or a surface on another display does nothing. + * Results arrive as YASL_PRIVATE_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. + */ +void yasl_private_display_paste(struct yasl_private_display *d, enum yasl_private_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. + */ +bool yasl_private_display_drag_start(struct yasl_private_display *d, struct yasl_surface *origin, + const struct yasl_private_drag_image *image, + const struct yasl_private_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. + */ +void yasl_private_display_drag_cancel(struct yasl_private_display *d); + +/* Surface Lifecycle */ +/** Toplevel options. Zero-initialize, then supply a positive logical-pixel size. */ +struct yasl_private_window_spec { + unsigned flags; + bool external_gpu; + /** Copied UTF-8 title; NULL uses backend defaults. */ + const char *title; + /** Requested logical-pixel width and height; both must be positive. */ + union { + struct yasl_private_vector2i size_logical; /**< Requested logical-pixel extent. */ + struct yasl_private_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_private_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_private_popup_spec { + unsigned anchor_edges, gravity, constraints; + bool positioner_explicit; + /** Full popup framebuffer extent in device pixels, including transparent margins. */ + struct yasl_private_vector2i size; + /** Rectangle in parent framebuffer coordinates, in device pixels. */ + struct yasl_private_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_private_vector2i content_offset; + /** Content extent; zero per axis extends to the corresponding size edge. */ + struct yasl_private_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_private_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_private_run(), the runner installs its own callbacks instead; + * use yasl_private_app_desc.event and yasl_private_app_desc.frame for application notifications. + */ +struct yasl_surface *yasl_private_surface_create_toplevel(struct yasl_private_display *d, + const struct yasl_private_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_private_popup_spec. + */ +struct yasl_surface *yasl_private_surface_create_popup(struct yasl_surface *parent, + const struct yasl_private_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. + */ +bool yasl_private_surface_popup_reposition(struct yasl_surface *popup, + const struct yasl_private_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. + */ +void yasl_private_surface_destroy(struct yasl_surface *s); +/** + * Get the display that owns a surface. + * @param s Surface, or NULL. + * @return A borrowed display, or NULL. + */ +struct yasl_private_display *yasl_private_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_private_surface_geometry() to read current geometry; do not rely on receiving + * an initial configure callback when registering. + */ +bool yasl_private_surface_set_callbacks(struct yasl_surface *s, + const struct yasl_private_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. + */ +void yasl_private_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_private_display_flush() to service the request. Schedule again from draw to + * animate. Without YASL_PRIVATE_CAP_FRAME_PACING, throttle animation with a timer. + */ +void yasl_private_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_PRIVATE_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_PRIVATE_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. + */ +bool yasl_private_surface_present(struct yasl_surface *s, const struct yasl_private_framebuffer *fb, + const struct yasl_private_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_private_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. + */ +bool yasl_private_surface_poll_event(struct yasl_surface *s, struct yasl_private_event *ev); +/** + * Decode the next local file path from a YASL_PRIVATE_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. + */ +size_t yasl_private_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_private_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. + */ +bool yasl_private_surface_read_pixels(struct yasl_surface *s, uint32_t *out, size_t cap, + struct yasl_private_vector2i *size); +/** + * Select absolute or relative (locked) pointer input for a surface. + * @param s Surface. + * @param mode YASL_PRIVATE_POINTER_NORMAL or YASL_PRIVATE_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_private_surface_set_cursor(). RELATIVE is supported on + * Wayland compositors with the relative-pointer and pointer-constraints + * protocols; X11 and Cocoa return false. + */ +bool yasl_private_surface_set_pointer_mode(struct yasl_surface *s, enum yasl_private_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. + */ +bool yasl_private_display_poll_event(struct yasl_private_display *d, struct yasl_private_event *ev); + +/** Stable nonzero identity within a display; zero for NULL. Use on the display thread. */ +uint64_t yasl_private_surface_id(const struct yasl_surface *s); +/** Store borrowed application data independently of callback userdata. */ +void yasl_private_surface_set_userdata(struct yasl_surface *s, void *userdata); +/** Read borrowed application data, or NULL for NULL; use on the display thread. */ +void *yasl_private_surface_userdata(const struct yasl_surface *s); + +/** Thread-safe message descriptor. Zero target_id means display-wide. */ +struct yasl_private_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. + */ +bool yasl_private_display_post(struct yasl_private_display *d, const struct yasl_private_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. + */ +bool yasl_private_frame_present(struct yasl_private_frame *frame, + const struct yasl_private_rect2i *rects, size_t count); +/** Coalesce a redraw request; use on the display thread. NULL is ignored. */ +void yasl_private_surface_request_frame(struct yasl_surface *s); +/** Set drawing policy for either loop style. Returns false with errno on failure. */ +bool yasl_private_surface_set_pacing(struct yasl_surface *s, yasl_private_pacing_mode mode); + +/** Request a positive logical-pixel size. Success means issued, not configured. */ +bool yasl_private_surface_set_size(struct yasl_surface *s, struct yasl_private_vector2i size_logical); +/** Request fullscreen state; returns acceptance, not confirmation. */ +bool yasl_private_surface_set_fullscreen(struct yasl_surface *s, bool enabled); +/** Request maximized state; returns acceptance, not confirmation. */ +bool yasl_private_surface_set_maximized(struct yasl_surface *s, bool enabled); +/** Request minimization. Window requests set errno on failure; display thread only. */ +bool yasl_private_surface_minimize(struct yasl_surface *s); + +/** Offer copied UTF-8 text. Returns false with errno if invalid/unsupported/failed. */ +bool yasl_private_clipboard_set(struct yasl_private_display *d, enum yasl_private_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. + */ +uint64_t yasl_private_clipboard_request(struct yasl_surface *s, enum yasl_private_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. + */ +struct yasl_private_geometry yasl_private_surface_geometry(const struct yasl_surface *s); +/** + * Read current window state. + * @param s Surface, or NULL. + * @return A bitmask of yasl_private_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. + */ +uint32_t yasl_private_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_PRIVATE_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. + */ +struct yasl_private_timing yasl_private_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_private_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. + */ +uint64_t yasl_private_surface_frame_time_ns(struct yasl_surface *s, uint64_t now); +/* Set the mouse and tablet cursor for this surface, including future entries. + * YASL_PRIVATE_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_PRIVATE_CURSOR_HIDDEN hides the cursor without disabling input. + * The choice persists across motion and re-entry until another shape is selected. + */ +void yasl_private_surface_set_cursor(struct yasl_surface *s, enum yasl_private_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. + */ +void yasl_private_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_PRIVATE_EVENT_TEXT into documents, + * not preedit text. + */ +const char *yasl_private_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. + */ +bool yasl_private_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. + */ +void yasl_private_surface_set_ime_caret(struct yasl_surface *s, struct yasl_private_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. + */ +bool yasl_private_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_private_resize_edge enumerator. + * @return true if issued; false for an invalid edge, missing support, or rejected request. + */ +bool yasl_private_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_private_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. + */ +bool yasl_private_surface_show_window_menu(struct yasl_surface *s, struct yasl_private_vector2i pos); + +/* Drag Support */ +/** + * Attach a toplevel surface to the current surface drag. + * @param s Surface to carry; check YASL_PRIVATE_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. + */ +bool yasl_private_surface_drag_carry(struct yasl_surface *s, struct yasl_private_vector2i offset); +/** + * Place a toplevel surface relative to the current pointer. + * @param s Surface; check YASL_PRIVATE_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. + */ +bool yasl_private_surface_place_under_pointer(struct yasl_surface *s, struct yasl_private_vector2i at); + +#ifdef __cplusplus +} +#endif + +#endif /* YASL_PRIVATE_H */ |
