summaryrefslogtreecommitdiff
path: root/tests/common/test_surface_integration.c
blob: 2752208d421abfe9ef3a8a28076cc909186a25bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
}