/** * @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_ERROR, /**< Request orderly cleanup and a failing run result. */ } yasl_app_result; /** Migration adapter; prefer yasl_frame_present() from yasl.h. */ YASL_API bool yasl_frame_present_cpu(struct yasl_frame *frame, const struct yasl_rect2i *dirty_rects, int count); /** * 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 code Application-defined message code (yasl_user_event.code). * @param payload Arbitrary pointer passed through to the event. * @param size Optional payload size. * @return true if queued; false if memory failed or d is not run by yasl_run(). * Migration adapter: keep s alive through the call, and stop producers before * shutdown. Prefer yasl_display_post() with a captured ID and release callback * in either loop style; legacy payloads have no cancellation cleanup. */ YASL_API bool yasl_post_event(struct yasl_display *d, struct yasl_surface *s, uint32_t code, 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; /** * Optional toplevel created before init(), with its first frame requested. * Borrowed for the call; spec cbs and ud are ignored as for any runner window. * yasl_run() returns an error without calling init() if creation fails. */ const struct yasl_window_spec *window; /** * Optional; called once after display and event machinery initialization. * Use this to create further windows and initialize application resources. * Return YASL_APP_CONTINUE, YASL_APP_QUIT, or YASL_APP_ERROR. */ enum yasl_app_result (*init)(void *ud, struct yasl_display *d); /** * Unified event handler for input, window and user events, in display-wide enqueue order. * Event payloads and borrowed strings are valid for the duration of the callback. * INPUT_RESET has no payload and requires clearing held application input. * Return YASL_APP_CONTINUE, YASL_APP_QUIT, or YASL_APP_ERROR. Optional; without it, a * WINDOW_CLOSE request on any window stops yasl_run(). */ enum yasl_app_result (*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 *frame); /** * 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); }; /** Request orderly exit from any display-thread callback; ERROR returns failure. */ YASL_API void yasl_app_exit(struct yasl_display *d, enum yasl_app_result result); /** Borrow the optional desc.window surface during init or later; NULL if absent/destroyed. */ YASL_API struct yasl_surface *yasl_app_window(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. * Display quit notifications stop the runner; connection loss and dispatch * failures return an error after application cleanup. */ YASL_API int yasl_run(const struct yasl_app_desc *desc); #ifdef __cplusplus } #endif #endif /* YASL_APP_H */