Release v0.6.22: recover verified partial text selections

This commit is contained in:
2026-10-31 12:32:26 +02:00
parent 64a04b4382
commit c0ab02df16
12 changed files with 103 additions and 14 deletions
+25 -3
View File
@@ -227,7 +227,8 @@ class Transaction
return selectPrevious(n, [&] { return valid(); });
}
std::wstring copyRange(size_t count, const std::wstring &wordCandidate,
const std::function<bool(const std::wstring &)> &matches)
const std::function<bool(const std::wstring &)> &matches,
const std::function<bool(const std::wstring &)> &suffixMatches = {})
{
// WebView word boundaries are only candidates; exact verification is mandatory.
if (needsSelectionDelay(target) && !wordCandidate.empty() &&
@@ -247,7 +248,25 @@ class Transaction
return {};
Sleep(25);
}
return select(count) ? copy() : std::wstring{};
auto text = select(count) ? copy() : std::wstring{};
// Chromium editors can apply only part of a burst of Shift+Left events.
// Extend only a verified suffix; never replace a partial or unrelated range.
if (valid() && !matches(text) && !text.empty() &&
(suffixMatches ? suffixMatches(text) : newlines(wordCandidate).ends_with(newlines(text))) &&
caretSteps(text) < count)
{
const auto missing = count - caretSteps(text);
diagnosticEvent(L"Selection: extending verified suffix by " + std::to_wstring(missing));
for (size_t i = 0; i < missing; ++i)
{
if (!valid() || !chord(VK_LEFT, MOD_SHIFT))
return {};
Sleep(25);
}
text = copy();
diagnosticEvent(L"Selection: suffix recovery match=" + std::to_wstring(matches(text)));
}
return text;
}
bool paste(const Clip &clip)
{
@@ -1138,7 +1157,9 @@ void App::transform(int command, int snippet)
{
text =
tx.copyRange(recent.keys.size(), recent.keys, [&](const std::wstring &candidate)
{ return recent.match(candidate, available, physicalLayout()) >= 0; });
{ return recent.match(candidate, available, physicalLayout()) >= 0; },
[&](const std::wstring &candidate)
{ return recent.matchSuffix(candidate, available, physicalLayout()) >= 0; });
hint = recent.match(text, available, physicalLayout());
diagnosticEvent(L"Recent verification copied=" + std::to_wstring(text.size()) + L" keys=" +
std::to_wstring(recent.keys.size()) + L" match=" + std::to_wstring(hint));
@@ -1155,6 +1176,7 @@ void App::transform(int command, int snippet)
previous->version == version)
{
expected = previous->result;
diagnosticEvent(L"Previous result expected=" + diagnosticText(expected));
text = tx.copyRange(caretSteps(previous->result), previous->result,
[&](const std::wstring &candidate)
{ return newlines(candidate) == newlines(previous->result); });