Release v0.6.35: reduce resident memory and compact shared dictionaries

This commit is contained in:
2026-11-04 14:08:05 +02:00
parent 004fee4976
commit d13e9849a7
21 changed files with 469 additions and 100 deletions
+56
View File
@@ -25,6 +25,38 @@ LRESULT CALLBACK countControlMoves(HWND w, UINT message, WPARAM wp, LPARAM lp, U
}
namespace ks {
struct InputRegressionAccess {
static bool idleUndo(App &a) {
a.last=LastTransform{}; a.last->at=100;
a.releaseIdleMemory(120100);
if (!a.last) return false;
a.busy=true;
a.releaseIdleMemory(120101);
if (!a.last) { a.busy=false; return false; }
a.busy=false;
a.releaseIdleMemory(120101);
return !a.last;
}
static bool releasedSync(const App &a) {
return a.syncSnapshot.capacity()==0 && a.syncResult.settings.capacity()==0 &&
a.syncResult.base.capacity()==0 && a.syncResult.conflicts.capacity()==0;
}
static bool completedSync(App &a, int mode) {
sampleConflicts(a);
auto conflicts=encodeSyncConflicts(a.pendingSyncConflicts);
a.syncConnection=loadSyncConfig(a.data);
a.syncSnapshot=encodeSettings(a.settings);
a.syncResult={mode!=1,sharedSyncSettings(a.settings),2,L"test"};
a.syncResult.base=a.syncResult.settings;
a.syncResult.conflicts=a.pendingSyncConflicts;
if(mode==2) a.syncResult.settings={1,2,3}; // Decode exception after joining.
a.syncWorker=std::thread([]{});
a.syncRunning=true; a.syncDone=true; a.busy=true;
a.pollSync();
bool retained=!a.syncSnapshot.empty() && a.syncRunning;
a.busy=false; a.pollSync();
return retained && releasedSync(a) && !a.syncRunning &&
encodeSyncConflicts(a.pendingSyncConflicts)==conflicts;
}
static inline bool delivery = true;
static inline int notifications = 0;
static bool notify(const std::wstring &) { ++notifications; return delivery; }
@@ -44,6 +76,7 @@ struct InputRegressionAccess {
a.syncRunning=true; a.syncDone=true;
a.pollSync();
return encodeSettings(a.settings)==before && !a.syncRunning &&
releasedSync(a) &&
!std::filesystem::exists(a.data/L"sync-base.bin");
}
static bool syncBackoff(App &a) {
@@ -791,6 +824,10 @@ int main(int argc, char **argv) {
require(IsWindowEnabled(app.settingsWindow),"closing sync restores parent");
require(ks::InputRegressionAccess::staleSync(app,false),"in-flight sync cannot overwrite newer local edits");
require(ks::InputRegressionAccess::staleSync(app,true),"disconnect discards in-flight downloaded profile");
require(ks::InputRegressionAccess::idleUndo(app),"idle cleanup retains available/busy Undo and frees expired Undo");
for(int mode=0;mode<3;++mode)
require(ks::InputRegressionAccess::completedSync(app,mode),
"completed, failed and invalid sync release buffers but preserve conflict choices");
require(ks::InputRegressionAccess::syncBackoff(app),"saving settings preserves authentication error backoff");
SendMessageW(app.settingsWindow,WM_COMMAND,255,0);
auto autoOptions=FindWindowW(L"KSwitcher.AutoOptions",nullptr);
@@ -902,6 +939,25 @@ int main(int argc, char **argv) {
SetDlgItemTextW(history,101,L"");
require(pumpUntil(2),"clearing search restores history");
require(GetFocus()==originalFocus,"history search preserves focus");
SendDlgItemMessageW(history,102,LB_SETCURSEL,1,0);
ks::refreshHistory(app); // A result may still be in flight when closing.
SendMessageW(history,WM_CLOSE,0,0);
SendMessageW(history,WM_TIMER,1,0); // KillTimer cannot retract a posted timer message.
require(pumpUntil(0),"closing history releases list strings");
auto until=GetTickCount64()+250;
while(GetTickCount64()<until) {
MSG message{};
while(PeekMessageW(&message,nullptr,0,0,PM_REMOVE)) {
TranslateMessage(&message); DispatchMessageW(&message);
}
Sleep(5);
}
require(SendDlgItemMessageW(history,102,LB_GETCOUNT,0,0)==0,
"late search results do not refill closed history");
ks::refreshHistory(app);
require(pumpUntil(2),"history reloads after releasing hidden rows");
require(SendDlgItemMessageW(history,102,LB_GETCURSEL,0,0)==1,
"history retains selected record across close and reload");
}
auto childRect=[&](int id) { RECT r{}; GetWindowRect(GetDlgItem(history,id),&r); MapWindowPoints(nullptr,history,(POINT*)&r,2); return r; };
RECT historyFrame{}; GetWindowRect(history,&historyFrame);