Release v0.6.12: improve continuous correction and resize log viewer
This commit is contained in:
+50
-18
@@ -248,6 +248,13 @@ App::App(HINSTANCE h, bool test, const std::filesystem::path &dataRoot) : instan
|
||||
registrationWarning = L"Settings were not loaded: " + wide(e.what());
|
||||
}
|
||||
setLoggingEnabled(settings.writeLog);
|
||||
if (settings.autoCorrect)
|
||||
try { autoPredictor.configure(std::filesystem::path(executable()).parent_path() / L"dictionaries", settings.autoLanguages); }
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
settings.autoCorrect = false;
|
||||
registrationWarning += L"\nAutomatic correction unavailable: " + wide(e.what());
|
||||
}
|
||||
try
|
||||
{
|
||||
history = std::make_unique<History>(data / L"history");
|
||||
@@ -417,12 +424,12 @@ bool App::registerHotkeys(const Settings &s, bool rollback)
|
||||
void App::applySettings(const Settings &s)
|
||||
{
|
||||
bool autostartChanged = false;
|
||||
AutoCorrector predictor;
|
||||
validateSettings(s);
|
||||
validateTesseract(s);
|
||||
if (s.autoCorrect)
|
||||
{
|
||||
AutoCorrector probe;
|
||||
probe.configure(std::filesystem::path(executable()).parent_path() / L"dictionaries", s.autoLanguages);
|
||||
predictor.configure(std::filesystem::path(executable()).parent_path() / L"dictionaries", s.autoLanguages);
|
||||
}
|
||||
if (!registerHotkeys(s))
|
||||
{
|
||||
@@ -454,6 +461,7 @@ void App::applySettings(const Settings &s)
|
||||
{
|
||||
std::lock_guard lock(stateMutex);
|
||||
settings = s;
|
||||
autoPredictor = std::move(predictor);
|
||||
setLoggingEnabled(s.writeLog);
|
||||
run.reset();
|
||||
last.reset();
|
||||
@@ -517,6 +525,7 @@ void App::resetInput()
|
||||
run.reset();
|
||||
last.reset();
|
||||
}
|
||||
void App::clearLog(bool previous) { clearDiagnosticLog(previous); }
|
||||
void App::keyboard(const KBDLLHOOKSTRUCT &k, UINT mods)
|
||||
{
|
||||
if (ownKeyboardInput(k))
|
||||
@@ -557,9 +566,32 @@ void App::keyboard(const KBDLLHOOKSTRUCT &k, UINT mods)
|
||||
return;
|
||||
}
|
||||
run.record(ch, fg, layout, GetTickCount64());
|
||||
if (settings.autoCorrect && ch == L' ' && run.keys.size() >= (size_t)settings.autoMinLength + 1 &&
|
||||
if (settings.autoCorrect && mods == 0 && ch == L' ' && run.keys.size() >= (size_t)settings.autoMinLength + 1 &&
|
||||
run.keys.size() <= 41 && !busy && !run.overflow)
|
||||
PostMessageW(window, AutoCorrectMessage, (WPARAM)inputVersion.load(), 0);
|
||||
{
|
||||
for (int source = 0; source < (int)layouts.size(); ++source)
|
||||
if (layouts[source].handle == layout)
|
||||
{
|
||||
std::wstring predicted;
|
||||
for (wchar_t key : run.keys)
|
||||
predicted += key == L' ' ? L' ' : layouts[source].at(physicalLayout().code(key));
|
||||
if (autoPredictor.suggest(predicted, source, layouts, settings))
|
||||
{
|
||||
// Reserve the transaction before the next physical key arrives.
|
||||
// The delimiter itself passes through; subsequent input is queued.
|
||||
typingTarget = fg;
|
||||
autoPending = true;
|
||||
busy = true;
|
||||
if (!PostMessageW(window, AutoCorrectMessage, (WPARAM)inputVersion.load(), 0))
|
||||
{
|
||||
typingTarget = nullptr;
|
||||
autoPending = false;
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (busy || settings.snippets.empty())
|
||||
return;
|
||||
auto keys = lower(run.keys);
|
||||
@@ -677,6 +709,7 @@ void App::replayTyping()
|
||||
std::lock_guard lock(stateMutex);
|
||||
target = typingTarget;
|
||||
typingTarget = nullptr;
|
||||
autoPending = false;
|
||||
inputs.swap(deferredTyping);
|
||||
}
|
||||
busy = false;
|
||||
@@ -793,12 +826,14 @@ void App::transform(int command, int snippet)
|
||||
L" version=" + std::to_wstring(currentVersion) +
|
||||
L" repeat=" + std::to_wstring(repeatAttempts));
|
||||
}
|
||||
if (busy.exchange(true))
|
||||
const bool preDeferred = command == AutoCorrect && autoPending;
|
||||
if (busy.exchange(true) && !preDeferred)
|
||||
{
|
||||
if (manual)
|
||||
diagnosticEvent(L"Transform outcome id=" + std::to_wstring(attempt) + L" reason=busy", true);
|
||||
return;
|
||||
}
|
||||
if (preDeferred) autoPending = false;
|
||||
Run recent;
|
||||
std::optional<LastTransform> previous;
|
||||
Settings config;
|
||||
@@ -813,7 +848,7 @@ void App::transform(int command, int snippet)
|
||||
version = inputVersion;
|
||||
}
|
||||
enqueue(
|
||||
[this, target, recent, previous, config, available, version, command, snippet, attempt, manual, requestedAt]
|
||||
[this, target, recent, previous, config, available, version, command, snippet, attempt, manual, requestedAt, preDeferred]
|
||||
{
|
||||
struct BusyReset
|
||||
{
|
||||
@@ -827,7 +862,7 @@ void App::transform(int command, int snippet)
|
||||
else
|
||||
b = false;
|
||||
}
|
||||
} reset{busy, window};
|
||||
} reset{busy, window, preDeferred};
|
||||
auto start = GetTickCount64();
|
||||
std::wstring reason = L"cancelled-before-selection";
|
||||
std::wstring text, result, expected;
|
||||
@@ -1476,9 +1511,13 @@ LRESULT CALLBACK App::windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
app->captureHistory();
|
||||
return 0;
|
||||
case AutoCorrectMessage:
|
||||
if (app->installingUpdate) return 0;
|
||||
app->pendingAutoVersion = (uint64_t)wp;
|
||||
SetTimer(hwnd, 3, 250, nullptr);
|
||||
if (app->autoPending)
|
||||
{
|
||||
if (!app->installingUpdate && app->settings.autoCorrect && app->inputVersion.load() == (uint64_t)wp)
|
||||
app->transform(AutoCorrect);
|
||||
else
|
||||
app->replayTyping();
|
||||
}
|
||||
return 0;
|
||||
case SnippetMessage:
|
||||
if (app->installingUpdate) return 0;
|
||||
@@ -1504,7 +1543,7 @@ LRESULT CALLBACK App::windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
case WM_COPYDATA:
|
||||
{
|
||||
auto *data = (COPYDATASTRUCT *)lp;
|
||||
if (data && data->dwData >= ConfigRead && data->dwData < ConfigReply)
|
||||
if (data && data->dwData >= ConfigRead && data->dwData < ConfigEnd)
|
||||
{
|
||||
if (app->installingUpdate) return FALSE;
|
||||
return configurationRequest(*app, (HWND)wp, *data);
|
||||
@@ -1534,13 +1573,6 @@ LRESULT CALLBACK App::windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||
app->dispatch(20);
|
||||
return 0;
|
||||
}
|
||||
if (wp == 3)
|
||||
{
|
||||
KillTimer(hwnd, 3);
|
||||
if (!app->installingUpdate && app->settings.autoCorrect && app->inputVersion.load() == app->pendingAutoVersion)
|
||||
app->transform(AutoCorrect);
|
||||
return 0;
|
||||
}
|
||||
if (wp == 2)
|
||||
{
|
||||
PostMessageW(hwnd, WM_CLOSE, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user