Release v0.6.3: fix capture banner ordering and check updates periodically

This commit is contained in:
2026-10-29 13:06:58 +02:00
parent 6b180798f5
commit d28e28c03c
16 changed files with 69 additions and 29 deletions
+21 -1
View File
@@ -7,6 +7,20 @@
namespace ks {
struct InputRegressionAccess {
static void setup(App &a) { a.hookBindings = {{Toggle,{MOD_CONTROL,VK_F12}}, {Case,{MOD_CONTROL|MOD_SHIFT,'U'}}}; }
static bool updateTimer(App &a) {
a.updateRunning=true; // Exercise timer scheduling without launching a network request.
App::windowProc(a.window,WM_TIMER,5,0);
bool first=KillTimer(a.window,5)!=FALSE;
App::windowProc(a.window,WM_TIMER,5,0);
bool repeated=KillTimer(a.window,5)!=FALSE;
a.updateRunning=false;
return first && repeated && !a.updateWorker.joinable();
}
static std::wstring updateResult(App &a,const wchar_t *state,const wchar_t *version) {
auto result=new UpdateResult; result->state=state; result->version=version;
App::windowProc(a.window,UpdateMessage,0,(LPARAM)result);
return a.notifiedUpdate;
}
static void click() { MSLLHOOKSTRUCT m{}; m.flags=LLMHF_INJECTED; App::mouseProc(HC_ACTION,WM_LBUTTONDOWN,(LPARAM)&m); }
};
}
@@ -31,6 +45,12 @@ int main(int argc, char **argv) {
// Message-only window: no hooks, synthetic input, clipboard changes or visible editor.
app.window=CreateWindowExW(0,L"STATIC",L"Input tests",0,0,0,0,0,HWND_MESSAGE,nullptr,nullptr,nullptr);
require(app.window!=nullptr,"message-only test window");
require(ks::UpdateCheckIntervalMs==21600000,"automatic update interval is six hours");
require(ks::InputRegressionAccess::updateTimer(app),"update timer rearms and avoids overlapping checks");
require(ks::InputRegressionAccess::updateResult(app,L"available",L"99.0.0")==L"99.0.0","background update records announced version");
require(ks::InputRegressionAccess::updateResult(app,L"available",L"99.0.0")==L"99.0.0","same available version remains deduplicated");
require(ks::InputRegressionAccess::updateResult(app,L"error",L"")==L"99.0.0","network error preserves announced version");
require(ks::InputRegressionAccess::updateResult(app,L"available",L"99.0.1")==L"99.0.1","new version can be announced after an error");
for(int variant=0;variant<3;++variant) for(int icon=0;icon<15;++icon)
for(int size:{22,44,55}) {
auto handle=(HICON)LoadImageW(app.instance,MAKEINTRESOURCEW(icon<9?300+variant*10+icon:400+variant*10+icon-9),IMAGE_ICON,size,size,0);
@@ -509,7 +529,7 @@ int main(int argc, char **argv) {
require(EqualRect(&listBefore,&(listAfter=childRect(102))),"DPI refresh preserves history list geometry");
}
auto settings=app.settingsWindow;
require(SendDlgItemMessageW(settings,209,BM_GETCHECK,0,0)==BST_CHECKED,"automatic screenshot editor checkbox defaults on");
require(SendDlgItemMessageW(settings,209,BM_GETCHECK,0,0)==BST_UNCHECKED,"automatic screenshot editor checkbox defaults off");
require(settings&&!IsWindowVisible(settings),"settings layout tested without changing user focus");
for(auto pair:{std::pair{209,215},std::pair{209,207},std::pair{209,220},std::pair{209,232},std::pair{207,215},std::pair{207,232},std::pair{207,220},std::pair{232,230},std::pair{230,231},std::pair{231,253}}) {
RECT first{},second{},overlap{};
+6
View File
@@ -165,8 +165,12 @@ int main()
require(!IsWindow(window),"copied screenshot closes without confirmation");
static bool published=false;
static bool notificationAccepted=false;
static HWND notificationWindow{};
static bool expectHidden=false;
app.notify=[](const ks::Clip &) {
if(!published) throw std::runtime_error("notification preceded clipboard publication");
if(expectHidden && IsWindowVisible(notificationWindow))
throw std::runtime_error("selection overlay is still visible when notification is sent");
return notificationAccepted;
};
for(bool autoOpen : {true,false}) for (bool accepted : {true, false}) {
@@ -178,6 +182,8 @@ int main()
PatBlt(selection.image->dc,0,0,100,100,WHITENESS);
selection.start={10,20}; selection.end={70,60};
auto overlay=CreateWindowW(cls.lpszClassName,L"Selection test",WS_POPUP,0,0,100,100,app.window,nullptr,app.instance,&selection);
notificationWindow=overlay; expectHidden=!autoOpen;
ShowWindow(overlay,SW_SHOWNOACTIVATE);
ks::finishSelection(overlay,selection,[](HWND,const ks::Clip &clip)->DWORD {
auto pixels=ks::decodeImage(clip);
if(pixels.width!=60 || pixels.height!=40) throw std::runtime_error("automatic copy did not crop selection");
+4 -1
View File
@@ -430,7 +430,10 @@ int main(int argc, char **argv)
auto invalid = settings;
auto captureSettings = settings;
captureSettings.screenshot = L"Ctrl+Shift+F9";
require(captureSettings.screenshotAutoOpenEditor,"editor opens by default");
require(!captureSettings.screenshotAutoOpenEditor,"notification-first capture is the default");
captureSettings.screenshotAutoOpenEditor=true;
require(ks::decodeSettings(ks::encodeSettings(captureSettings), {}).screenshotAutoOpenEditor,
"explicit automatic editor preference survives settings roundtrip");
captureSettings.screenshotAutoOpenEditor=false;
require(!ks::decodeSettings(ks::encodeSettings(captureSettings), {}).screenshotAutoOpenEditor,
"notification-first preference survives settings roundtrip");