summaryrefslogtreecommitdiff
path: root/tests/common/test_surface_integration.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /tests/common/test_surface_integration.c
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (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.c90
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;
+}