#define _POSIX_C_SOURCE 200809L #include #include #include #include "common/backend.h" #include #include #include #include #include #include #if YASL_HAS_COCOA void yasl_test_frame_tick(struct yasl_surface *surface); #endif 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); if(backend==YASL_BACKEND_COCOA) { assert(!(yasl_surface_features(s)&YASL_CAP_OPENGL)); assert(!yasl_gl_surface_create("unsupported GL",64,64,0,NULL,NULL)); assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); assert(!yasl_gl_make_current(NULL)); assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); assert(!yasl_gl_get_proc_address("glClear")); assert(yasl_get_error(NULL)==YASL_ERROR_UNSUPPORTED); } /* 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)); #if YASL_HAS_COCOA yasl_test_frame_tick(s); #endif uint64_t deadline=yasl_private_loop_now_ns()+3000000000ull; while(!refreshes && yasl_private_loop_now_ns()=0); 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; }