import io,sys,time,subprocess from pathlib import Path from PIL import Image from ipc import ipc,ENV baseline='--baseline' in sys.argv def check(ok, label, value): print(label, value, 'PASS' if ok else 'FAIL', flush=True) if not baseline: assert ok, (label,value) def shot(output): return Image.open(io.BytesIO(subprocess.check_output(['grim','-o',output,'-'],env=ENV))).convert('RGB') def solid(key,layer,color,box=(0,0,640,480),output='HEADLESS-1'): r,g,b,a=color;x,y,w,h=box return ipc('test/solid',dict(key=key,layer=layer,r=r,g=g,b=b,a=a,x=x,y=y,w=w,h=h,output=output)) subprocess.run(['wlr-randr','--output','HEADLESS-1','--custom-mode','640x480','--pos=-640,0', '--output','HEADLESS-2','--custom-mode','640x480','--scale','2','--pos=0,0', '--output','HEADLESS-3','--custom-mode','640x480','--transform','90','--pos=320,0'],env=ENV,check=True) for name in ['HEADLESS-1','HEADLESS-2','HEADLESS-3']: ipc('test/cube',{'output':name}) time.sleep(1.5) ipc('test/stats');time.sleep(1) value=ipc('test/stats')['passes'];check(value==0,'Settled render passes in one second',value) for name in ['HEADLESS-1','HEADLESS-2','HEADLESS-3']: value=ipc('test/partial',{'output':name}) check(value['outside']==0 and value['inside']>0,'Damage clipping '+name,value) for name in ['HEADLESS-1','HEADLESS-2','HEADLESS-3']: ipc('test/cube',{'output':name,'stop':True}) # Real toplevel held during workspace rotation must stay below screensavers. ipc('wayfire/set-config-options',{'cube/initial_animation':'3000ms linear'}) log=(Path(ENV['XDG_RUNTIME_DIR']) / 'test-terminal.log').open('w') terminal=subprocess.Popen(['alacritty','--config-file','/dev/null','--class','render-regression', '-o','colors.primary.background="#00ff00"','-o','cursor.style.blinking="Never"', '-e','sleep','120'],env=ENV,stdout=log,stderr=log) try: for _ in range(50): views=[v for v in ipc('window-rules/list-views') if v.get('app-id')=='render-regression'] if views:break time.sleep(.1) assert views view=views[0] outputs={o['id']:o for o in ipc('window-rules/list-outputs')} output=outputs[view['output-id']]['name'] solid('popup',5,(1.,0.,1.,1.),(0,0,2000,2000),output) time.sleep(.2) result=ipc('test/held',{'output':output});assert result['found'] and result['carried-out'] time.sleep(.2) pixels=list(shot(output).get_flattened_data()) leaks=sum(p!=(255,0,255) for p in pixels) check(leaks==0,'Held window above overlay pixels',leaks) solid('saver',6,(1.,0.,1.,1.),(0,0,2000,2000),output) time.sleep(.1) pixels=list(shot(output).get_flattened_data()) leaks=sum(p!=(255,0,255) for p in pixels) check(leaks==0,'Held window above screensaver pixels',leaks) solid('lock',7,(0.,0.,1.,1.),(0,0,2000,2000),output) time.sleep(.1) pixels=list(shot(output).get_flattened_data()) leaks=sum(p!=(0,0,255) for p in pixels) check(leaks==0,'Held window above lock pixels',leaks) finally: terminal.terminate();terminal.wait(timeout=5) for k in ['popup','saver','lock']:ipc('test/solid',{'key':k,'close':True}) ipc('test/cube',{'output':output,'stop':True}) ipc('wayfire/set-config-options',{'cube/initial_animation':'350ms circle'})