Release v0.6.57: multi-PC input, shared clipboard and resilient Settings Save

This commit is contained in:
agrynco committed 2026-11-06 21:33:37 +02:00
1 parent 82292c8a7e
commit 5de010ee44
39 files changed
+1707 -312

No files matched your search

+32 -9
View File
@@ -293,8 +293,9 @@ int main()
require(!IsWindowEnabled(GetDlgItem(lan,707)),"cannot forget nonexistent pair");
require(!IsWindowEnabled(GetDlgItem(lan,715)),"input sharing requires a paired computer");
require(!IsWindowEnabled(GetDlgItem(lan,716)),"stop input disabled when sharing is off");
for(int id:{711,712,713,714}) require(!IsWindowEnabled(GetDlgItem(lan,id)),"screen positions unavailable until peer selected");
require(IsDlgButtonChecked(lan,712)==BST_CHECKED,"default screen position is Right");
require(GetDlgItem(lan,721)!=nullptr,"monitor arrangement grid is present");
require(!(GetWindowLongPtrW(lan,GWL_STYLE)&(WS_THICKFRAME|WS_MAXIMIZEBOX)),"LAN window has a fixed size");
require(GetDlgItem(lan,711)==nullptr,"obsolete side radios are removed");
require(SendDlgItemMessageW(lan,702,LB_GETCOUNT,0,0)==0,"disabled discovery lists no generic network devices");
require(!std::filesystem::exists(root/L"lan-pairing.bin"),"opening LAN settings does not enable or save discovery");
RedrawWindow(lan,nullptr,nullptr,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
@@ -306,19 +307,23 @@ int main()
SendMessageW(parent,WM_COMMAND,IDCANCEL,0);
}
{
ks::lan::Json fixture={{"version",1},{"id",std::string(32,'a')},{"enabled",false},
ks::lan::Json fixture={{"version",1},{"id",std::string(32,'a')},{"enabled",false},{"inputPeer",std::string(32,'b')},{"inputEdge",1},
{"trusted",{{std::string(32,'b'),{{"name","Test paired KSwitcher"},{"key",std::string(64,'f')}}}}}};
auto text=fixture.dump();ks::atomicWrite(root/L"lan-pairing.bin",ks::protect(ks::Bytes(text.begin(),text.end())));
ks::App pairedApp(GetModuleHandleW(nullptr),true,root);ks::showSettings(pairedApp);
SendMessageW(pairedApp.settingsWindow,WM_COMMAND,262,0);
HWND lan=FindWindowW(L"KSwitcher.LAN",nullptr);
SendDlgItemMessageW(lan,702,LB_SETCURSEL,0,0);
SendMessageW(lan,WM_COMMAND,MAKEWPARAM(702,LBN_SELCHANGE),0);
for(int id:{711,712,713,714})require(IsWindowEnabled(GetDlgItem(lan,id)),"paired computer exposes all four layout positions");
SendDlgItemMessageW(lan,713,BM_CLICK,0,0);
require(IsDlgButtonChecked(lan,713)==BST_CHECKED&&IsDlgButtonChecked(lan,712)==BST_UNCHECKED,"Above selection changes radio group");
require(SendDlgItemMessageW(lan,702,LB_GETCURSEL,0,0)==0,"single saved pair selected automatically when opening LAN settings");
require(!IsWindowEnabled(GetDlgItem(lan,705))&&!IsWindowEnabled(GetDlgItem(lan,703))&&!IsWindowEnabled(GetDlgItem(lan,704)),"saved pair disables pairing and code controls");
SendDlgItemMessageW(lan,702,LB_SETCURSEL,-1,0);
SendMessageW(lan,WM_TIMER,1,0);
require(IsDlgButtonChecked(lan,713)==BST_CHECKED,"status refresh preserves unsaved position choice");
require(SendDlgItemMessageW(lan,702,LB_GETCURSEL,0,0)==0,"refresh restores single paired selection without a peer list change");
auto grid=GetDlgItem(lan,721);
SendMessageW(grid,WM_KEYDOWN,VK_UP,0);SendMessageW(grid,WM_KEYDOWN,VK_LEFT,0);
auto saved=ks::lan::Json::parse(ks::unprotect(ks::readFile(root/L"lan-pairing.bin",256*1024)));
require(saved["positions"][std::string(32,'b')]==ks::lan::Json::array({0,-1}),"keyboard moves monitor above this PC and saves immediately");
SendMessageW(lan,WM_TIMER,1,0);
require(saved["inputEdge"]==2,"monitor arrangement updates the existing input direction");
require(!IsWindowEnabled(GetDlgItem(lan,715)),"input cannot start while discovery is disabled");
// Let the native radio-button theme animation finish before visual capture.
auto repaintUntil=GetTickCount64()+200;
@@ -334,6 +339,24 @@ int main()
SendMessageW(lan,WM_COMMAND,IDCANCEL,0);
SendMessageW(pairedApp.settingsWindow,WM_COMMAND,IDCANCEL,0);
}
{
using J=ks::lan::Json;const std::string b(32,'b'),c(32,'c');
J fixture={{"version",1},{"id",std::string(32,'a')},{"enabled",false},{"inputPeer",b},{"inputEdge",0},
{"trusted",{{b,{{"name","Left desktop"},{"key",std::string(64,'f')}}},{c,{{"name","Right laptop"},{"key",std::string(64,'e')}}}}},
{"positions",{{b,J::array({-1,0})},{c,J::array({1,0})}}}};
auto text=fixture.dump();ks::atomicWrite(root/L"lan-pairing.bin",ks::protect(ks::Bytes(text.begin(),text.end())));
ks::App layoutApp(GetModuleHandleW(nullptr),true,root);ks::showSettings(layoutApp);
SendMessageW(layoutApp.settingsWindow,WM_COMMAND,262,0);auto lan=FindWindowW(L"KSwitcher.LAN",nullptr);auto grid=GetDlgItem(lan,721);
RECT r{};GetClientRect(grid,&r);
auto point=[&](int column,int row){return MAKELPARAM((2*column+1)*r.right/10,(2*row+1)*r.bottom/6);};
SendMessageW(grid,WM_LBUTTONDOWN,MK_LBUTTON,point(1,1));SendMessageW(grid,WM_MOUSEMOVE,MK_LBUTTON,point(1,0));SendMessageW(grid,WM_LBUTTONUP,0,point(1,0));
auto saved=J::parse(ks::unprotect(ks::readFile(root/L"lan-pairing.bin",256*1024)));
require(saved["positions"][b]==J::array({-1,-1})&&saved["positions"][c]==J::array({1,0}),"drag moves one monitor without moving another paired PC");
RedrawWindow(lan,nullptr,nullptr,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
GetClientRect(lan,&r);auto dc=GetDC(lan);auto screenshot=ks::screenshotClip(dc,r.right,r.bottom,{});ReleaseDC(lan,dc);
ks::atomicWrite(std::filesystem::path(ks::executable()).parent_path()/L"lan-three-computers.png",ks::encodePng(ks::decodeImage(screenshot)));
SendMessageW(lan,WM_COMMAND,IDCANCEL,0);SendMessageW(layoutApp.settingsWindow,WM_COMMAND,IDCANCEL,0);
}
std::filesystem::remove_all(root);
std::cout << "Passed " << passed << " chat profile checks\n";
CoUninitialize();