diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 15:43:04 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 15:43:04 +0300 |
| commit | e24b8a8cef001e1c7e50ab12b739486f59b2a850 (patch) | |
| tree | f4678f9c7081c2bfd2dad56c8ca456c01447a116 | |
| parent | 38533c81e7b7ebfc5f281c2523188aeaa38d09c3 (diff) | |
Let yasl_app_desc describe its initial window
A new optional yasl_app_desc.window spec makes yasl_run() create that
toplevel and request its first frame before init(), which is now
optional too. If creation fails, yasl_run() closes the display and
returns an error without calling init().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | docs/guide.md | 7 | ||||
| -rw-r--r-- | docs/migrating.md | 5 | ||||
| -rw-r--r-- | include/yasl/app.h | 10 | ||||
| -rw-r--r-- | src/common/app.c | 17 | ||||
| -rw-r--r-- | tests/common/test_app.c | 24 |
5 files changed, 55 insertions, 8 deletions
diff --git a/docs/guide.md b/docs/guide.md index f195e5e..a65972f 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -40,8 +40,11 @@ it advertises CSD. Check each result and provide an application fallback. ## Window creation and callbacks All examples include `<yasl/app.h>` and call `yasl_run()` with a -`yasl_app_desc`. Create surfaces in `init`, handle `YASL_EVENT_*` notifications -in `event`, and render into `frame->cpu.pixels` in `frame`. Present with +`yasl_app_desc`. Set `window` to a `yasl_window_spec` for a single toplevel, +which the runner creates before `init` with its first frame requested; `yasl_run()` returns an +error if creation fails. Create further surfaces in the optional `init`, handle +`YASL_EVENT_*` notifications in `event`, and render into `frame->cpu.pixels` in +`frame`. Present with `yasl_frame_present_cpu(frame, NULL, 0)` and return `YASL_APP_QUIT` from an event handler to exit. The runner handles dispatch, input polling, resize redraws, and remaining surface/display cleanup. Display quit stops the runner; connection diff --git a/docs/migrating.md b/docs/migrating.md index e1f5442..86804c8 100644 --- a/docs/migrating.md +++ b/docs/migrating.md @@ -6,8 +6,9 @@ See the [application guide](guide.md) for the full window and input workflow. ## Application callbacks -All examples now use `<yasl/app.h>` and `yasl_run()`. Move window creation to -`yasl_app_desc.init`, input handling to `.event`, and drawing to `.frame`. +All examples now use `<yasl/app.h>` and `yasl_run()`. Describe a single window +in `yasl_app_desc.window`, or create windows in `.init`; move input handling to +`.event` and drawing to `.frame`. Replace manual dispatch/poll/flush loops with the runner and request redraws with `yasl_surface_request_frame()`. Present the frame context with `yasl_frame_present_cpu()`; the runner destroys remaining surfaces on exit. diff --git a/include/yasl/app.h b/include/yasl/app.h index f067d5b..79b2519 100644 --- a/include/yasl/app.h +++ b/include/yasl/app.h @@ -148,10 +148,16 @@ struct yasl_app_desc { 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; /** - * Called once after display and event machinery initialization. - * Use this to create windows and initialize application resources. + * Optional; called once after display and event machinery initialization. + * Use this to create further windows and initialize application resources. * Return YASL_APP_CONTINUE or YASL_APP_QUIT. */ enum yasl_app_result (*init)(void *ud, struct yasl_display *d); diff --git a/src/common/app.c b/src/common/app.c index 9ec1f6a..9d52e4a 100644 --- a/src/common/app.c +++ b/src/common/app.c @@ -332,7 +332,7 @@ static void app_runner_lost(void *ud) int yasl_run(const struct yasl_app_desc *desc) { - if (!desc || !desc->init) + if (!desc) return -1; struct app_runner runner = {.desc = desc, .running = true}; @@ -358,7 +358,20 @@ int yasl_run(const struct yasl_app_desc *desc) } d->app_runner = &runner; - if (desc->init(desc->userdata, d) == YASL_APP_QUIT) { + if (desc->window) { + struct yasl_surface *s = yasl_surface_create_toplevel(d, desc->window); + if (!s) { + int create_error = errno; + d->app_runner = NULL; + yasl_mutex_destroy(&runner.user_event_mutex); + yasl_display_close(d); + errno = create_error; + return -1; + } + yasl_surface_request_frame(s); + } + + if (desc->init && desc->init(desc->userdata, d) == YASL_APP_QUIT) { runner.running = false; } diff --git a/tests/common/test_app.c b/tests/common/test_app.c index 6972921..f61a957 100644 --- a/tests/common/test_app.c +++ b/tests/common/test_app.c @@ -109,6 +109,29 @@ static void on_quit(void *ud, struct yasl_display *d) state->quit_called = true; } +static void present_once(void *ud, struct yasl_surface *s, struct yasl_frame_context *ctx) +{ + (*(int *)ud)++; + if (ctx->cpu.pixels) + assert(yasl_frame_present_cpu(ctx, NULL, 0)); + yasl_surface_destroy(s); +} + +/* desc.window replaces init: the runner creates the toplevel and draws it. */ +static void test_window_without_init(void) +{ + int frames = 0; + struct yasl_window_spec window = {.title = "App Runner Window", .size = {160, 120}}; + int res = yasl_run(&(struct yasl_app_desc){ + .app_id = "org.yasl.test.app.window", + .userdata = &frames, + .window = &window, + .frame = present_once, + }); + assert(res == 0); + assert(frames == 1); +} + int main(void) { struct test_state state = {0}; @@ -129,6 +152,7 @@ int main(void) assert(state.user_event_called); assert(state.timer_called); assert(state.quit_called); + test_window_without_init(); printf("App runner tests passed!\n"); return 0; } |
