#pragma once #include "lan_channel.h" #include namespace ks::lan { enum class ControlMode { Local, Requesting, Sending, Receiving }; struct InputEnvironment { std::function bounds; std::function cursor; std::function inject; std::function desktop; std::function held; std::function anchor; std::function modeChanged; std::function dpi; }; InputEnvironment windowsInputEnvironment(); ULONG_PTR remoteInputMarker(); ULONG_PTR cursorWarpMarker(); bool atEdge(POINT,RECT,int edge); int edgePosition(POINT,RECT,int edge); POINT edgePoint(RECT,int edge,int position,int inset=8); class InputRouter { InputEnvironment env; std::function send; ControlMode mode_=ControlMode::Local; int edge{};bool preferLocal{},connected{},multi{},transit{}; int crossEdge=-1;uint64_t crossAt{}; uint32_t token{}; uint64_t cooldown{},requested{},revision_{}; POINT anchor{},returnPoint{},receivedPoint{}; bool awaitingWarp{},awaitingEntry{}; uint64_t warpStarted{},entryStarted{}; bool returning{};POINT returnTarget{};uint64_t returnStarted{}; double remainderX{},remainderY{}; std::array physical{},outKeys{},remoteKeys{}; std::array releases{}; std::array outButtons{},remoteButtons{}; void mode(ControlMode); bool emit(INPUT); bool move(POINT,bool warp=false); bool post(InputFrame); bool held() const; void release(); void local(uint64_t now,int position=-1); public: InputRouter(InputEnvironment,std::function,int edge,bool preferLocal,bool multi=false); ~InputRouter(); void selectEdge(int side,bool prefer){edge=side;preferLocal=prefer;} uint32_t sessionToken()const{return token;} bool canHandoff()const{return mode_==ControlMode::Sending&&!held();} bool handoff(int side,int position,uint64_t now); void returnAt(int side,int position,uint64_t now); ControlMode mode()const{return mode_;} uint64_t revision()const{return revision_;} void tick(bool ready,uint64_t now); void receive(const InputFrame &,uint64_t now); bool keyboard(const KBDLLHOOKSTRUCT &,bool down,uint64_t now); bool mouse(UINT,const MSLLHOOKSTRUCT &,uint64_t now,bool allowEnter=true); void cancel(uint64_t now,const char *reason="control cancelled"); }; }