diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 16:24:56 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 16:24:56 +0300 |
| commit | ed963bba0b234d52fda14b2a8237dbf02ef4d655 (patch) | |
| tree | 0c7bd51ff01089fbc810f94a55e0adb94084478e | |
| parent | 4a61a0f8a749831b74aca04302a30ebbbb6f5586 (diff) | |
Quit on window close when the app has no event callback
Without yasl_app_desc.event, a close request had nowhere to go and the
window stayed open. The runner now stops instead, so hello drops its
event callback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | docs/guide.md | 12 | ||||
| -rw-r--r-- | examples/hello.c | 9 | ||||
| -rw-r--r-- | include/yasl/app.h | 3 | ||||
| -rw-r--r-- | src/common/app.c | 7 | ||||
| -rw-r--r-- | tests/common/test_hello_example.c | 2 | ||||
| -rw-r--r-- | tests/wayland/test_app_input.c | 14 |
7 files changed, 30 insertions, 19 deletions
@@ -49,7 +49,7 @@ explicit backend with `yasl_display_spec.backend`. Include `<yasl/app.h>` and pass application callbacks to `yasl_run()`. The complete [hello.c](examples/hello.c) describes its window in -`yasl_app_desc.window`, handles close requests in `event`, and fills every pixel +`yasl_app_desc.window`, lets the runner quit when it is closed, and fills every pixel in its frame callback: ```c diff --git a/docs/guide.md b/docs/guide.md index 62c2e1a..ab30c3d 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -41,12 +41,12 @@ it advertises CSD. Check each result and provide an application fallback. All examples include `<yasl/app.h>` and call `yasl_run()` with a `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, +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. Without an `event` +callback, closing any window stops the runner. The runner handles dispatch, input polling, resize redraws, and remaining surface/display cleanup. Display quit stops the runner; connection loss and dispatch failures return an error after cleanup. The runner delivers input exactly as `yasl_surface_poll_event()` returns it, plus diff --git a/examples/hello.c b/examples/hello.c index d3d74cf..38a0cac 100644 --- a/examples/hello.c +++ b/examples/hello.c @@ -1,16 +1,8 @@ /* A complete CPU-rendered window. Build instructions: docs/getting-started.md. */ #include <yasl/app.h> - #include <stdio.h> static bool failed; - -static enum yasl_app_result event(void *ud, const struct yasl_event *event) -{ - (void)ud; - return event->type == YASL_EVENT_WINDOW_CLOSE ? YASL_APP_QUIT : YASL_APP_CONTINUE; -} - static void draw(void *ud, struct yasl_surface *surface, struct yasl_frame_context *frame) { (void)ud; @@ -31,7 +23,6 @@ int main(void) struct yasl_app_desc desc = { .app_id = "org.example.hello", .window = &window, - .event = event, .frame = draw, }; int result = yasl_run(&desc); diff --git a/include/yasl/app.h b/include/yasl/app.h index 79b2519..bf6de9c 100644 --- a/include/yasl/app.h +++ b/include/yasl/app.h @@ -166,7 +166,8 @@ struct yasl_app_desc { * Unified event handler for input, window and user events, in arrival 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 or YASL_APP_QUIT. + * Return YASL_APP_CONTINUE or YASL_APP_QUIT. 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); diff --git a/src/common/app.c b/src/common/app.c index 9d52e4a..435d020 100644 --- a/src/common/app.c +++ b/src/common/app.c @@ -111,8 +111,13 @@ static void app_runner_surface_close(struct yasl_surface *s, void *ud) { struct app_surface *as = ud; struct app_runner *ar = as ? as->runner : NULL; - if (!ar || !ar->desc || !ar->desc->event) + if (!ar || !ar->desc) + return; + /* Without an event callback nothing could answer the request, so quit. */ + if (!ar->desc->event) { + ar->running = false; return; + } emit(ar, &(struct yasl_event){ .type = YASL_EVENT_WINDOW_CLOSE, diff --git a/tests/common/test_hello_example.c b/tests/common/test_hello_example.c index c648038..101e2d4 100644 --- a/tests/common/test_hello_example.c +++ b/tests/common/test_hello_example.c @@ -14,7 +14,7 @@ int main(void) struct yasl_window_spec window = {.title = "Hello YASL", .size = {640, 480}}; struct yasl_app_desc desc = { .app_id = "org.yasl.test.hello", .window = &window, - .event = event, .frame = draw_once, + .frame = draw_once, }; return yasl_run(&desc) || failed ? 1 : 0; } diff --git a/tests/wayland/test_app_input.c b/tests/wayland/test_app_input.c index 843f38d..88f9ead 100644 --- a/tests/wayland/test_app_input.c +++ b/tests/wayland/test_app_input.c @@ -26,6 +26,15 @@ static void push_key(struct yasl_surface *s) static enum yasl_app_result on_init(void *ud, struct yasl_display *d) { struct test_state *state = ud; + if (state->end == 3) { + /* With no event callback, a close request alone stops the runner. */ + struct yasl_surface *s = yasl_surface_create_toplevel(d, + &(struct yasl_window_spec){ .title = "App Close Test", .size = {64, 64} }); + assert(s); + struct wayland_surface *w = (struct wayland_surface *)s; + w->cbs->close(s, w->ud); + return YASL_APP_CONTINUE; + } if (state->end) { struct wayland_display *display = (struct wayland_display *)d; if (state->end == 1) @@ -107,5 +116,10 @@ int main(void) }); assert(end == 1 ? res == 0 : res < 0); } + state = (struct test_state){.end = 3}; + res = yasl_run(&(struct yasl_app_desc){ + .backend = YASL_BACKEND_WAYLAND, .userdata = &state, .init = on_init, + }); + assert(res == 0); return 0; } |
