Files
msime-windows/windows/tests/deferred_key_failure_policy.cpp
T
fanlusky f7064eb7c7 refactor(windows): 翻页与高亮移动的回复缺失改为软错过
WM_AsyncServerCandidateKey 对所有候选键都用 300 ms 提交预算,回复缺失即按
「可能已上屏」处理:丢键并完整重置传输。可对 PageUp/PageDown/Up/Down/Tab(含
Shift+Tab)来说,Server 只翻页或移动高亮,回复本来就只是确认(处理函数原先的
注释也这么写),永远不会上屏。把一次慢确认升级成拆管道、清组合,代价完全不对等。

现在这几颗键走普通的 50 ms 软读取:超时只是软错过,不拆管道、不清队列,迟到
的回复按 request id 缓存;只有真正的读失败/坏帧(TransportUnavailable)才按传输
失败处理。回复内容一律不应用,因为 Server 对这些键从不提交文本。

逗号、句号、括号、减号/等号(可配置翻页,也可能以词定字或随标点上屏)、
Ctrl+Enter 译文上屏和选词键仍保留 300 ms 提交预算与「歧义即丢键 + 传输重置」。
判定放在 IsCandidateNavigationOnlyKey 里并补了单元测试。
2026-09-27 19:02:17 +08:00

82 lines
3.2 KiB
C++

#include "Key/DeferredKeyFailurePolicy.h"
namespace
{
using Kind = DeferredKeyFailureKind;
using Reason = DeferredKeyFailureReason;
bool Resolves(Reason reason, bool offline, Kind expected)
{
return ResolveDeferredKeyFailure(reason, offline) == expected;
}
} // namespace
int main()
{
// A superseded key never starts another reset, online or offline.
if (!Resolves(Reason::Superseded, false, Kind::Stale))
return 1;
if (!Resolves(Reason::Superseded, true, Kind::Stale))
return 2;
// Host quirks resync the composition over the healthy pipes.
if (!Resolves(Reason::HostEditRejected, false, Kind::Resync))
return 3;
if (!Resolves(Reason::EditSessionRequestFailed, false, Kind::Resync))
return 4;
if (!Resolves(Reason::AsyncPostFailed, false, Kind::Resync))
return 5;
// Offline, the local composition is the only authority: nothing to resync.
if (!Resolves(Reason::HostEditRejected, true, Kind::Offline))
return 6;
if (!Resolves(Reason::EditSessionRequestFailed, true, Kind::Offline))
return 7;
if (!Resolves(Reason::AsyncPostFailed, true, Kind::Offline))
return 8;
// A broken or ambiguous transport always takes the full reset.
if (!Resolves(Reason::TransportBroken, false, Kind::Transport))
return 9;
if (!Resolves(Reason::TransportBroken, true, Kind::Transport))
return 10;
if (!Resolves(Reason::DeliveryAmbiguous, false, Kind::Transport))
return 11;
if (!Resolves(Reason::DeliveryAmbiguous, true, Kind::Transport))
return 12;
// Edit-session outcomes: validation beats the HRESULT, ambiguity beats a
// plain transport error, and anything else is a host rejection.
if (ClassifyEditSessionFailure(true, true, true) != Reason::Superseded)
return 13;
if (ClassifyEditSessionFailure(false, true, true) != Reason::DeliveryAmbiguous)
return 14;
if (ClassifyEditSessionFailure(false, false, true) != Reason::TransportBroken)
return 15;
if (ClassifyEditSessionFailure(false, false, false) != Reason::HostEditRejected)
return 16;
// Paging and highlight moves are acknowledgement-only.
const unsigned int navigationKeys[] = {0x09 /*Tab*/, 0x21 /*PageUp*/, 0x22 /*PageDown*/, 0x26 /*Up*/,
0x28 /*Down*/};
for (const unsigned int key : navigationKeys)
{
if (!IsCandidateNavigationOnlyKey(key))
return 17;
}
// Keys the Server may turn into a commit keep the ambiguous-commit rule:
// configurable paging punctuation (, . [ ] - =), Enter (Ctrl+Enter
// translation), Space and the selection digits. Composition edit keys are
// not candidate keys at all.
const unsigned int commitCapableKeys[] = {0xBC /*,*/, 0xBE /*.*/, 0xDB /*[*/, 0xDD /*]*/, 0xBD /*-*/,
0xBB /*=*/, 0x0D /*Enter*/, 0x20 /*Space*/, '1', '9',
0x24 /*Home*/, 0x23 /*End*/, 0x25 /*Left*/, 0x27 /*Right*/};
for (const unsigned int key : commitCapableKeys)
{
if (IsCandidateNavigationOnlyKey(key))
return 18;
}
return 0;
}