summaryrefslogtreecommitdiff
path: root/include/yasl/yasl.h
blob: 284039ae3eca0ab7d8aa0d9461f2f34d886dc368 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/** @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>
#include "yasl/keycodes.h"
#if defined(__GNUC__)
#define YASL_API __attribute__((visibility("default")))
#else
#define YASL_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
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_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_pointer_mode { YASL_POINTER_NORMAL, YASL_POINTER_RELATIVE };
enum yasl_button {
    YASL_BUTTON_PRIMARY,
    YASL_BUTTON_MIDDLE,
    YASL_BUTTON_SECONDARY,
    YASL_BUTTON_BACK,
    YASL_BUTTON_FORWARD
};
#define YASL_BUTTON_BIT(button) (1u << (button))
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_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;
};

/** Read the union member named by type. Strings stay valid until the next wait.
 * CLOSE: the user closed this window. QUIT: the system asked the app to quit.
 * WINDOW: size, scale or state changed. REFRESH: draw now; sent once the window
 * has a size, after every resize and when the system needs the contents again.
 * INPUT_RESET: forget held keys, buttons and strokes. DROP: external data over
 * the window, delivered as DATA. DRAG: another YASL surface dragged over.
 * DISPLAY_LOST: the display server went away. Destroy Vulkan surfaces and GL
 * objects now; windows stay valid. Wayland reconnects, then sends DISPLAY_RESTORED:
 * recreate them (GL contexts are new and must be bound again). Elsewhere loss is
 * final and later waits fail. */
struct yasl_event {
    enum yasl_event_type type;
    yasl_surface *surface;
    uint64_t time_ns;
    union {
        struct yasl_window_payload window;
        struct yasl_key_payload key;
        struct yasl_text_payload text;
        struct yasl_pointer_payload pointer;
        struct yasl_scroll_payload scroll;
        struct yasl_pen_payload pen;
        struct yasl_composition_payload composition;
        struct yasl_text_edit_payload text_edit;
        struct yasl_clipboard_payload clipboard;
        /** DATA carries a text/uri-list for yasl_drop_next_path; x/y are set for OVER. */
        struct yasl_drop_payload drop;
        struct yasl_drag_payload drag;
    };
};
/** 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);
/** 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 double yasl_surface_get_scale(const yasl_surface *surface);
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 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 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 int yasl_surface_set_text_input(yasl_surface *surface, bool active,
                                         enum yasl_text_purpose purpose);
/** UTF-8; selection offsets are bytes. */
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
}
#endif
#endif