summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/yasl/app.h297
1 files changed, 297 insertions, 0 deletions
diff --git a/include/yasl/app.h b/include/yasl/app.h
new file mode 100644
index 0000000..91de019
--- /dev/null
+++ b/include/yasl/app.h
@@ -0,0 +1,297 @@
+/**
+ * @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_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 *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 */