#include "nt/providers.h" #include #include #include static void check(bool value,const char *message) { if (!value) throw std::runtime_error(message); } int main(int argc,char **argv) { try { check(argc==5,"bootstrap, paint, close and pointer fixtures required"); for (int fixture=2;fixture0,"cannot read paint fixture"); std::vector bytes(size_t(file.tellg())); file.seekg(0); check(bool(file.read(reinterpret_cast(bytes.data()),std::streamsize(bytes.size()))),"short paint fixture"); raven::ModuleSet modules; auto &entry=modules.add("paint.exe",bytes); unsigned frames=0,removed=0; uint64_t window=0; raven::DesktopPresentation presentation; presentation.present=[&](uint64_t handle,std::string_view title,uint32_t width,uint32_t height,std::span pixels) { check(handle && (!window || window==handle) && title=="Raven native paint" && width==32 && height==32 && pixels.size()==4096,"paint surface identity differs"); window=handle; if (frames) { for (unsigned y=0;y<32;++y) for (unsigned x=0;x<32;++x) { const auto at=(y*32+x)*4; check(pixels[at]==x*7 && pixels[at+1]==(31-y)*7 && pixels[at+2]==192,"guest paint pixel differs"); } } else for (const auto pixel : pixels) check(!pixel,"initial window surface is not zeroed"); ++frames; }; presentation.remove=[&](uint64_t handle) { check(handle==window,"removed wrong surface"); ++removed; }; // The pointer over the window shows the hand its class names. std::vector cursors; presentation.cursor=[&](uint32_t shape) { cursors.push_back(shape); }; unsigned waits=0; bool closed=false; // A blocked GetMessage looks at the host without a budget of its own, so the event comes on the first look after the frame. presentation.poll=[&](std::chrono::milliseconds) { std::vector events; if (fixture>=3 && frames==2 && !closed) { ++waits; closed=true; if (fixture==3) events.push_back({window,0x10}); else { events.push_back({window,0,0,0,raven::DesktopEventKind::pointer_motion,-2,3}); events.push_back({window,0x110,1,0,raven::DesktopEventKind::pointer_button,16,16}); events.push_back({window,0x110,0,0,raven::DesktopEventKind::pointer_button,16,16}); } } return events; }; const auto result=raven::run_native_process(modules,entry,argv[1],std::chrono::seconds(5),{},{},presentation); check(result.stop==raven::NativeStop::returned && !result.value && frames==2 && removed==1,"SDK paint lifecycle failed"); check(fixture==2 || waits==1,"close workflow did not wait for host event"); check(fixture!=4 || (!cursors.empty() && cursors.front()==32649),"class cursor did not reach the host pointer"); } } catch (const std::exception &error) { std::cerr<