diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 23:41:31 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-13 23:41:31 +0300 |
| commit | 76073fe5fad8799e5850805f2f090af2cb62c741 (patch) | |
| tree | 9658019babe4760a3634bdab4da0731a10e42e68 /tests/common/test_surface_integration.c | |
| parent | dd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff) | |
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that
handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels.
- Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size,
scale and state; unchanged values send nothing.
- Guarantee REFRESH once a window has a size and after every resize,
never at size zero.
- Merge DROP_HOVER into DROP with over/leave/data actions and give drag
and drop actions enums.
- Keep event strings valid until the next wait and drop
yasl_event_release; empty or failed waits report NONE.
- Replace copy-in presentation with a lent pixel buffer:
yasl_cpu_pixels and yasl_cpu_present.
- Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and
comments that restated names.
- Wayland: resize floating windows in request_size instead of reporting
it unsupported, and stop marking new GPU surfaces as Vulkan so
yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE.
Also includes the in-progress public API refactor that was uncommitted
in the tree (removal of the app/loop layer, new surface, GL and Vulkan
entry points).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/common/test_surface_integration.c')
| -rw-r--r-- | tests/common/test_surface_integration.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/tests/common/test_surface_integration.c b/tests/common/test_surface_integration.c new file mode 100644 index 0000000..2752208 --- /dev/null +++ b/tests/common/test_surface_integration.c @@ -0,0 +1,90 @@ +#define _POSIX_C_SOURCE 200809L +#include <yasl/yasl.h> +#include <yasl/cpu.h> +#include "common/backend.h" +#include <assert.h> +#include <pthread.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <stdio.h> +static void drain(void) +{ + yasl_event e;int n=0; + while(yasl_wait_event(&e,0)>0)assert(++n<1000); +} +static void *wake_thread(void *unused) +{ (void)unused;struct timespec delay={0,20000000};nanosleep(&delay,NULL);yasl_wake();return NULL; } +static void *wrong_thread(void *data) +{ assert(!yasl_surface_set_title(data,"wrong"));assert(yasl_get_error(NULL)==YASL_ERROR_WRONG_THREAD);return NULL; } +static int refreshes; +static void refresh(yasl_surface *s,void *ud) +{ + (void)ud;refreshes++; + yasl_event e;assert(yasl_wait_event(&e,0)==-1);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); + yasl_surface_destroy(s);assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); +} +int main(int argc,char **argv) +{ + assert(argc==2); + enum yasl_backend backend=!strcmp(argv[1],"wayland")?YASL_BACKEND_WAYLAND:!strcmp(argv[1],"x11")?YASL_BACKEND_X11:YASL_BACKEND_COCOA; + assert(yasl_set_backend(backend));assert(yasl_set_app_id("org.yasl.surface-test")); + yasl_surface *s=yasl_surface_create("CPU contract",96,80,YASL_SURFACE_CPU); + if(!s){const char *why;yasl_get_error(&why);fprintf(stderr,"surface: %s native=%d\n",why,yasl_get_native_error());return 1;} + assert(yasl_surface_backend(s)==backend); + /* The first events report the window size, then ask for a frame. */ + yasl_event e;int fw=0,fh=0;bool window=false; + for(int i=0;i<1000;i++) { + assert(yasl_wait_event(&e,i?20:0)>=0); + if(e.type==YASL_EVENT_WINDOW){window=true;fw=e.window.pixel_width;fh=e.window.pixel_height;} + if(e.type==YASL_EVENT_REFRESH){assert(window&&fw>0&&fh>0&&e.surface==s);break;} + } + assert(e.type==YASL_EVENT_REFRESH); + int w,h;yasl_surface_get_framebuffer_size(s,&w,&h);assert(w==fw&&h==fh); + assert(!yasl_set_backend(backend));assert(yasl_get_error(NULL)==YASL_ERROR_BUSY); + int pw,ph;uint32_t *pixels=yasl_cpu_pixels(s,&pw,&ph);assert(pixels&&pw==w&&ph==h); + assert(pixels[0]==0&&pixels[(size_t)w*h-1]==0); + for(size_t i=0;i<(size_t)w*h;i++)pixels[i]=0xff102030u; + pixels[(size_t)3*w+2]=0xffaabbccu; + assert(yasl_cpu_present(s)); + assert(yasl_cpu_pixels(s,&pw,&ph)==pixels&&pixels[0]==0xff102030u&&pixels[(size_t)3*w+2]==0xffaabbccu); + drain(); + pthread_t thread;assert(!pthread_create(&thread,NULL,wrong_thread,s));pthread_join(thread,NULL); + assert(!pthread_create(&thread,NULL,wake_thread,NULL)); + int n=yasl_wait_event(&e,500);assert(n>=0);pthread_join(thread,NULL); + bool ime=yasl_surface_set_text_input(s,true,YASL_TEXT_NORMAL); + if(!ime)assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + bool snapshot=yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,1,3,7); + if(ime)assert(snapshot); + else assert(!snapshot&&yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); + assert(!yasl_surface_set_surrounding_text(s,"a\xc3\xa9z",4,2,3,8)); + assert(!yasl_surface_set_surrounding_text(s,"\xc0\xaf",2,0,2,8)); + drain(); + struct yasl_private_event pen={.type=YASL_PRIVATE_EVENT_PEN,.surface=s, + .pen={.device_id=10,.tool_id=20,.x=12.5,.y=9.25,.pressure=0.3, + .axes_valid=YASL_PRIVATE_PEN_PRESSURE,.action=YASL_PRIVATE_PEN_DOWN,.in_contact=true}}; + assert(yasl_private_events_push(s->display,s,&pen)); + assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_PEN&&e.pen.device_id==10&&e.pen.pressure==0.3&&e.pen.in_contact); + struct yasl_private_event text={.type=YASL_PRIVATE_EVENT_TEXT,.surface=s,.text={.data="owned",.len=5}}; + assert(yasl_private_events_push(s->display,s,&text));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_TEXT); + assert(e.text.length==5&&!strcmp(e.text.data,"owned")); + /* Unchanged focus folds into no event; a change reports the activated state. */ + unsigned active=yasl_surface_state(s)&YASL_STATE_ACTIVATED; + struct yasl_private_event focus={.type=YASL_PRIVATE_EVENT_FOCUS,.surface=s,.focus={.focused=!active}}; + assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_WINDOW); + assert((e.window.state&YASL_STATE_ACTIVATED)==(active?0u:YASL_STATE_ACTIVATED)&&e.window.pixel_width==w); + assert(yasl_private_events_push(s->display,s,&focus));assert(yasl_wait_event(&e,0)==0&&e.type==YASL_EVENT_NONE); + struct yasl_private_event hover={.type=YASL_PRIVATE_EVENT_DROP_HOVER,.surface=s,.drop={YASL_PRIVATE_DROP_LEAVE,{0,0}}}; + assert(yasl_private_events_push(s->display,s,&hover)); + assert(yasl_wait_event(&e,0)==1&&e.type==YASL_EVENT_DROP&&e.drop.action==YASL_DROP_LEAVE); + yasl_surface_set_refresh_callback(s,refresh,NULL); + assert(yasl_cpu_present(s)); + drain();assert(refreshes>0); + yasl_surface_set_refresh_callback(s,NULL,NULL); + yasl_surface_destroy(s); + assert(!yasl_set_backend(backend)); + s=yasl_surface_create("shared backend remains",64,64,YASL_SURFACE_CPU);assert(s); + yasl_shutdown();assert(yasl_set_backend(backend)); + s=yasl_surface_create("reinitialized",64,64,YASL_SURFACE_CPU);assert(s);yasl_shutdown(); + puts("public surface lifecycle, pixels, ownership, input, wake and refresh passed");return 0; +} |
