summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-14 13:13:52 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-14 13:13:52 +0300
commit1ab3e5a123109704789c2768e11a4f9af515821d (patch)
tree31ee03e58093a58100c6eb58681d5d29648a5ddd /include
parentd86fa6215d40caa7852dbbd6a8cf4aa8e89dd879 (diff)
Redefine public and rendering APIs with explicit contracts
Diffstat (limited to 'include')
-rw-r--r--include/yasl/cpu.h25
-rw-r--r--include/yasl/desktop.h20
-rw-r--r--include/yasl/gl.h37
-rw-r--r--include/yasl/metal.h5
-rw-r--r--include/yasl/native/cocoa.h15
-rw-r--r--include/yasl/native/wayland.h13
-rw-r--r--include/yasl/native/x11.h13
-rw-r--r--include/yasl/vulkan.h28
-rw-r--r--include/yasl/yasl.h401
9 files changed, 416 insertions, 141 deletions
diff --git a/include/yasl/cpu.h b/include/yasl/cpu.h
index d18f91f..23e0803 100644
--- a/include/yasl/cpu.h
+++ b/include/yasl/cpu.h
@@ -1,14 +1,29 @@
-/** @file CPU surfaces: draw into the lent pixel buffer, then present it. */
+/** @file CPU rendering with explicitly acquired frame buffers. */
#ifndef YASL_CPU_H
#define YASL_CPU_H
#include "yasl/yasl.h"
#ifdef __cplusplus
extern "C" {
#endif
-/** width*height premultiplied 0xAARRGGBB pixels, rows tightly packed. Contents
- * persist; a resize keeps the overlap and zeroes the rest. Valid until the next wait. */
-YASL_API uint32_t *yasl_cpu_pixels(yasl_surface *surface, int *width, int *height);
-YASL_API bool yasl_cpu_present(yasl_surface *surface);
+/** Borrowed premultiplied 0xAARRGGBB pixels; stride_bytes describes each row.
+ * Only pixels may be edited. Preserve the remaining fields for present/discard.
+ * The buffer expires on successful present/discard, the next wait, or destruction.
+ * Do not retain or access pixels after expiry. */
+struct yasl_cpu_buffer {
+ uint32_t *pixels;
+ int width, height;
+ size_t stride_bytes;
+ uint64_t token;
+};
+/** One outstanding acquisition per surface (-EBUSY otherwise). Starts with the
+ * last submitted pixels; resize preserves their overlap and clears new pixels.
+ * Clears out on failure. Acquisition does not change the visible frame. */
+YASL_API int yasl_cpu_acquire(yasl_surface *surface, struct yasl_cpu_buffer *out);
+/** Snapshot this buffer for presentation, then consume its token. Failed calls
+ * leave a valid acquisition retryable. Stale/consumed tokens return -ESTALE.
+ * Success means queued, not confirmed scanout. */
+YASL_API int yasl_cpu_present(yasl_surface *surface, const struct yasl_cpu_buffer *buffer);
+YASL_API int yasl_cpu_discard(yasl_surface *surface, const struct yasl_cpu_buffer *buffer);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/desktop.h b/include/yasl/desktop.h
index 2c2379e..6dc24e9 100644
--- a/include/yasl/desktop.h
+++ b/include/yasl/desktop.h
@@ -5,16 +5,20 @@
#ifdef __cplusplus
extern "C" {
#endif
-enum yasl_appearance { YASL_APPEARANCE_DARK=1u, YASL_APPEARANCE_LIGHT=2u, YASL_APPEARANCE_HIGH_CONTRAST=4u };
-YASL_API bool yasl_open_uri(const char *uri);
-YASL_API bool yasl_notify(const char *title, const char *body);
-YASL_API unsigned yasl_appearance(void);
-YASL_API bool yasl_surface_bell(yasl_surface *surface);
+enum yasl_appearance {
+ YASL_APPEARANCE_DARK = 1u,
+ YASL_APPEARANCE_LIGHT = 2u,
+ YASL_APPEARANCE_HIGH_CONTRAST = 4u
+};
+YASL_API int yasl_open_uri(const char *uri);
+YASL_API int yasl_notify(const char *title, const char *body);
+YASL_API unsigned yasl_get_appearance(void);
+YASL_API int yasl_surface_bell(yasl_surface *surface);
/** Full byte length excluding NUL, zero on failure. Buffer unchanged unless cap
* exceeds returned length. NULL/zero queries size. These three are thread-safe. */
-YASL_API size_t yasl_executable_path(char *out, size_t capacity);
-YASL_API size_t yasl_resource_dir(char *out, size_t capacity);
-YASL_API size_t yasl_default_locale(char *out, size_t capacity);
+YASL_API size_t yasl_get_executable_path(char *out, size_t capacity);
+YASL_API size_t yasl_get_resource_dir(char *out, size_t capacity);
+YASL_API size_t yasl_get_default_locale(char *out, size_t capacity);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/gl.h b/include/yasl/gl.h
index 39d2c63..d5603e3 100644
--- a/include/yasl/gl.h
+++ b/include/yasl/gl.h
@@ -1,27 +1,36 @@
-/** @file Optional EGL/OpenGL/OpenGL ES contexts on Linux. Attribute lists are per-call. */
+/** @file Optional EGL/OpenGL/OpenGL ES contexts on Linux. */
#ifndef YASL_GL_H
#define YASL_GL_H
#include "yasl/yasl.h"
#ifdef __cplusplus
extern "C" {
#endif
-enum yasl_gl_attribute { YASL_GL_END, YASL_GL_MAJOR, YASL_GL_MINOR, YASL_GL_PROFILE, YASL_GL_DEBUG,
- YASL_GL_FORWARD_COMPAT, YASL_GL_RED_BITS, YASL_GL_GREEN_BITS, YASL_GL_BLUE_BITS, YASL_GL_ALPHA_BITS,
- YASL_GL_DEPTH_BITS, YASL_GL_STENCIL_BITS, YASL_GL_SAMPLES, YASL_GL_SRGB, YASL_GL_API };
enum yasl_gl_profile { YASL_GL_ANY, YASL_GL_CORE, YASL_GL_COMPATIBILITY };
enum yasl_gl_api { YASL_GL_OPENGL, YASL_GL_OPENGL_ES };
typedef void (*yasl_gl_proc)(void);
-/** key/value pairs terminated by END, NULL defaults to GL3.2 core RGBA8 D24 S8.
- * share is a live GL surface or NULL. CPU flag is invalid. Context is owned by
- * the returned surface. Detach it from all rendering threads before destruction.
- * Cocoa returns NULL with YASL_ERROR_UNSUPPORTED; use Metal or MoltenVK. */
-YASL_API yasl_surface *yasl_gl_surface_create(const char *title, int width, int height,
- unsigned flags, const int *attributes, yasl_surface *share);
-/** May run on a rendering thread. NULL detaches this thread's current context. */
-YASL_API bool yasl_gl_make_current(yasl_surface *surface);
+struct yasl_gl_options {
+ int major, minor;
+ enum yasl_gl_profile profile;
+ enum yasl_gl_api api;
+ int red_bits, green_bits, blue_bits, alpha_bits;
+ int depth_bits, stencil_bits, samples;
+ bool debug, forward_compat, srgb;
+ yasl_surface *share;
+};
+/** C and C++ initializer: GL 3.2 core, RGBA8, D24, S8. */
+#define YASL_GL_OPTIONS_INIT \
+ {3, 2, YASL_GL_CORE, YASL_GL_OPENGL, 8, 8, 8, 8, 24, 8, 0, false, false, false, NULL}
+/** NULL gl selects defaults. options->type must be NATIVE. share, when set,
+ * must be a live GL surface. Detach the owned context from every rendering
+ * thread before destruction. Cocoa fails with errno=ENOTSUP. */
+YASL_API yasl_surface *yasl_gl_surface_create(const struct yasl_surface_options *options,
+ const struct yasl_gl_options *gl);
+/** These four operations may run on a rendering thread. The application must
+ * synchronize surface/display destruction. NULL make_current detaches. */
+YASL_API int yasl_gl_make_current(yasl_surface *surface);
YASL_API yasl_gl_proc yasl_gl_get_proc_address(const char *name);
-YASL_API bool yasl_gl_swap_interval(yasl_surface *surface, int interval);
-YASL_API bool yasl_gl_swap_buffers(yasl_surface *surface);
+YASL_API int yasl_gl_set_swap_interval(yasl_surface *surface, int interval);
+YASL_API int yasl_gl_present(yasl_surface *surface);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/metal.h b/include/yasl/metal.h
index 695f80c..8197d80 100644
--- a/include/yasl/metal.h
+++ b/include/yasl/metal.h
@@ -12,8 +12,9 @@ extern "C" {
#endif
/** Borrowed until surface destruction. YASL owns view/layer and drawableSize.
* No device, drawable acquisition, command submission, or implicit present.
- * Returns NULL on unsupported backend, CPU/GL surface, or incompatible presenter. */
-YASL_API CAMetalLayer *yasl_metal_layer(yasl_surface *surface);
+ * Returns -ENOTSUP on unsupported backends, -EBUSY for a different presenter.
+ * Clears out on failure. Successful access reserves the surface for Metal. */
+YASL_API int yasl_metal_get_layer(yasl_surface *surface, CAMetalLayer **out);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/native/cocoa.h b/include/yasl/native/cocoa.h
index bd92c98..2d2d432 100644
--- a/include/yasl/native/cocoa.h
+++ b/include/yasl/native/cocoa.h
@@ -1,3 +1,4 @@
+/** @file Borrowed cocoa handles for an initialized, connected surface. */
#ifndef YASL_NATIVE_COCOA_H
#define YASL_NATIVE_COCOA_H
#include "yasl/yasl.h"
@@ -13,10 +14,16 @@ typedef struct objc_object NSView;
#ifdef __cplusplus
extern "C" {
#endif
-/** Borrowed native objects. Use on main thread, never change native ownership. */
-YASL_API NSApplication *yasl_cocoa_application(void);
-YASL_API NSWindow *yasl_cocoa_window(const yasl_surface *surface);
-YASL_API NSView *yasl_cocoa_view(const yasl_surface *surface);
+struct yasl_cocoa_handles {
+ NSApplication *application;
+ NSWindow *window;
+ NSView *view;
+};
+/** Owner thread only. Returns -ENOTSUP for another backend and -ENOTCONN
+ * while disconnected. Clears out on failure. Handles expire on display loss
+ * or surface destruction; query again after DISPLAY_RESTORED. Never destroy
+ * borrowed objects or dispatch/close the connection independently. */
+YASL_API int yasl_cocoa_get_native(const yasl_surface *surface, struct yasl_cocoa_handles *out);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/native/wayland.h b/include/yasl/native/wayland.h
index 1b8881e..5c18a80 100644
--- a/include/yasl/native/wayland.h
+++ b/include/yasl/native/wayland.h
@@ -1,3 +1,4 @@
+/** @file Borrowed wayland handles for an initialized, connected surface. */
#ifndef YASL_NATIVE_WAYLAND_H
#define YASL_NATIVE_WAYLAND_H
#include "yasl/yasl.h"
@@ -6,9 +7,15 @@ struct wl_surface;
#ifdef __cplusplus
extern "C" {
#endif
-/** Borrowed handles; never dispatch or close native connections independently. */
-YASL_API struct wl_display *yasl_wayland_display(const yasl_surface *surface);
-YASL_API struct wl_surface *yasl_wayland_surface(const yasl_surface *surface);
+struct yasl_wayland_handles {
+ struct wl_display *display;
+ struct wl_surface *surface;
+};
+/** Owner thread only. Returns -ENOTSUP for another backend and -ENOTCONN
+ * while disconnected. Clears out on failure. Handles expire on display loss
+ * or surface destruction; query again after DISPLAY_RESTORED. Never destroy
+ * borrowed objects or dispatch/close the connection independently. */
+YASL_API int yasl_wayland_get_native(const yasl_surface *surface, struct yasl_wayland_handles *out);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/native/x11.h b/include/yasl/native/x11.h
index f8c37ae..6cc85fb 100644
--- a/include/yasl/native/x11.h
+++ b/include/yasl/native/x11.h
@@ -1,3 +1,4 @@
+/** @file Borrowed x11 handles for an initialized, connected surface. */
#ifndef YASL_NATIVE_X11_H
#define YASL_NATIVE_X11_H
#include "yasl/yasl.h"
@@ -5,9 +6,15 @@ typedef struct _XDisplay Display;
#ifdef __cplusplus
extern "C" {
#endif
-/** Borrowed handles; surface/window lifetime and native connection stay in YASL. */
-YASL_API Display *yasl_x11_display(const yasl_surface *surface);
-YASL_API uintptr_t yasl_x11_window(const yasl_surface *surface);
+struct yasl_x11_handles {
+ Display *display;
+ uintptr_t window;
+};
+/** Owner thread only. Returns -ENOTSUP for another backend and -ENOTCONN
+ * while disconnected. Clears out on failure. Handles expire on display loss
+ * or surface destruction; query again after DISPLAY_RESTORED. Never destroy
+ * borrowed objects or dispatch/close the connection independently. */
+YASL_API int yasl_x11_get_native(const yasl_surface *surface, struct yasl_x11_handles *out);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/vulkan.h b/include/yasl/vulkan.h
index afa1089..1a1c5be 100644
--- a/include/yasl/vulkan.h
+++ b/include/yasl/vulkan.h
@@ -1,4 +1,4 @@
-/** @file Vulkan WSI only; application owns all Vulkan objects. */
+/** @file Vulkan WSI; YASL tracks the WSI handle, the application owns rendering. */
#ifndef YASL_VULKAN_H
#define YASL_VULKAN_H
#include "yasl/yasl.h"
@@ -6,13 +6,27 @@
#ifdef __cplusplus
extern "C" {
#endif
-YASL_API bool yasl_vulkan_init(PFN_vkGetInstanceProcAddr loader);
-/** Borrowed list through shutdown; merge with app extensions before instance creation. */
-YASL_API const char *const *yasl_vulkan_instance_extensions(const yasl_surface *surface, uint32_t *count);
-YASL_API VkInstanceCreateFlags yasl_vulkan_instance_flags(const yasl_surface *surface);
-/** Uses injected loader; destroy returned VkSurfaceKHR before YASL surface. */
+YASL_API int yasl_vulkan_init(PFN_vkGetInstanceProcAddr loader);
+struct yasl_vulkan_requirements {
+ const char *const *extensions;
+ uint32_t extension_count;
+ VkInstanceCreateFlags flags;
+};
+/** Initialize the loader first. Borrowed extensions live through shutdown;
+ * merge them with application extensions before creating the instance.
+ * Clears out on failure. */
+YASL_API int yasl_vulkan_get_requirements(const yasl_surface *surface,
+ struct yasl_vulkan_requirements *out);
+/** WSI creation retains VkResult semantics. Uses the injected loader.
+ * One live VkSurfaceKHR per window; destroy it with yasl_vulkan_destroy_surface
+ * before destroying the YASL surface. The application owns swapchains/devices. */
YASL_API VkResult yasl_vulkan_create_surface(yasl_surface *surface, VkInstance instance,
- const VkAllocationCallbacks *allocator, VkSurfaceKHR *out);
+ const VkAllocationCallbacks *allocator,
+ VkSurfaceKHR *out);
+/** Destroy the WSI surface (including while disconnected), releasing the window
+ * for another renderer. Destroy dependent swapchains first. Uses the instance
+ * and allocation callbacks recorded at creation. No live WSI surface is a no-op. */
+YASL_API int yasl_vulkan_destroy_surface(yasl_surface *surface);
#ifdef __cplusplus
}
#endif
diff --git a/include/yasl/yasl.h b/include/yasl/yasl.h
index c0ebb75..284039a 100644
--- a/include/yasl/yasl.h
+++ b/include/yasl/yasl.h
@@ -1,8 +1,11 @@
-/** @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. */
+/** @file Windows, input and events.
+ * Commands return 0 on success or a negative errno value on failure. Constructors
+ * return NULL and set errno on failure; data queries document their sentinel.
+ * Use the initializing thread (main on Cocoa), except where stated otherwise.
+ * Coordinates are logical units unless named pixel. */
#ifndef YASL_H
#define YASL_H
+#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -18,56 +21,226 @@ extern "C" {
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, YASL_ERROR_DISCONNECTED };
+enum yasl_surface_type { YASL_SURFACE_NATIVE, YASL_SURFACE_CPU };
+enum yasl_surface_flags {
+ YASL_SURFACE_HIDDEN = 2u,
+ YASL_SURFACE_UNDECORATED = 4u,
+ YASL_SURFACE_FIXED_SIZE = 8u
+};
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_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 };
+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))
-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_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, YASL_EVENT_DISPLAY_RESTORED };
+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,
+ YASL_EVENT_DISPLAY_RESTORED
+};
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 };
-struct yasl_window_payload { int width,height,pixel_width,pixel_height; double scale; unsigned state; };
-struct yasl_key_payload { enum yasl_key key; enum yasl_key_action action; unsigned mods;
- uint32_t codepoint, shifted, native_code; };
-struct yasl_text_payload { const char *data; size_t length; };
-struct yasl_pointer_payload { double x,y,dx,dy; enum yasl_pointer_action action; unsigned button,buttons,mods; };
-struct yasl_scroll_payload { double x,y,lines_x,lines_y,pixels_x,pixels_y; unsigned valid,source,phase,mods; bool momentum; };
-struct yasl_pen_payload { 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; };
-struct yasl_composition_payload { const char *data; size_t length; int begin,end; bool active; uint64_t revision,generation; };
-struct yasl_text_edit_payload { const char *data; size_t length,begin,end; uint64_t revision,generation; };
-struct yasl_clipboard_payload { const char *data; size_t length; uint64_t request_id; enum yasl_transfer_status status; };
-struct yasl_drop_payload { enum yasl_drop_action action; double x,y; const char *data; size_t length; };
-struct yasl_drag_payload { enum yasl_drag_action action; double x,y; };
+struct yasl_window_payload {
+ int width, height, pixel_width, pixel_height;
+ double scale;
+ unsigned state;
+};
+struct yasl_key_payload {
+ enum yasl_key key;
+ enum yasl_key_action action;
+ unsigned mods;
+ uint32_t codepoint, shifted, native_code;
+};
+struct yasl_text_payload {
+ const char *data;
+ size_t length;
+};
+struct yasl_pointer_payload {
+ double x, y, dx, dy;
+ enum yasl_pointer_action action;
+ unsigned button, buttons, mods;
+};
+struct yasl_scroll_payload {
+ double x, y, lines_x, lines_y, pixels_x, pixels_y;
+ unsigned valid, source, phase, mods;
+ bool momentum;
+};
+struct yasl_pen_payload {
+ 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;
+};
+struct yasl_composition_payload {
+ const char *data;
+ size_t length;
+ int begin, end;
+ bool active;
+ uint64_t revision, generation;
+};
+struct yasl_text_edit_payload {
+ const char *data;
+ size_t length, begin, end;
+ uint64_t revision, generation;
+};
+struct yasl_clipboard_payload {
+ const char *data;
+ size_t length;
+ uint64_t request_id;
+ enum yasl_transfer_status status;
+};
+struct yasl_drop_payload {
+ enum yasl_drop_action action;
+ double x, y;
+ const char *data;
+ size_t length;
+};
+struct yasl_drag_payload {
+ enum yasl_drag_action action;
+ double x, y;
+};
/** 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.
@@ -98,69 +271,107 @@ struct yasl_event {
struct yasl_drag_payload drag;
};
};
-/** 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
+/** NULL options select the automatic backend and no application ID. */
+struct yasl_options {
+ enum yasl_backend backend;
+ const char *app_id;
+};
+/** Zero initialization selects a native GPU window. A positive logical size is
+ * required; title may be NULL. Strings are copied before creation returns. */
+struct yasl_surface_options {
+ const char *title;
+ int width, height;
+ enum yasl_surface_type type;
+ unsigned flags;
+ void *userdata;
+};
+/** Optional explicit initialization. Creation initializes with defaults when
+ * needed. Reinitialization returns -EALREADY; failed initialization is retryable. */
+YASL_API int yasl_init(const struct yasl_options *options);
+YASL_API yasl_surface *yasl_surface_create(const struct yasl_surface_options *options);
+/** Also destroys its popups. NULL is a no-op. Returns -EBUSY while a window
+ * in the subtree owns a Vulkan surface; destroy that WSI surface first. */
+YASL_API int yasl_surface_destroy(yasl_surface *surface);
+/** Destroys all surfaces. Returns -EBUSY without destroying any windows if
+ * a Vulkan surface remains live. Release your GPU objects first. */
+YASL_API int yasl_shutdown(void);
+/** 1 event, 0 none (timeout or wake), negative errno on 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);
+/** Monotonic nanoseconds; thread-safe and independent of initialization. */
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);
+/** Queries accept NULL: return AUTO, zero, NULL or scale 1; size outputs are
+ * optional and become zero. Non-NULL surfaces must belong to the owner thread. */
+YASL_API enum yasl_backend yasl_surface_get_backend(const yasl_surface *surface);
+YASL_API unsigned yasl_surface_get_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 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);
+YASL_API unsigned yasl_surface_get_state(const yasl_surface *surface);
+YASL_API void *yasl_surface_get_userdata(const yasl_surface *surface);
+YASL_API int yasl_surface_set_userdata(yasl_surface *surface, void *userdata);
+YASL_API int 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);
+YASL_API int yasl_surface_request_size(yasl_surface *surface, int width, int height);
+YASL_API int yasl_surface_request_fullscreen(yasl_surface *surface, bool enabled);
+YASL_API int yasl_surface_request_maximized(yasl_surface *surface, bool enabled);
+YASL_API int yasl_surface_request_minimize(yasl_surface *surface);
+YASL_API int yasl_surface_set_cursor(yasl_surface *surface, enum yasl_cursor cursor);
+YASL_API int 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);
+YASL_API int yasl_surface_set_refresh_callback(yasl_surface *surface,
+ void (*refresh)(yasl_surface *, void *),
+ void *userdata);
+YASL_API int yasl_get_double_click_ms(void);
+YASL_API int 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);
+YASL_API int 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 int 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 int yasl_surface_set_ime_caret(yasl_surface *surface, double x, double y, double width,
+ double height);
+/** Anchor selects a point on the parent rectangle; gravity is the direction
+ * the popup grows. Zero edges mean center. All dimensions are logical units. */
+struct yasl_popup_options {
+ int width, height;
+ double x, y, anchor_width, anchor_height;
+ enum yasl_popup_edge anchor, gravity;
+ unsigned constraints;
+};
+/** Trigger must be a recent pointer/pen press on parent. */
+YASL_API yasl_surface *yasl_popup_create(yasl_surface *parent,
+ const struct yasl_popup_options *options,
+ const yasl_event *trigger);
+YASL_API int yasl_popup_reposition(yasl_surface *popup, const struct yasl_popup_options *options);
+YASL_API int yasl_surface_start_interactive_move(yasl_surface *surface, const yasl_event *trigger);
+YASL_API int yasl_surface_start_interactive_resize(yasl_surface *surface,
+ enum yasl_resize_edge edge,
+ const yasl_event *trigger);
+YASL_API int yasl_surface_show_window_menu(yasl_surface *surface, double x, double y,
+ const yasl_event *trigger);
+/** Optional premultiplied ARGB image in device pixels. Copied by drag_start. */
+struct yasl_drag_image {
+ const uint32_t *pixels;
+ int width, height;
+ int hotspot_x, hotspot_y;
+};
+YASL_API int yasl_drag_start(yasl_surface *origin, const yasl_event *trigger,
+ const struct yasl_drag_image *image);
+YASL_API int yasl_drag_cancel(void);
+YASL_API int yasl_surface_drag_carry(yasl_surface *surface, double x, double y);
+YASL_API int yasl_surface_place_under_pointer(yasl_surface *surface, double x, double y);
+/** Parse local file URIs. Returns byte length excluding NUL, zero at end.
+ * If capacity <= length, leaves cursor/output unchanged for retry. NULL/zero
+ * queries size. The caller owns the cursor string; this helper is thread-safe. */
YASL_API size_t yasl_drop_next_path(const char **cursor, char *out, size_t capacity);
#ifdef __cplusplus
}