diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/yasl/cpu.h | 25 | ||||
| -rw-r--r-- | include/yasl/desktop.h | 20 | ||||
| -rw-r--r-- | include/yasl/gl.h | 37 | ||||
| -rw-r--r-- | include/yasl/metal.h | 5 | ||||
| -rw-r--r-- | include/yasl/native/cocoa.h | 15 | ||||
| -rw-r--r-- | include/yasl/native/wayland.h | 13 | ||||
| -rw-r--r-- | include/yasl/native/x11.h | 13 | ||||
| -rw-r--r-- | include/yasl/vulkan.h | 28 | ||||
| -rw-r--r-- | include/yasl/yasl.h | 401 |
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 } |
