#define _GNU_SOURCE #include #include "xdg-shell-client.h" #include "wlr-layer-shell-client.h" #include #include #include #include #include #include #include static struct wl_display *display; static struct wl_compositor *compositor; static struct wl_shm *shm; static struct xdg_wm_base *wm; static struct zwlr_layer_shell_v1 *layer_shell; struct window {struct wl_surface *surface; struct xdg_surface *xdg; struct xdg_toplevel *top; int w,h,fs,max;}; static struct window main_window,dialog; static const char *app; static void release(void *data,struct wl_buffer *buffer){wl_buffer_destroy(buffer);} static const struct wl_buffer_listener releases={release}; static void draw(struct wl_surface *s,int w,int h,uint32_t color){ int fd=memfd_create("scope-test",MFD_CLOEXEC);size_t size=(size_t)w*h*4;assert(fd>=0&&ftruncate(fd,size)==0); uint32_t *p=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);assert(p!=MAP_FAILED); for(size_t i=0;iw)w->w=300;if(!w->h)w->h=180;printf("CONFIG %s %d %d fs=%d max=%d\n",w==&main_window?"main":"dialog",w->w,w->h,w->fs,w->max);draw(w->surface,w->w,w->h,strstr(app,"cover") ? 0xffdd5533 : 0xff2244aa);} static const struct xdg_surface_listener conf={configured}; static void top_config(void *data,struct xdg_toplevel *t,int32_t width,int32_t height,struct wl_array *states){struct window *w=data;w->w=width;w->h=height;w->fs=w->max=0;uint32_t *v;wl_array_for_each(v,states){if(*v==XDG_TOPLEVEL_STATE_FULLSCREEN)w->fs=1;if(*v==XDG_TOPLEVEL_STATE_MAXIMIZED)w->max=1;}} static void top_close(void*d,struct xdg_toplevel*t){exit(0);} static const struct xdg_toplevel_listener top_events={.configure=top_config,.close=top_close}; static void ping(void*d,struct xdg_wm_base*w,uint32_t serial){xdg_wm_base_pong(w,serial);} static const struct xdg_wm_base_listener wm_events={ping}; static void global(void*d,struct wl_registry*r,uint32_t id,const char*name,uint32_t version){ if(!strcmp(name,"wl_compositor"))compositor=wl_registry_bind(r,id,&wl_compositor_interface,4); if(!strcmp(name,"wl_shm"))shm=wl_registry_bind(r,id,&wl_shm_interface,1); if(!strcmp(name,"xdg_wm_base"))wm=wl_registry_bind(r,id,&xdg_wm_base_interface,2); if(!strcmp(name,"zwlr_layer_shell_v1"))layer_shell=wl_registry_bind(r,id,&zwlr_layer_shell_v1_interface,1); } static void removed(void*d,struct wl_registry*r,uint32_t id){} static const struct wl_registry_listener registry_events={global,removed}; static void create(struct window*w,int child){w->surface=wl_compositor_create_surface(compositor);w->xdg=xdg_wm_base_get_xdg_surface(wm,w->surface);xdg_surface_add_listener(w->xdg,&conf,w);w->top=xdg_surface_get_toplevel(w->xdg);xdg_toplevel_add_listener(w->top,&top_events,w);xdg_toplevel_set_app_id(w->top,child?"scope-dialog":app);xdg_toplevel_set_title(w->top,child?"Scope dialog":"Scope client");if(child)xdg_toplevel_set_parent(w->top,main_window.top);} static struct wl_surface *bar; static void layer_config(void*d,struct zwlr_layer_surface_v1*s,uint32_t serial,uint32_t w,uint32_t h){zwlr_layer_surface_v1_ack_configure(s,serial);draw(bar,w,h,0xffee2222);} static void layer_close(void*d,struct zwlr_layer_surface_v1*s){} static const struct zwlr_layer_surface_v1_listener layer_events={layer_config,layer_close}; int main(int argc,char**argv){setbuf(stdout,NULL);setbuf(stdin,NULL);app=argc>1?argv[1]:"scope-normal";display=wl_display_connect(NULL);assert(display);struct wl_registry*r=wl_display_get_registry(display);wl_registry_add_listener(r,®istry_events,NULL);wl_display_roundtrip(display);assert(compositor&&shm&&wm);xdg_wm_base_add_listener(wm,&wm_events,NULL); if(argc>2&&!strcmp(argv[2],"bar")){assert(layer_shell);bar=wl_compositor_create_surface(compositor);struct zwlr_layer_surface_v1*l=zwlr_layer_shell_v1_get_layer_surface(layer_shell,bar,NULL,ZWLR_LAYER_SHELL_V1_LAYER_TOP,"scope-bar");zwlr_layer_surface_v1_add_listener(l,&layer_events,NULL);zwlr_layer_surface_v1_set_size(l,0,24);zwlr_layer_surface_v1_set_anchor(l,ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP|ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT|ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);zwlr_layer_surface_v1_set_exclusive_zone(l,24);wl_surface_commit(bar); }else{create(&main_window,0);if(argc>2&&!strcmp(argv[2],"fullscreen"))xdg_toplevel_set_fullscreen(main_window.top,NULL);if(argc>2&&!strcmp(argv[2],"maximize"))xdg_toplevel_set_maximized(main_window.top);wl_surface_commit(main_window.surface);} while(1){wl_display_dispatch_pending(display);wl_display_flush(display);struct pollfd fds[2]={{wl_display_get_fd(display),POLLIN,0},{STDIN_FILENO,POLLIN,0}};assert(poll(fds,2,-1)>=0);if(fds[0].revents&POLLIN){if(wl_display_dispatch(display)<0)break;}if(fds[1].revents&POLLIN){char cmd[256];if(!fgets(cmd,sizeof(cmd),stdin))break; if(!strncmp(cmd,"fullscreen 1",12))xdg_toplevel_set_fullscreen(main_window.top,NULL); else if(!strncmp(cmd,"fullscreen 0",12))xdg_toplevel_unset_fullscreen(main_window.top); else if(!strncmp(cmd,"maximize 1",10))xdg_toplevel_set_maximized(main_window.top); else if(!strncmp(cmd,"maximize 0",10))xdg_toplevel_unset_maximized(main_window.top); else if(!strncmp(cmd,"dialog",6)){create(&dialog,1);wl_surface_commit(dialog.surface);} else if(!strncmp(cmd,"appid ",6)){cmd[strcspn(cmd,"\n")]=0;xdg_toplevel_set_app_id(main_window.top,cmd+6);} if(main_window.surface)wl_surface_commit(main_window.surface); }}return 0;}