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
|
/**
* @file
* Unified application runner, event pipeline, and presentation context.
*
* Implements the inverted lifecycle architecture for modern cross-platform
* applications (games, IDEs, and desktop tools). Instead of managing manual
* dispatch/poll/flush pumps, the application provides event and frame callbacks
* to yasl_run(), which drives platform runloops, display pacing, and live resizing.
*/
#ifndef YASL_APP_H
#define YASL_APP_H
#include "yasl/yasl.h"
#include "yasl/loop.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Application callback return status. */
typedef enum yasl_app_result {
YASL_APP_CONTINUE = 0, /**< Continue running the application. */
YASL_APP_QUIT, /**< Request graceful termination of yasl_run(). */
} yasl_app_result;
/** Pacing mode governing when frame() callbacks are invoked. */
typedef enum yasl_pacing_mode {
/**
* Reactive / on-demand presentation (ideal for IDEs, text editors, tools).
* The application sleeps at 0% CPU when idle. frame() is only invoked when
* explicitly requested via yasl_surface_request_frame() or upon OS window
* expose/resize events.
*/
YASL_PACING_ON_DEMAND = 0,
/**
* Continuous vsync-aligned tick (ideal for game engines and animations).
* frame() is driven continuously at the display's native refresh rate
* (e.g. 60/120/144 Hz) via DisplayLink, Wayland frame callbacks, or loop timers.
*/
YASL_PACING_CONTINUOUS,
} yasl_pacing_mode;
/** Mouse capture and virtualization modes. */
typedef enum yasl_mouse_mode {
YASL_MOUSE_NORMAL = 0, /**< Standard visible pointer. */
YASL_MOUSE_HIDDEN, /**< Hidden cursor, normal bounded window coordinates. */
YASL_MOUSE_RELATIVE, /**< Relative pointer lock: cursor hidden, unbounded deltas. */
} yasl_mouse_mode;
/** Unified event types delivered to the application event callback. */
typedef enum yasl_event_type {
YASL_EVENT_NONE = 0,
/* Input events */
YASL_EVENT_KEY,
YASL_EVENT_TEXT,
YASL_EVENT_MOUSE_BUTTON,
YASL_EVENT_MOUSE_MOTION,
YASL_EVENT_MOUSE_SCROLL,
YASL_EVENT_MOUSE_LEAVE,
/* Window lifecycle events */
YASL_EVENT_WINDOW_RESIZE,
YASL_EVENT_WINDOW_SCALE_CHANGED,
YASL_EVENT_WINDOW_CLOSE_REQUEST,
YASL_EVENT_WINDOW_FOCUS,
/* System & external events */
YASL_EVENT_PASTE,
YASL_EVENT_DROP_FILES,
YASL_EVENT_USER,
} yasl_event_type;
/** Unified event payload delivered to yasl_app_desc.event(). */
struct yasl_event {
struct yasl_surface *surface; /**< Associated surface, or NULL for display-wide events. */
yasl_event_type type;
union {
struct {
enum yasl_key key;
enum yasl_key_action action;
uint32_t mods;
uint32_t codepoint;
uint32_t shifted;
uint32_t native_code;
bool repeat; /**< true if this press is generated by OS autorepeat. */
} key;
struct {
const char *text; /**< UTF-8 text string; borrowed for callback duration. */
size_t len; /**< Length in bytes excluding terminating NUL. */
} text;
struct {
struct yasl_vector2i pos; /**< Device-pixel position relative to surface. */
int16_t button; /**< 0 primary, 1 middle, 2 secondary. */
bool pressed; /**< true for press, false for release. */
uint32_t mods;
struct yasl_pointer_pen pen;
} mouse_button;
struct {
struct yasl_vector2i pos; /**< Device-pixel position relative to surface. */
struct yasl_vector2i delta; /**< Relative motion delta (dx, dy). */
uint32_t mods;
struct yasl_pointer_pen pen;
} mouse_motion;
struct {
struct yasl_vector2i pos;
struct yasl_vector2d scroll; /**< Fractional line units; positive right/down. */
uint32_t mods;
} mouse_scroll;
struct {
struct yasl_vector2i size; /**< Configured content extent in device pixels. */
uint32_t scale_120;
} resize;
struct {
uint32_t scale_120;
struct yasl_vector2i size;
} scale;
struct {
bool focused;
} focus;
struct {
const char *text; /**< UTF-8 text from clipboard. */
size_t len;
} paste;
struct {
const char *files; /**< NUL-terminated text/uri-list. */
size_t len;
} drop_files;
struct {
uint32_t type; /**< Application-defined message type. */
void *payload; /**< User-defined payload pointer. */
size_t size; /**< Optional payload size. */
} user;
};
};
/** Frame context provided to yasl_app_desc.frame() during presentation. */
struct yasl_frame_context {
struct yasl_surface *surface;
uint64_t frame_index;
uint64_t target_time_ns; /**< Monotonic timestamp aligned to display refresh. */
struct yasl_vector2i size; /**< Surface content size in device pixels. */
uint32_t scale_120;
/** CPU software rendering target, if surface was created for CPU blitting. */
struct {
uint32_t *pixels; /**< Writable premultiplied 0xAARRGGBB device pixels. */
int stride_bytes; /**< Row stride in bytes. */
} cpu;
/** Native GPU rendering layer/surface, if surface was created for GPU rendering. */
struct {
void *native_layer; /**< CAMetalLayer* on Cocoa, wl_surface* on Wayland, Window on X11. */
} gpu;
/** Internal handle used by yasl_frame_present_cpu. Applications must not touch. */
void *internal_handle;
};
/**
* Present CPU software target pixels.
* @param ctx Active frame context passed to yasl_app_desc.frame().
* @param dirty_rects Optional array of damaged rectangles in device pixels.
* Pass NULL or count <= 0 to indicate full-surface damage.
* @param count Number of rectangles in dirty_rects.
* @return true if accepted, false on presentation failure.
*/
YASL_API bool yasl_frame_present_cpu(struct yasl_frame_context *ctx,
const struct yasl_rect2i *dirty_rects,
int count);
/**
* Configure the presentation pacing mode for a surface.
* @param s Surface.
* @param mode YASL_PACING_ON_DEMAND for reactive UI, YASL_PACING_CONTINUOUS for games.
*/
YASL_API void yasl_surface_set_pacing(struct yasl_surface *s, yasl_pacing_mode mode);
/**
* Mark a surface as needing a redraw on the next frame pass.
* Wakes the event loop if sleeping under YASL_PACING_ON_DEMAND.
* @param s Surface.
*/
YASL_API void yasl_surface_request_frame(struct yasl_surface *s);
/**
* Configure mouse pointer capture / virtualization mode.
* @param s Surface.
* @param mode Normal, hidden, or relative pointer lock.
*/
YASL_API void yasl_surface_set_mouse_mode(struct yasl_surface *s, yasl_mouse_mode mode);
/**
* Safely post a custom user event to the main event loop from ANY thread.
* Wakes the display loop and delivers YASL_EVENT_USER to the event callback.
* @param d Display.
* @param s Optional target surface, or NULL.
* @param user_type Application-defined message type.
* @param payload Arbitrary pointer passed through to the event.
* @param size Optional payload size.
* @return true if queued successfully, false if queue is full or memory failed.
*/
YASL_API bool yasl_post_event(struct yasl_display *d, struct yasl_surface *s,
uint32_t user_type, void *payload, size_t size);
/**
* Watch an open file descriptor or socket for poll-style readiness in the main loop.
* @param d Display.
* @param fd Open file descriptor (e.g. LSP stdout pipe or socket).
* @param poll_events Poll bitmask (e.g. POLLIN, POLLOUT).
* @param cb Readiness callback run on the main thread.
* @param ud Userdata.
* @return Positive watch ID, or -1 on failure.
*/
YASL_API int yasl_app_watch_fd(struct yasl_display *d, int fd, short poll_events,
int (*cb)(int fd, short revents, void *ud), void *ud);
/**
* Unregister a file watch.
* @param d Display.
* @param watch_id Watch ID returned by yasl_app_watch_fd().
*/
YASL_API void yasl_app_unwatch_fd(struct yasl_display *d, int watch_id);
/**
* Schedule a repeating or one-shot timer on the display's event loop.
* @param d Display.
* @param interval_ns Delay in monotonic nanoseconds.
* @param cb Callback returning next interval in nanoseconds, or 0 to stop.
* @param ud Userdata.
* @return Positive timer ID, or 0 on failure.
*/
YASL_API yasl_timer_id yasl_app_add_timer(struct yasl_display *d, uint64_t interval_ns,
yasl_timer_cb cb, void *ud);
/**
* Cancel an active timer.
* @param d Display.
* @param id Timer ID returned by yasl_app_add_timer().
*/
YASL_API void yasl_app_del_timer(struct yasl_display *d, yasl_timer_id id);
/** Application callbacks descriptor passed to yasl_run(). */
struct yasl_app_desc {
/** Application identifier, e.g. "org.example.app". */
const char *app_id;
/** Desired backend; YASL_BACKEND_AUTO chooses native with fallback. */
enum yasl_backend backend;
/** User data passed to all callbacks. */
void *userdata;
/**
* Called once after display and event machinery initialization.
* Use this to create windows and initialize application resources.
* Return YASL_APP_CONTINUE or YASL_APP_QUIT.
*/
int (*init)(void *ud, struct yasl_display *d);
/**
* Unified event handler called for input, resize, close, scale, and custom events.
* Event payloads and borrowed strings are valid for the duration of the callback.
* Return YASL_APP_CONTINUE or YASL_APP_QUIT.
*/
int (*event)(void *ud, const struct yasl_event *ev);
/**
* Invoked when a surface needs to present a frame.
* Synchronized automatically with display pacing and live window resizing.
*/
void (*frame)(void *ud, struct yasl_surface *s, struct yasl_frame_context *ctx);
/**
* Called right before the display is closed and yasl_run() exits.
* Destroy remaining surfaces and release application resources here.
*/
void (*quit)(void *ud, struct yasl_display *d);
};
/**
* Run the application with the inverted lifecycle runner.
* Handles the display event loop, live-resizing, pacing, and cleanup.
* @param desc Application callbacks and options.
* @return 0 on orderly exit, or non-zero on error.
*/
YASL_API int yasl_run(const struct yasl_app_desc *desc);
#ifdef __cplusplus
}
#endif
#endif /* YASL_APP_H */
|