1132 lines
42 KiB
C
1132 lines
42 KiB
C
#ifndef UHDK_H_INCLUDED
|
|
#define UHDK_H_INCLUDED
|
|
|
|
/*
|
|
* Uhdk desktop platform API — v0.1, macOS, Windows and Linux backends.
|
|
*
|
|
* Implementation: Zig. ABI: C. Header baseline: C99 (also usable from C++).
|
|
* No libc runtime objects or allocation contract.
|
|
* <stdint.h> supplies types only; this header requires no libc function calls.
|
|
* Native OS frameworks may themselves depend on system runtimes.
|
|
*
|
|
* Header configuration (define before the first include):
|
|
* - UHDK_ENABLE_OPENGL: include bundled GLAD types and per-context loader API.
|
|
* - UHDK_ENABLE_NATIVE: declare the experimental borrowed native-handle API.
|
|
* - UHDK_PROFILE_BACKEND: quoted consumer instrumentation adapter header.
|
|
* Presence enables each feature flag; leave it undefined to disable it.
|
|
* These select declarations only, not library backend/build features.
|
|
*
|
|
* Naming:
|
|
* - Types: uhdk_type; functions: uhdk_object_verb; constants: UHDK_CATEGORY_VALUE.
|
|
* - create/destroy allocate and dispose unique objects; retain/release manage
|
|
* shared ownership. Reference-counted objects also start with create.
|
|
* - get/set access properties; copy writes caller storage; is/has/can query bools.
|
|
* - *_async starts a request completed by UHDK_EVENT_REQUEST_DONE. Functions
|
|
* that merely schedule events (wake/invalidate) do not create async requests.
|
|
* - *_desc describes creation/configuration; *_fn names callbacks; *_flags names
|
|
* bitmask types. Pointer/span lengths use len or <field>_len; writable buffers
|
|
* use capacity. Measurement units are named explicitly where needed.
|
|
*
|
|
* Global rules:
|
|
* - Floating-point values use C float (32-bit / Zig f32 on supported targets).
|
|
* - All text is UTF-8 pointer + byte length, never implicitly NUL-terminated.
|
|
* Embedded NUL is rejected where an OS identifier/path cannot represent it.
|
|
* - NULL is allowed for a span's pointer only when its length is zero.
|
|
* - Input spans/descriptors are copied before return unless documented otherwise.
|
|
* - No allocator ownership crosses the ABI. Release objects through Uhdk.
|
|
* - Event batches and spans are borrowed until the next valid poll on the
|
|
* application thread, or app destruction (whichever comes first). Copy spans
|
|
* or retain files/menus to keep them. Every such poll resets storage, including empty/error polls.
|
|
* Rendering does not reset storage. Each poll returns an immutable batch.
|
|
* - create/run/destroy belong to OS main. run invokes one application entry on
|
|
* a second thread. All other calls belong to that application thread except
|
|
* app_wake, which is thread-safe. Native work is queued to the main thread.
|
|
* - File operations are async to the caller and executed in bounded platform
|
|
* batches. Individual filesystem calls can still delay native input collection.
|
|
* - Descriptors start with struct_size; zero-initialize them, set struct_size to
|
|
* sizeof(the descriptor), then fill fields. Reserved fields must remain zero.
|
|
* Unknown trailing fields are ignored; smaller descriptors are rejected.
|
|
* - Integer enum values have fixed-width typedefs; C enums only name constants.
|
|
* - For output structs with struct_size, callers set it before the call; Uhdk
|
|
* writes only the supplied size. Event struct_size describes library output.
|
|
* - Functions return a status; output arguments are valid only on UHDK_STATUS_OK,
|
|
* except documented buffer-size queries.
|
|
* - The application owns rendering, document state, file encoding and layout.
|
|
* Uhdk provides optional OpenGL 3.3 core context management. Other renderers
|
|
* may attach through the experimental native-handle API; drawing remains app-owned.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
/* Optional, consumer-owned instrumentation; no exported UHDK ABI or dependency.
|
|
* Define UHDK_PROFILE_BACKEND to a quoted adapter header before including uhdk.h.
|
|
* That header implements the macros below. Without it, arguments are not evaluated.
|
|
* Names (zone, thread, pool) must be string literals or have static lifetime.
|
|
* C zones: UHDK_PROFILE_BEGIN(token, "name"); ... UHDK_PROFILE_END(token);
|
|
* End on the same thread, in reverse nesting order, including early exits.
|
|
* C++ may use UHDK_PROFILE_SCOPE("name") for automatic scope exit.
|
|
* Memory: report successful non-null allocations, then free BEFORE releasing
|
|
* storage. A successful resize is free + alloc; failed allocations emit nothing.
|
|
* A pointer must use the same pool name for allocation and free. These hooks do
|
|
* not allocate/free memory themselves, intercept malloc, or transfer ownership.
|
|
*/
|
|
#ifdef UHDK_PROFILE_BACKEND
|
|
#include UHDK_PROFILE_BACKEND
|
|
#else
|
|
#define UHDK_PROFILE_BEGIN(token, name) ((void)0)
|
|
#define UHDK_PROFILE_END(token) ((void)0)
|
|
#define UHDK_PROFILE_SCOPE(name) ((void)0)
|
|
#define UHDK_PROFILE_FRAME() ((void)0)
|
|
#define UHDK_PROFILE_THREAD(name) ((void)0)
|
|
#define UHDK_PROFILE_ALLOC(ptr, size, pool) ((void)0)
|
|
#define UHDK_PROFILE_FREE(ptr, pool) ((void)0)
|
|
#endif
|
|
|
|
#ifndef UHDK_API
|
|
#if defined(_WIN32) && defined(UHDK_SHARED)
|
|
#if defined(UHDK_BUILD)
|
|
#define UHDK_API __declspec(dllexport)
|
|
#else
|
|
#define UHDK_API __declspec(dllimport)
|
|
#endif
|
|
#elif defined(__GNUC__) && defined(UHDK_SHARED)
|
|
#define UHDK_API __attribute__((visibility("default")))
|
|
#else
|
|
#define UHDK_API
|
|
#endif
|
|
#endif
|
|
#if defined(_WIN32) && !defined(_WIN64)
|
|
#define UHDK_CALL __cdecl
|
|
#else
|
|
#define UHDK_CALL
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define UHDK_ABI_VERSION 1u
|
|
|
|
typedef char uhdk_bool; /* Values are UHDK_FALSE (0) or UHDK_TRUE (1). */
|
|
enum {
|
|
UHDK_FALSE = 0,
|
|
UHDK_TRUE = 1
|
|
};
|
|
|
|
typedef uint32_t uhdk_status;
|
|
enum {
|
|
UHDK_STATUS_OK = 0,
|
|
UHDK_STATUS_CANCELLED = 1,
|
|
UHDK_STATUS_UNSUPPORTED = 2,
|
|
UHDK_STATUS_INVALID_ARGUMENT = 3,
|
|
UHDK_STATUS_OUT_OF_MEMORY = 4,
|
|
UHDK_STATUS_PERMISSION_DENIED = 5,
|
|
UHDK_STATUS_UNAVAILABLE = 6,
|
|
UHDK_STATUS_NOT_FOUND = 7,
|
|
UHDK_STATUS_BUSY = 8,
|
|
UHDK_STATUS_WRONG_THREAD = 9,
|
|
UHDK_STATUS_OS_ERROR = 10,
|
|
UHDK_STATUS_BUFFER_TOO_SMALL = 11
|
|
};
|
|
|
|
typedef struct uhdk_app uhdk_app;
|
|
typedef struct uhdk_window uhdk_window;
|
|
typedef struct uhdk_gl_context uhdk_gl_context;
|
|
typedef struct uhdk_file uhdk_file;
|
|
typedef struct uhdk_watch uhdk_watch;
|
|
typedef struct uhdk_menu uhdk_menu;
|
|
typedef uint64_t uhdk_request_id; /* 0 is invalid; IDs never reused per app. */
|
|
|
|
typedef struct uhdk_text {
|
|
const char *ptr;
|
|
uint64_t len;
|
|
} uhdk_text;
|
|
|
|
typedef struct uhdk_bytes {
|
|
const uint8_t *ptr;
|
|
uint64_t len;
|
|
} uhdk_bytes;
|
|
|
|
typedef struct uhdk_text_list {
|
|
const uhdk_text *ptr;
|
|
uint64_t len;
|
|
} uhdk_text_list;
|
|
|
|
typedef struct uhdk_file_list {
|
|
uhdk_file *const *ptr;
|
|
uint64_t len;
|
|
} uhdk_file_list;
|
|
|
|
typedef struct uhdk_point {
|
|
float x;
|
|
float y;
|
|
} uhdk_point;
|
|
|
|
typedef struct uhdk_size {
|
|
float width;
|
|
float height;
|
|
} uhdk_size;
|
|
|
|
typedef struct uhdk_rect {
|
|
float x;
|
|
float y;
|
|
float width;
|
|
float height;
|
|
} uhdk_rect;
|
|
|
|
typedef struct uhdk_image {
|
|
uint32_t struct_size;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t reserved;
|
|
uint64_t stride_bytes;
|
|
uhdk_bytes pixels; /* Top-down, straight-alpha RGBA8 in sRGB. */
|
|
} uhdk_image;
|
|
|
|
typedef uint32_t uhdk_backend;
|
|
enum {
|
|
UHDK_BACKEND_AUTO = 0,
|
|
UHDK_BACKEND_MACOS = 1,
|
|
UHDK_BACKEND_WINDOWS = 2,
|
|
UHDK_BACKEND_WAYLAND = 3,
|
|
UHDK_BACKEND_X11 = 4
|
|
};
|
|
|
|
typedef uint32_t uhdk_capability;
|
|
enum {
|
|
UHDK_CAP_FILE_DIALOGS = 1,
|
|
UHDK_CAP_CLIPBOARD = 2,
|
|
UHDK_CAP_DROP_FILES = 4,
|
|
UHDK_CAP_APP_MENU = 5,
|
|
UHDK_CAP_CONTEXT_MENU = 6,
|
|
UHDK_CAP_APP_ICON = 8,
|
|
UHDK_CAP_POINTER_CAPTURE = 12,
|
|
UHDK_CAP_TEXT_INPUT = 16,
|
|
UHDK_CAP_OPENGL = 18
|
|
};
|
|
|
|
/* Every accepted async request returns a nonzero ID and exactly one terminal
|
|
* REQUEST_DONE during normal draining. Failure to accept produces no event.
|
|
* Cancellation is best effort; an operation already committed may succeed.
|
|
* Return from app_main early abandons undelivered results and initiates shutdown.
|
|
*/
|
|
typedef struct uhdk_event uhdk_event;
|
|
typedef struct uhdk_event_list {
|
|
const uhdk_event *ptr;
|
|
uint64_t len;
|
|
} uhdk_event_list;
|
|
#define UHDK_WAIT_FOREVER UINT64_MAX
|
|
|
|
typedef void(UHDK_CALL *uhdk_app_main_fn)(uhdk_app *app, void *user);
|
|
typedef struct uhdk_app_desc {
|
|
uint32_t struct_size;
|
|
uint32_t abi_version;
|
|
uhdk_text application_id;
|
|
uhdk_text display_name;
|
|
uhdk_backend preferred_backend;
|
|
uint32_t reserved;
|
|
} uhdk_app_desc;
|
|
|
|
UHDK_API uint32_t UHDK_CALL uhdk_get_abi_version(void);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_create(const uhdk_app_desc *desc, uhdk_app **out);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_run(
|
|
uhdk_app *app,
|
|
uhdk_app_main_fn main_fn,
|
|
void *user
|
|
); /* Once. */
|
|
/* Zero timeout does not wait; finite timeouts use monotonic nanoseconds.
|
|
* STOPPED is delivered once; later polls return UNAVAILABLE. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_poll_events(
|
|
uhdk_app *app,
|
|
uint64_t timeout_ns,
|
|
uhdk_event_list *out
|
|
);
|
|
UHDK_API void UHDK_CALL uhdk_app_quit(uhdk_app *app); /* Accept/request shutdown. */
|
|
UHDK_API void UHDK_CALL uhdk_app_wake(uhdk_app *app); /* Thread-safe, coalesced WAKE event. */
|
|
/* Monotonic nanoseconds since app creation, in the same clock as event.time_ns. */
|
|
UHDK_API uint64_t UHDK_CALL uhdk_app_get_time_ns(uhdk_app *app);
|
|
/* One pending deadline per app. Replaces any previous deadline; 0 cancels it.
|
|
* A past deadline queues WAKE at the next dispatch. On expiry the deadline is
|
|
* cleared before delivering WAKE. Explicit wakes may coalesce with expiry but
|
|
* do not cancel a future deadline. No event is delivered inline. App code maintains
|
|
* multiple timers by scheduling its earliest deadline. No real-time guarantee.
|
|
*/
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_set_wake_deadline(uhdk_app *app, uint64_t deadline_ns);
|
|
UHDK_API void UHDK_CALL uhdk_app_destroy(uhdk_app *app); /* After run; releases child objects. */
|
|
/* Linux: AUTO/false before successful startup; thereafter the selected backend
|
|
* and implemented, available mechanisms. Capabilities do not guarantee success
|
|
* for a particular operation. Other platforms retain their fixed backend. */
|
|
UHDK_API uhdk_backend UHDK_CALL uhdk_app_get_backend(uhdk_app *app);
|
|
UHDK_API uhdk_bool UHDK_CALL uhdk_app_has_capability(uhdk_app *app, uhdk_capability capability);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_request_cancel(uhdk_app *app, uhdk_request_id request_id);
|
|
|
|
/* Application-thread CPU execution time in nanoseconds, not elapsed wall time.
|
|
* Bracket user update/input processing with begin_tick/end_tick, AFTER polling
|
|
* events and BEFORE rendering. Nested ticks return BUSY; end without begin is
|
|
* INVALID_ARGUMENT. Polling/idle time outside the bracket is not counted.
|
|
* Render timing uses GL begin_frame/end_frame brackets containing a successful
|
|
* swap_buffers. Setup/cleanup brackets without presentation are not frames.
|
|
* Blocked waits (including GPU waits), sleep, and time spent descheduled are
|
|
* excluded. The entire swap_buffers call is excluded, including driver spinning
|
|
* during presentation/vsync. Other CPU work in GL/driver calls is counted;
|
|
* this does not measure GPU execution or CPU work on other threads.
|
|
* tick_time_ns and render_time_ns are the most recent completed phase samples.
|
|
* frame_time_ns captures the latest completed tick + render at presentation's
|
|
* end_frame; it stays unchanged until another presented frame completes.
|
|
* frames_per_second is the reciprocal of elapsed wall time between the last two
|
|
* presented end_frame calls, across all contexts. It includes idle time, vsync,
|
|
* and GPU waits; it is NOT derived from CPU frame_time_ns or monitor refresh.
|
|
* It is zero until two frames complete, then retains the last sample while idle.
|
|
* Counts are cumulative; timings are zero until a sample is available. Calls
|
|
* do not generate events. Read the previous frame to display stats while drawing.
|
|
*/
|
|
typedef struct uhdk_app_stats {
|
|
uint32_t struct_size;
|
|
uint32_t reserved;
|
|
uint64_t tick_count;
|
|
uint64_t frame_count;
|
|
uint64_t event_count;
|
|
uint64_t tick_time_ns;
|
|
uint64_t render_time_ns;
|
|
uint64_t frame_time_ns;
|
|
float frames_per_second;
|
|
} uhdk_app_stats;
|
|
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_begin_tick(uhdk_app *app);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_end_tick(uhdk_app *app);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_get_stats(uhdk_app *app, uhdk_app_stats *out);
|
|
|
|
/* Logical coordinates: top-left origin, x right, y down. Window geometry uses
|
|
* content-area units. Framebuffer dimensions are pixels; use reported sizes,
|
|
* not a rounded logical-size * scale calculation. Global positions are not exposed.
|
|
*/
|
|
typedef uint32_t uhdk_window_flags;
|
|
enum {
|
|
UHDK_WINDOW_RESIZABLE = 1u << 0,
|
|
UHDK_WINDOW_DECORATED = 1u << 1,
|
|
UHDK_WINDOW_OPENGL = 1u << 3 /* Prepare a drawable for uhdk_gl_context_create. */
|
|
};
|
|
|
|
typedef uint32_t uhdk_window_state;
|
|
enum {
|
|
UHDK_WINDOW_NORMAL = 0,
|
|
UHDK_WINDOW_MINIMIZED = 1,
|
|
UHDK_WINDOW_MAXIMIZED = 2,
|
|
UHDK_WINDOW_FULLSCREEN = 3
|
|
};
|
|
|
|
typedef struct uhdk_window_desc {
|
|
uint32_t struct_size;
|
|
uhdk_window_flags flags;
|
|
uhdk_text title;
|
|
uhdk_size content_size;
|
|
uhdk_size min_size;
|
|
uhdk_size max_size; /* Zero limit = unconstrained. */
|
|
uhdk_window *parent; /* Optional; must outlive child. */
|
|
} uhdk_window_desc;
|
|
|
|
/* Observation bits say which independent window facts are known. A clear bit
|
|
* means unknown, not false. Support depends on the backend/protocol version. */
|
|
typedef uint32_t uhdk_window_observation_flags;
|
|
enum {
|
|
UHDK_WINDOW_OBSERVE_MINIMIZED = 1u << 0,
|
|
UHDK_WINDOW_OBSERVE_RESIZING = 1u << 1,
|
|
UHDK_WINDOW_OBSERVE_OCCLUDED = 1u << 2,
|
|
UHDK_WINDOW_OBSERVE_SUSPENDED = 1u << 3
|
|
};
|
|
|
|
/* WINDOW_METRICS is the resize/state hook; compare snapshots for transitions.
|
|
* State describes geometry (normal/maximized/fullscreen), independently of
|
|
* minimized. Wayland does not report minimization; its observation bit is clear.
|
|
* visible is show/hide visibility, not an occlusion or minimization guarantee;
|
|
* on Wayland it is application intent. occluded is an optional rendering hint,
|
|
* not permission to stop processing events. suspended is a separate compositor
|
|
* hint that content is not ordinarily repainted, not proof of occlusion or
|
|
* minimization. Resizing is an advisory interactive size/move-loop
|
|
* hint, not a guaranteed transaction around every size change.
|
|
* Async size/state completion acknowledges submission; geometry arrives here. */
|
|
typedef struct uhdk_window_metrics {
|
|
uint32_t struct_size;
|
|
uint32_t framebuffer_width;
|
|
uint32_t framebuffer_height;
|
|
uhdk_window_state state;
|
|
uhdk_size logical_size;
|
|
float scale;
|
|
uhdk_bool focused;
|
|
uhdk_bool visible;
|
|
uhdk_window_observation_flags observations;
|
|
uhdk_bool minimized;
|
|
uhdk_bool resizing;
|
|
uhdk_bool occluded;
|
|
uhdk_bool suspended;
|
|
} uhdk_window_metrics;
|
|
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_create_async(
|
|
uhdk_app *app,
|
|
const uhdk_window_desc *desc,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API void UHDK_CALL uhdk_window_destroy(uhdk_window *window);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_title_async(
|
|
uhdk_window *window,
|
|
uhdk_text title,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_size_async(
|
|
uhdk_window *window,
|
|
uhdk_size size,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_state_async(
|
|
uhdk_window *window,
|
|
uhdk_window_state state,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_visible_async(
|
|
uhdk_window *window,
|
|
uhdk_bool visible,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_request_focus_async(
|
|
uhdk_window *window,
|
|
uhdk_request_id *out
|
|
); /* OS may decline. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_get_metrics(
|
|
uhdk_window *window,
|
|
uhdk_window_metrics *out
|
|
);
|
|
UHDK_API void UHDK_CALL uhdk_window_invalidate(uhdk_window *window); /* Coalesced redraw event. */
|
|
|
|
/* Optional OpenGL context management (application/render thread).
|
|
* Define UHDK_ENABLE_OPENGL before including this header for bundled Khronos
|
|
* GL types, constants, and PFNGL* function-pointer types. Without that flag,
|
|
* no GL names are introduced.
|
|
*
|
|
* Creation requires UHDK_WINDOW_OPENGL and guarantees desktop OpenGL >= 3.3,
|
|
* core profile, with GLSL >= 3.30. macOS selects its 4.1 core profile because
|
|
* it cannot create an exact 3.3 profile. No legacy or OpenGL ES fallback.
|
|
* Initial framebuffer requirement: double-buffered RGBA8. Depth/stencil buffers
|
|
* are not required or guaranteed. No multisampling or sRGB is requested.
|
|
* Sharing, debug contexts and custom formats are future work.
|
|
*
|
|
* One context per window. Create does NOT change the current context. Explicitly
|
|
* begin_frame locks drawable updates and makes it current; end_frame unlocks.
|
|
* ALL raw GL calls (including initialization and deletion) and presentation must
|
|
* be inside this bracket. Never wait for platform results inside a bracket.
|
|
* make_current/clear_current are also available inside a bracket.
|
|
* Contexts cannot migrate to another thread. Destroy detaches a current context;
|
|
* window destruction also destroys its context and invalidates the handle.
|
|
* Creation failures leave the window valid and release partially created state.
|
|
* Uhdk does not modify viewport/scissor or other application GL state on resize;
|
|
* use WINDOW_METRICS framebuffer dimensions to update these yourself.
|
|
*/
|
|
#if defined(_WIN32)
|
|
#define UHDK_GL_CALL __stdcall
|
|
#else
|
|
#define UHDK_GL_CALL
|
|
#endif
|
|
/* A function pointer, never a data pointer. Cast to the matching Khronos PFNGL*
|
|
* type before calling. GL uses stdcall on Win32; Uhdk exports still use C ABI. */
|
|
typedef void(UHDK_GL_CALL *uhdk_gl_proc)(void);
|
|
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_create_async(
|
|
uhdk_window *window,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_begin_frame(uhdk_gl_context *context);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_end_frame(uhdk_gl_context *context);
|
|
UHDK_API void UHDK_CALL uhdk_gl_context_destroy(uhdk_gl_context *context);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_make_current(uhdk_gl_context *context);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_clear_current(uhdk_app *app);
|
|
/* Actual negotiated version, not the requested minimum. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_get_version(
|
|
uhdk_gl_context *context,
|
|
uint32_t *out_major,
|
|
uint32_t *out_minor
|
|
);
|
|
/* Wayland returns UNAVAILABLE while hidden or awaiting mapping configuration. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_swap_buffers(uhdk_gl_context *context);
|
|
/* Explicitly set 0 (unsynchronized) or 1 (vsync); other values are invalid.
|
|
* No initial interval is guaranteed. Unsupported control returns UNSUPPORTED;
|
|
* compositor/driver policy may override presentation timing. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_set_swap_interval(
|
|
uhdk_gl_context *context,
|
|
int32_t interval
|
|
);
|
|
/* Requires this context current. Accepts pointer+length ASCII GL symbol names.
|
|
* Missing symbols return NOT_FOUND. Pointers are valid until context destruction
|
|
* and must only be used with that context current. A non-NULL pointer alone does
|
|
* not prove extension/version support; check GL version/extension availability.
|
|
* Loads both platform-library exports and driver-provided GL entry points. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_gl_context_get_proc(
|
|
uhdk_gl_context *context,
|
|
uhdk_text name,
|
|
uhdk_gl_proc *out
|
|
);
|
|
|
|
/* Keyboard events are not text. Physical key = USB HID keyboard-page usage;
|
|
* 0 means unknown. Logical key = Unicode scalar, or UHDK_KEY_* below.
|
|
* Modifier bits describe state after the event. Focus loss resets held state.
|
|
* With text input enabled, text/edit events are authoritative for editing;
|
|
* raw key events are observational for those actions (do not insert twice).
|
|
* Registered menu accelerators are dispatched as menu/edit commands instead of
|
|
* raw key events. Unregistered application shortcuts need their own policy.
|
|
*/
|
|
typedef uint32_t uhdk_modifier_flags;
|
|
enum {
|
|
UHDK_MOD_SHIFT = 1u << 0,
|
|
UHDK_MOD_CONTROL = 1u << 1,
|
|
UHDK_MOD_ALT = 1u << 2,
|
|
UHDK_MOD_SUPER = 1u << 3,
|
|
UHDK_MOD_CAPS_LOCK = 1u << 4,
|
|
UHDK_MOD_NUM_LOCK = 1u << 5
|
|
};
|
|
|
|
typedef uint32_t uhdk_key;
|
|
enum {
|
|
UHDK_KEY_UNKNOWN = 0,
|
|
UHDK_KEY_ESCAPE = 0x110000,
|
|
UHDK_KEY_ENTER,
|
|
UHDK_KEY_TAB,
|
|
UHDK_KEY_BACKSPACE,
|
|
UHDK_KEY_DELETE,
|
|
UHDK_KEY_INSERT,
|
|
UHDK_KEY_LEFT,
|
|
UHDK_KEY_RIGHT,
|
|
UHDK_KEY_UP,
|
|
UHDK_KEY_DOWN,
|
|
UHDK_KEY_HOME,
|
|
UHDK_KEY_END,
|
|
UHDK_KEY_PAGE_UP,
|
|
UHDK_KEY_PAGE_DOWN,
|
|
UHDK_KEY_F1 = 0x110100 /* F1..F24 are contiguous. */
|
|
};
|
|
|
|
typedef uint32_t uhdk_pointer_button;
|
|
enum {
|
|
UHDK_BUTTON_NONE = 0,
|
|
UHDK_BUTTON_PRIMARY = 1,
|
|
UHDK_BUTTON_SECONDARY = 2,
|
|
UHDK_BUTTON_MIDDLE = 3,
|
|
UHDK_BUTTON_BACK = 4,
|
|
UHDK_BUTTON_FORWARD = 5
|
|
};
|
|
|
|
typedef uint32_t uhdk_scroll_unit;
|
|
enum {
|
|
UHDK_SCROLL_LOGICAL_PIXELS = 0,
|
|
UHDK_SCROLL_LINES = 1
|
|
};
|
|
|
|
typedef uint32_t uhdk_scroll_phase;
|
|
enum {
|
|
UHDK_SCROLL_DISCRETE = 0,
|
|
UHDK_SCROLL_BEGIN = 1,
|
|
UHDK_SCROLL_UPDATE = 2,
|
|
UHDK_SCROLL_END = 3,
|
|
UHDK_SCROLL_CANCEL = 4
|
|
};
|
|
|
|
typedef uint32_t uhdk_cursor_shape;
|
|
enum {
|
|
UHDK_CURSOR_ARROW = 0,
|
|
UHDK_CURSOR_TEXT,
|
|
UHDK_CURSOR_CROSSHAIR,
|
|
UHDK_CURSOR_HAND,
|
|
UHDK_CURSOR_RESIZE_HORIZONTAL,
|
|
UHDK_CURSOR_RESIZE_VERTICAL,
|
|
UHDK_CURSOR_RESIZE_NW_SE,
|
|
UHDK_CURSOR_RESIZE_NE_SW,
|
|
UHDK_CURSOR_MOVE,
|
|
UHDK_CURSOR_NOT_ALLOWED,
|
|
UHDK_CURSOR_WAIT,
|
|
UHDK_CURSOR_HIDDEN
|
|
};
|
|
|
|
typedef uint32_t uhdk_pointer_mode;
|
|
enum {
|
|
UHDK_POINTER_NORMAL = 0,
|
|
UHDK_POINTER_CAPTURE = 1
|
|
};
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_cursor_shape_async(
|
|
uhdk_window *window,
|
|
uhdk_cursor_shape shape,
|
|
uhdk_request_id *out
|
|
);
|
|
/* Capture delivers selection-drag events outside the window. Focus loss or OS
|
|
* cancellation restores NORMAL and emits POINTER_MODE_CHANGED. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_pointer_mode_async(
|
|
uhdk_window *window,
|
|
uhdk_pointer_mode mode,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* Text offsets/lengths are UTF-8 byte counts, always at scalar boundaries.
|
|
* surrounding_text is a bounded snapshot; document_offset locates it in the
|
|
* document. Selection and replacement ranges are relative to this snapshot.
|
|
* Events are ordered. Apply all edits in order, including edits sharing a base
|
|
* revision; do not discard a burst just because its first edit changed revision.
|
|
* acknowledged_input_id is the last applied text/edit input ID. Snapshots behind
|
|
* outstanding native edits are ignored; publish again after consuming the batch.
|
|
* On macOS, a semantic edit invalidates the native snapshot. Subsequent text
|
|
* input waits for an acknowledging snapshot, including when an edit is ignored.
|
|
* Acknowledge asynchronous edits (such as paste) only once their result is applied.
|
|
* Disabling text input discards deferred input. Raw key IDs are observational;
|
|
* acknowledge applied text/edit events, not raw keys that may precede them.
|
|
* Commit/preedit events carry text + an optional replacement range. A preedit
|
|
* updates temporary composition, never the permanent document by itself.
|
|
*/
|
|
typedef struct uhdk_text_state {
|
|
uint32_t struct_size;
|
|
uint32_t reserved;
|
|
uhdk_text surrounding_text;
|
|
uint64_t revision;
|
|
uint64_t acknowledged_input_id;
|
|
uint64_t document_offset;
|
|
uint64_t selection_start;
|
|
uint64_t selection_len;
|
|
uhdk_rect caret; /* Window-local logical coordinates. */
|
|
} uhdk_text_state;
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_text_input_async(
|
|
uhdk_window *window,
|
|
uhdk_bool enabled,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_text_state(
|
|
uhdk_window *window,
|
|
const uhdk_text_state *state
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_cancel_composition_async(
|
|
uhdk_window *window,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* File references preserve native names, including non-UTF-8 POSIX paths.
|
|
* Display names are UTF-8. URI/native-path export is explicit and owned by the
|
|
* caller's buffer. Windows native path bytes are UTF-16LE (no terminator),
|
|
* POSIX native paths are uninterpreted bytes. Windows URI export returns
|
|
* UNSUPPORTED when the shell cannot represent a native name losslessly (such
|
|
* as unpaired UTF-16 surrogates); native-path export remains available.
|
|
* A reference can carry an access
|
|
* grant; retaining it keeps that grant alive where the OS permits. Persistence
|
|
* across launches/bookmark serialization is deferred to a future extension.
|
|
* Buffer queries: NULL/0 gets required byte count in out_len and returns UHDK_STATUS_OK.
|
|
* Too-small buffers return UHDK_STATUS_BUFFER_TOO_SMALL and required count; no partial copy.
|
|
*/
|
|
typedef uint32_t uhdk_file_representation;
|
|
enum {
|
|
UHDK_FILE_DISPLAY_NAME = 0,
|
|
UHDK_FILE_URI = 1,
|
|
UHDK_FILE_NATIVE_PATH = 2
|
|
};
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_create_from_native_path(
|
|
uhdk_app *app,
|
|
uhdk_bytes path,
|
|
uhdk_file **out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_create_from_uri(
|
|
uhdk_app *app,
|
|
uhdk_text uri,
|
|
uhdk_file **out
|
|
);
|
|
UHDK_API void UHDK_CALL uhdk_file_retain(uhdk_file *file);
|
|
UHDK_API void UHDK_CALL uhdk_file_release(uhdk_file *file);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_copy_representation(
|
|
uhdk_file *file,
|
|
uhdk_file_representation representation,
|
|
uint8_t *buffer,
|
|
uint64_t capacity,
|
|
uint64_t *out_len
|
|
);
|
|
|
|
typedef uint32_t uhdk_file_type;
|
|
enum {
|
|
UHDK_FILE_REGULAR = 1,
|
|
UHDK_FILE_DIRECTORY = 2,
|
|
UHDK_FILE_OTHER = 3
|
|
};
|
|
typedef struct uhdk_file_info {
|
|
uint64_t size_bytes;
|
|
int64_t modified_time_ns; /* Unix epoch, nanoseconds. */
|
|
uhdk_file_type type;
|
|
uint32_t reserved;
|
|
} uhdk_file_info;
|
|
/* FIFO across accepted file requests. Read results are raw bytes, batch-owned.
|
|
* max_bytes is a hard limit; oversized files return BUFFER_TOO_SMALL.
|
|
* Read/write accept regular files only; final-component symlinks are rejected.
|
|
* Write copies bytes at submission, stages an exclusive same-directory temp,
|
|
* preserves POSIX mode of an existing regular file, then renames atomically.
|
|
* Windows rejects read-only destinations; replacement gets the directory's
|
|
* inherited permissions and does not preserve other destination attributes.
|
|
* Symlinks/nonregular destinations are rejected. ACLs/xattrs/ownership are not
|
|
* preserved; replacement requires a directory writable by the current user.
|
|
* New POSIX files use mode 0600. No power-loss durability or conflict detection promise.
|
|
* No silent truncate fallback. Cancellation before rename leaves the target intact.
|
|
*/
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_read_all_async(
|
|
uhdk_file *file,
|
|
uint64_t max_bytes,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_write_all_async(
|
|
uhdk_file *file,
|
|
uhdk_bytes bytes,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_get_info_async(uhdk_file *file, uhdk_request_id *out);
|
|
|
|
typedef uint32_t uhdk_dialog_kind;
|
|
enum {
|
|
UHDK_DIALOG_OPEN_FILE = 0,
|
|
UHDK_DIALOG_OPEN_FILES = 1,
|
|
UHDK_DIALOG_OPEN_DIRECTORY = 2,
|
|
UHDK_DIALOG_SAVE_FILE = 3
|
|
};
|
|
|
|
typedef struct uhdk_file_filter {
|
|
uhdk_text label;
|
|
uhdk_text_list extensions; /* Without dots; empty means all files. */
|
|
} uhdk_file_filter;
|
|
|
|
typedef struct uhdk_file_dialog_desc {
|
|
uint32_t struct_size;
|
|
uhdk_dialog_kind kind;
|
|
uhdk_window *parent;
|
|
uhdk_text title;
|
|
uhdk_text accept_label;
|
|
uhdk_text suggested_name; /* Empty = native default. */
|
|
uhdk_file *initial_directory;
|
|
const uhdk_file_filter *filters;
|
|
uint64_t filters_len;
|
|
} uhdk_file_dialog_desc;
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_file_dialog_show_async(
|
|
uhdk_app *app,
|
|
const uhdk_file_dialog_desc *desc,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* Plain-text clipboard only. Writes copy UTF-8 before returning; empty text is
|
|
* valid. Reads negotiate native text formats internally and complete with text
|
|
* borrowed for the event batch lifetime. NOT_FOUND means no text format.
|
|
* max_bytes bounds the UTF-8 result; excess returns BUFFER_TOO_SMALL, never a
|
|
* truncated string. A read remains async even when a backend can read instantly.
|
|
*/
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_clipboard_write_text_async(
|
|
uhdk_app *app,
|
|
uhdk_text text,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_clipboard_read_text_async(
|
|
uhdk_app *app,
|
|
uint64_t max_bytes,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* Incoming file drops only. When enabled, Uhdk negotiates copy-only file drops
|
|
* and emits DROP_FILES with borrowed file references plus the drop position.
|
|
* Retain references to use beyond the event batch lifetime. Directory references are allowed;
|
|
* the application decides whether to open them. No source deletion, outgoing
|
|
* drag, data offers, or application-visible drop-completion transaction.
|
|
*/
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_drop_enabled_async(
|
|
uhdk_window *window,
|
|
uhdk_bool enabled,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* Menus are immutable snapshots. Command IDs are application-assigned, nonzero
|
|
* and unique within a menu tree. Shortcuts use logical keys + modifiers.
|
|
* Created menus have one reference; attached menus are retained internally.
|
|
* Retain/release manage references; the final release destroys the menu.
|
|
*/
|
|
typedef uint32_t uhdk_menu_role;
|
|
enum {
|
|
UHDK_MENU_ROLE_NONE = 0,
|
|
UHDK_MENU_ROLE_ABOUT,
|
|
UHDK_MENU_ROLE_QUIT,
|
|
UHDK_MENU_ROLE_COPY,
|
|
UHDK_MENU_ROLE_CUT,
|
|
UHDK_MENU_ROLE_PASTE,
|
|
UHDK_MENU_ROLE_SELECT_ALL,
|
|
UHDK_MENU_ROLE_UNDO,
|
|
UHDK_MENU_ROLE_REDO
|
|
};
|
|
|
|
typedef uint32_t uhdk_menu_flags;
|
|
enum {
|
|
UHDK_MENU_DISABLED = 1u << 0,
|
|
UHDK_MENU_CHECKED = 1u << 1,
|
|
UHDK_MENU_SEPARATOR = 1u << 2
|
|
};
|
|
|
|
typedef struct uhdk_menu_item {
|
|
uint64_t command_id;
|
|
uhdk_text label;
|
|
uhdk_menu_flags flags;
|
|
uhdk_menu_role role;
|
|
uhdk_key shortcut_key;
|
|
uhdk_modifier_flags shortcut_modifiers;
|
|
uhdk_menu *submenu; /* Retained by the created parent menu. */
|
|
} uhdk_menu_item;
|
|
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_menu_create(
|
|
uhdk_app *app,
|
|
const uhdk_menu_item *items,
|
|
uint64_t len,
|
|
uhdk_menu **out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_menu_set_item_flags_async(
|
|
uhdk_menu *menu,
|
|
uint64_t command_id,
|
|
uhdk_menu_flags flags,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API void UHDK_CALL uhdk_menu_retain(uhdk_menu *menu);
|
|
UHDK_API void UHDK_CALL uhdk_menu_release(uhdk_menu *menu);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_set_menu_async(
|
|
uhdk_app *app,
|
|
uhdk_menu *menu,
|
|
uhdk_request_id *out
|
|
); /* NULL clears. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_set_menu_async(
|
|
uhdk_window *window,
|
|
uhdk_menu *menu,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_menu_popup_async(
|
|
uhdk_menu *menu,
|
|
uhdk_window *window,
|
|
uhdk_point position,
|
|
uhdk_request_id *out
|
|
);
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_set_icon_async(
|
|
uhdk_app *app,
|
|
const uhdk_image *image,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
/* Successful shell completion means handed off to the OS, not that a target
|
|
* application finished loading. URLs are not shell command strings. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_shell_open_url_async(
|
|
uhdk_app *app,
|
|
uhdk_text url,
|
|
uhdk_request_id *out
|
|
);
|
|
|
|
typedef uint32_t uhdk_change_flags;
|
|
enum {
|
|
UHDK_CHANGE_CREATED = 1u << 0,
|
|
UHDK_CHANGE_REMOVED = 1u << 1,
|
|
UHDK_CHANGE_CONTENT = 1u << 2,
|
|
UHDK_CHANGE_METADATA = 1u << 3,
|
|
UHDK_CHANGE_RENAMED = 1u << 4,
|
|
UHDK_CHANGE_RESCAN_REQUIRED = 1u << 5,
|
|
UHDK_CHANGE_ROOT_INVALIDATED = 1u << 6
|
|
};
|
|
/* Watch a document path or a directory's immediate children; never recursive.
|
|
* Document watches follow the named path across atomic-save replacement, using
|
|
* parent-directory observation where needed. Removal emits REMOVED; subsequent
|
|
* recreation emits CREATED. If observation can no longer continue (for example,
|
|
* parent removal), emit ROOT_INVALIDATED and let the app recreate the watch.
|
|
* Changes may coalesce and are hints, not a transaction log. Renames may arrive
|
|
* as remove/create; no rename pairing is promised. RESCAN_REQUIRED means inspect
|
|
* current state. Pending notifications are suppressed after destroy; already borrowed batches remain valid. */
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_watch_create_async(uhdk_file *root, uhdk_request_id *out);
|
|
UHDK_API void UHDK_CALL uhdk_watch_destroy(uhdk_watch *watch);
|
|
|
|
typedef uint32_t uhdk_appearance;
|
|
enum {
|
|
UHDK_APPEARANCE_UNKNOWN = 0,
|
|
UHDK_APPEARANCE_LIGHT = 1,
|
|
UHDK_APPEARANCE_DARK = 2
|
|
};
|
|
|
|
typedef struct uhdk_preferences {
|
|
uint32_t struct_size;
|
|
uhdk_appearance appearance;
|
|
uhdk_bool reduced_motion;
|
|
uhdk_bool high_contrast;
|
|
} uhdk_preferences;
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_app_get_preferences(uhdk_app *app, uhdk_preferences *out);
|
|
|
|
/* Event payloads. Window is NULL for app-wide events. time_ns is monotonic time
|
|
* relative to app creation, not wall time. Do not persist event pointers.
|
|
* Destroying a window suppresses queued window input/redraw events and cancels
|
|
* its requests. REQUEST_DONE never includes a dangling window pointer.
|
|
*/
|
|
typedef uint32_t uhdk_event_type;
|
|
enum {
|
|
UHDK_EVENT_READY = 1,
|
|
UHDK_EVENT_STOPPED,
|
|
UHDK_EVENT_WAKE,
|
|
UHDK_EVENT_QUIT_REQUESTED,
|
|
UHDK_EVENT_APP_ACTIVATION,
|
|
UHDK_EVENT_OPEN_FILES,
|
|
UHDK_EVENT_PREFERENCES_CHANGED,
|
|
UHDK_EVENT_WINDOW_CLOSE_REQUESTED,
|
|
UHDK_EVENT_WINDOW_METRICS,
|
|
UHDK_EVENT_WINDOW_REDRAW,
|
|
UHDK_EVENT_KEY,
|
|
UHDK_EVENT_POINTER_ENTER,
|
|
UHDK_EVENT_POINTER_LEAVE,
|
|
UHDK_EVENT_POINTER_MOVE,
|
|
UHDK_EVENT_POINTER_BUTTON,
|
|
UHDK_EVENT_POINTER_MODE_CHANGED,
|
|
UHDK_EVENT_SCROLL,
|
|
UHDK_EVENT_TEXT_COMMIT,
|
|
UHDK_EVENT_TEXT_PREEDIT,
|
|
UHDK_EVENT_TEXT_COMPOSITION_END,
|
|
UHDK_EVENT_EDIT_COMMAND,
|
|
UHDK_EVENT_MENU_COMMAND,
|
|
UHDK_EVENT_DROP_FILES,
|
|
UHDK_EVENT_WATCH,
|
|
UHDK_EVENT_REQUEST_DONE
|
|
};
|
|
|
|
typedef uint32_t uhdk_request_kind;
|
|
enum {
|
|
UHDK_REQUEST_FILE_DIALOG = 1,
|
|
UHDK_REQUEST_CLIPBOARD_TEXT,
|
|
UHDK_REQUEST_MENU_POPUP,
|
|
UHDK_REQUEST_SHELL,
|
|
UHDK_REQUEST_COMMAND,
|
|
UHDK_REQUEST_WINDOW,
|
|
UHDK_REQUEST_GL_CONTEXT,
|
|
UHDK_REQUEST_WATCH,
|
|
UHDK_REQUEST_FILE_READ,
|
|
UHDK_REQUEST_FILE_WRITE,
|
|
UHDK_REQUEST_FILE_INFO
|
|
};
|
|
|
|
/* Semantic requests, not edits performed by UHDK. The application owns text,
|
|
* grapheme/word boundaries, bidi/layout, selection, clipboard actions and history.
|
|
* LEFT/RIGHT are visual; BACKWARD/FORWARD follow logical document order.
|
|
* LINE uses visual lines; LEFT_END/RIGHT_END explicitly select their visual edge.
|
|
* LINE_START/END follow writing direction; PARAGRAPH uses document boundaries.
|
|
* PAGE moves the caret by a viewport; SCROLL moves the viewport without the caret.
|
|
* Deletion first removes the selection; otherwise it removes the indicated unit.
|
|
* NEWLINE requests a paragraph separator; LINE_BREAK requests a soft line break.
|
|
* TAB/BACKTAB may insert text or traverse focus, as decided by the application.
|
|
* CANCEL is delivered only after native composition handling declines/finishes it.
|
|
* Native default gestures vary: macOS uses AppKit selectors, Windows/Wayland
|
|
* use Ctrl-based editing defaults. Commands without customary platform gestures
|
|
* remain application-bindable intents, not invented global shortcuts. */
|
|
typedef uint32_t uhdk_edit_command;
|
|
enum {
|
|
UHDK_EDIT_COPY = 1,
|
|
UHDK_EDIT_CUT,
|
|
UHDK_EDIT_PASTE,
|
|
UHDK_EDIT_SELECT_ALL,
|
|
UHDK_EDIT_UNDO,
|
|
UHDK_EDIT_REDO,
|
|
UHDK_EDIT_DELETE_BACKWARD,
|
|
UHDK_EDIT_DELETE_FORWARD,
|
|
UHDK_EDIT_MOVE_LEFT,
|
|
UHDK_EDIT_MOVE_RIGHT,
|
|
UHDK_EDIT_MOVE_UP,
|
|
UHDK_EDIT_MOVE_DOWN,
|
|
UHDK_EDIT_LINE_START,
|
|
UHDK_EDIT_LINE_END,
|
|
UHDK_EDIT_DOCUMENT_START,
|
|
UHDK_EDIT_DOCUMENT_END,
|
|
UHDK_EDIT_WORD_LEFT,
|
|
UHDK_EDIT_WORD_RIGHT,
|
|
UHDK_EDIT_NEWLINE,
|
|
UHDK_EDIT_TAB,
|
|
UHDK_EDIT_BACKTAB,
|
|
UHDK_EDIT_LINE_BREAK,
|
|
UHDK_EDIT_CANCEL,
|
|
UHDK_EDIT_DELETE_WORD_BACKWARD,
|
|
UHDK_EDIT_DELETE_WORD_FORWARD,
|
|
UHDK_EDIT_DELETE_LINE_START,
|
|
UHDK_EDIT_DELETE_LINE_END,
|
|
UHDK_EDIT_DELETE_PARAGRAPH_START,
|
|
UHDK_EDIT_DELETE_PARAGRAPH_END,
|
|
UHDK_EDIT_MOVE_BACKWARD,
|
|
UHDK_EDIT_MOVE_FORWARD,
|
|
UHDK_EDIT_WORD_BACKWARD,
|
|
UHDK_EDIT_WORD_FORWARD,
|
|
UHDK_EDIT_PARAGRAPH_START,
|
|
UHDK_EDIT_PARAGRAPH_END,
|
|
UHDK_EDIT_PAGE_UP,
|
|
UHDK_EDIT_PAGE_DOWN,
|
|
UHDK_EDIT_SCROLL_PAGE_UP,
|
|
UHDK_EDIT_SCROLL_PAGE_DOWN,
|
|
UHDK_EDIT_SCROLL_DOCUMENT_START,
|
|
UHDK_EDIT_SCROLL_DOCUMENT_END,
|
|
UHDK_EDIT_LINE_LEFT_END,
|
|
UHDK_EDIT_LINE_RIGHT_END
|
|
};
|
|
|
|
/* Event data is a pointer to the named payload type selected by type.
|
|
* All payloads are immutable and naturally aligned. data_size is the payload
|
|
* size in bytes; check it before accessing fields introduced by newer versions.
|
|
* Payload-free events have NULL data and data_size == 0. Unknown types may be
|
|
* ignored. Event envelopes have a fixed stride within each returned batch.
|
|
*/
|
|
typedef struct uhdk_key_event {
|
|
uint32_t physical_key;
|
|
uhdk_key logical_key;
|
|
uhdk_modifier_flags modifiers;
|
|
uhdk_bool pressed;
|
|
uhdk_bool repeat;
|
|
} uhdk_key_event;
|
|
|
|
typedef struct uhdk_pointer_event {
|
|
uhdk_point position;
|
|
uhdk_point delta; /* delta uses logical units. */
|
|
uhdk_pointer_button button;
|
|
uhdk_modifier_flags modifiers;
|
|
uhdk_bool pressed;
|
|
uint32_t click_count;
|
|
} uhdk_pointer_event;
|
|
|
|
typedef struct uhdk_scroll_event {
|
|
uhdk_point position;
|
|
uhdk_point delta; /* Positive scroll = toward right/bottom. */
|
|
uhdk_scroll_unit unit;
|
|
uhdk_scroll_phase phase;
|
|
uhdk_modifier_flags modifiers;
|
|
uhdk_bool momentum;
|
|
} uhdk_scroll_event;
|
|
|
|
typedef struct uhdk_text_event {
|
|
uhdk_text text;
|
|
uint64_t revision;
|
|
uhdk_bool has_replacement;
|
|
uint32_t reserved;
|
|
uint64_t replacement_start;
|
|
uint64_t replacement_len;
|
|
uint64_t selection_start;
|
|
uint64_t selection_len; /* Within preedit text. */
|
|
} uhdk_text_event;
|
|
|
|
typedef struct uhdk_edit_event {
|
|
uhdk_edit_command command;
|
|
uhdk_bool extend_selection; /* Only meaningful for caret movement. */
|
|
} uhdk_edit_event;
|
|
|
|
typedef struct uhdk_drop_files_event {
|
|
uhdk_file_list files;
|
|
uhdk_point position;
|
|
} uhdk_drop_files_event;
|
|
|
|
typedef struct uhdk_menu_event {
|
|
uint64_t command_id;
|
|
} uhdk_menu_event;
|
|
|
|
typedef struct uhdk_watch_event {
|
|
uhdk_watch *watch;
|
|
uhdk_change_flags flags;
|
|
uhdk_status status; /* Non-OK: watch failure; rescan/recreate as needed. */
|
|
uhdk_file *file; /* Nullable when only the watched root is known. */
|
|
} uhdk_watch_event;
|
|
|
|
typedef struct uhdk_activation_event {
|
|
uhdk_bool active;
|
|
} uhdk_activation_event;
|
|
typedef struct uhdk_pointer_mode_event {
|
|
uhdk_pointer_mode mode;
|
|
} uhdk_pointer_mode_event;
|
|
typedef struct uhdk_window_result {
|
|
uhdk_window *window;
|
|
} uhdk_window_result;
|
|
typedef struct uhdk_gl_context_result {
|
|
uhdk_gl_context *gl_context;
|
|
} uhdk_gl_context_result;
|
|
typedef struct uhdk_watch_result {
|
|
uhdk_watch *watch;
|
|
} uhdk_watch_result;
|
|
|
|
/* Request data mapping (only valid on UHDK_STATUS_OK):
|
|
* FILE_DIALOG: uhdk_file_list; CLIPBOARD_TEXT: uhdk_text;
|
|
* WINDOW: uhdk_window_result; GL_CONTEXT: uhdk_gl_context_result;
|
|
* WATCH: uhdk_watch_result; FILE_READ: uhdk_bytes; FILE_INFO: uhdk_file_info.
|
|
* SHELL, COMMAND, FILE_WRITE, MENU_POPUP and failures have NULL/0 data.
|
|
*/
|
|
typedef struct uhdk_request_result {
|
|
uhdk_request_id id;
|
|
uhdk_request_kind kind;
|
|
uhdk_status status;
|
|
uhdk_text diagnostic; /* Optional; for humans, never parse for logic. */
|
|
const void *data;
|
|
uint64_t data_size;
|
|
} uhdk_request_result;
|
|
|
|
/* Event data mapping:
|
|
* APP_ACTIVATION: uhdk_activation_event; OPEN_FILES: uhdk_file_list;
|
|
* WINDOW_METRICS: uhdk_window_metrics; PREFERENCES_CHANGED: uhdk_preferences;
|
|
* KEY: uhdk_key_event; POINTER_ENTER/LEAVE/MOVE/BUTTON: uhdk_pointer_event;
|
|
* POINTER_MODE_CHANGED: uhdk_pointer_mode_event; SCROLL: uhdk_scroll_event;
|
|
* TEXT_COMMIT/PREEDIT: uhdk_text_event; EDIT_COMMAND: uhdk_edit_event;
|
|
* DROP_FILES: uhdk_drop_files_event; MENU_COMMAND: uhdk_menu_event;
|
|
* WATCH: uhdk_watch_event; REQUEST_DONE: uhdk_request_result.
|
|
* All other events have NULL/0 data.
|
|
*/
|
|
struct uhdk_event {
|
|
uint32_t struct_size;
|
|
uhdk_event_type type;
|
|
uint64_t time_ns;
|
|
uint64_t input_id; /* Correlates raw key and native edit/text; zero for non-input. */
|
|
uhdk_window *window;
|
|
const void *data;
|
|
uint64_t data_size;
|
|
};
|
|
|
|
/* Lifecycle policy: close/quit requests are advisory. Destroy the window or call
|
|
* uhdk_app_quit() to accept; otherwise the application stays alive. Closing the
|
|
* last window does not automatically quit. App destruction invalidates ALL child
|
|
* handles, including retained files/menus; callers must stop other threads from
|
|
* waking the app first. Native menu roles produce EDIT_COMMAND/QUIT_REQUESTED
|
|
* where applicable; custom menu items produce MENU_COMMAND. A popup selection
|
|
* delivers its command event first and REQUEST_DONE afterward; process the
|
|
* command only once. Popup dismissal completes as UHDK_STATUS_CANCELLED.
|
|
*
|
|
* Boundaries: no widget/layout engine, text rasterizer, high-level renderer,
|
|
* networking, process spawning, global input hooks, or streaming filesystem API.
|
|
* Deferred: generic clipboard data, outgoing drag/drop, custom cursors, relative
|
|
* pointer input, transparent windows, display enumeration/positioning, tray items,
|
|
* badges/progress/attention, recursive watching, accent colors, accessibility
|
|
* semantic trees, notifications, persistent access bookmarks and streaming data.
|
|
*/
|
|
|
|
#ifdef UHDK_ENABLE_NATIVE
|
|
/* Experimental platform escape hatch; native handles may require OS headers. */
|
|
/* Platform escape hatch. Returned handles are borrowed and must not be released.
|
|
* macOS: primary=NSWindow*, secondary=NSView*; Windows: primary=HWND.
|
|
* Wayland: primary=wl_display*, secondary=wl_surface*.
|
|
* X11: primary=Display*, value=XID. Lifetime ends with the Uhdk window.
|
|
* With UHDK_WINDOW_OPENGL, Uhdk owns drawable setup; do not replace its native
|
|
* view/surface or pixel format. Otherwise the external renderer owns setup.
|
|
* Borrowing a handle does not change platform threading rules: AppKit window
|
|
* and view operations still belong on the macOS main thread.
|
|
*/
|
|
typedef struct uhdk_native_window {
|
|
uint32_t struct_size;
|
|
uhdk_backend backend;
|
|
void *primary;
|
|
void *secondary;
|
|
uint64_t value;
|
|
} uhdk_native_window;
|
|
UHDK_API uhdk_status UHDK_CALL uhdk_window_get_native(uhdk_window *window, uhdk_native_window *out);
|
|
#endif /* UHDK_ENABLE_NATIVE */
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
#ifdef UHDK_ENABLE_OPENGL
|
|
/* GLAD 2: OpenGL 3.3 core, no extensions, explicit per-context function table.
|
|
* Do not combine with platform GL headers or GL/glcorearb.h.
|
|
* The loader implementation is linked into libuhdk; consumers must not define
|
|
* GLAD_GL_IMPLEMENTATION when linking that library.
|
|
* Load a GladGLContext via gladLoadGLContextUserPtr and an adapter calling
|
|
* uhdk_gl_context_get_proc, inside a begin_frame/end_frame bracket. Keep one
|
|
* table per context and use it only while that context is current.
|
|
*/
|
|
#if defined(UHDK_SHARED)
|
|
#define GLAD_API_CALL_EXPORT
|
|
#endif
|
|
#include "glad/gl.h"
|
|
#endif /* UHDK_ENABLE_OPENGL */
|
|
|
|
#endif /* UHDK_H_INCLUDED */
|