perf(windows): 健康路径去掉多余的排空投递,删除死掉的 50 ms 硬读取
健康路径上 OnKeyDown 把键入队后立即同步排空(Excel 首键修复,保留),但入队时 仍先投递一条 WM_DrainDeferredKeyDown。同步排空已经把这颗键取出:它要么还在 飞行中、要么已完成,那条消息运行时只会看到「有键在飞」或「队列为空」而直接 返回;后面排队的键由这颗键完成时自己安排排空。所以现在入队时不再投递,同步 排空之后只在键仍留在队列里(焦点会话未连上或刚开了重置)时才补一次投递, 这两种情况与原先的行为一致。每个健康按键省掉一次 PostMessage 和一次空转的 窗口消息。PeekNamedPipe 存活探测不动。 同时删除已确认没有调用者的硬读取路径:ReadDataFromServerViaNamedPipe、 单参数的 TryReadDataFromServerPipeWithTimeout(50 ms 超时即拆管道),以及 ClearNamedpipeDataIfExists——它唯一存活的调用不带 force,函数体什么也不做。
This commit is contained in:
1 parent
f7064eb7c7
commit
44caaefcec
6 files changed
+17
-53
No files matched your search
@@ -356,7 +356,6 @@ void CCompositionProcessorEngine::OnPreservedKey( //
|
||||
{
|
||||
WriteDataToSharedMemory(Global::Keycode, L'\0', Global::ModifiersDown, nullptr, 0, L"", 0b000111);
|
||||
SendKeyEventToUIProcess();
|
||||
ClearNamedpipeDataIfExists();
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUID(rguid, _PreservedKey_DoubleSingleByte.Guid))
|
||||
|
||||
@@ -547,8 +547,10 @@ class CMetasequoiaIME : public ITfTextInputProcessorEx,
|
||||
// caller already proved the keyboard is live through a non-zero
|
||||
// _IsKeyEaten out-char; otherwise the disabled compartment is queried here.
|
||||
void _NotePassthroughStatistics(UINT virtualKey, WCHAR wch, bool keyboardKnownEnabled);
|
||||
// scheduleDrain is false only when the caller drains synchronously right
|
||||
// after queueing and schedules a drain itself if the key stays queued.
|
||||
bool _QueueDeferredKeyDown(_In_ ITfContext *pContext, WPARAM wParam, LPARAM lParam, WCHAR translatedWch,
|
||||
UINT modifiersDown, const _KEYSTROKE_STATE &keyState);
|
||||
UINT modifiersDown, const _KEYSTROKE_STATE &keyState, bool scheduleDrain = true);
|
||||
bool _QueueDeferredPreservedKey(_In_ ITfContext *pContext, REFGUID preservedKey);
|
||||
void _ClearDeferredKeyDowns();
|
||||
void _ScheduleDeferredKeyDownDrain();
|
||||
|
||||
@@ -1267,38 +1267,6 @@ bool SendToNamedpipe(bool *deliveryAmbiguous = nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear namedpipe data if exists, cause sometimes there may be some useless data sent by last key event from
|
||||
* server
|
||||
*
|
||||
*/
|
||||
void ClearNamedpipeDataIfExists(bool force)
|
||||
{
|
||||
// Request IDs make destructive draining both unnecessary and incorrect:
|
||||
// an async edit session may still own any frame currently in this pipe.
|
||||
// Mismatched replies are retained by TryReadData... in pendingReplies.
|
||||
if (force)
|
||||
{
|
||||
// Compatibility path for Server-initiated candidate clicks: legacy
|
||||
// Server builds deliver the same candidate both on the worker pipe and
|
||||
// as one unsolicited (request_id == 0) reply. The worker payload has
|
||||
// already been consumed by the caller, so discard exactly that one
|
||||
// duplicate. TryRead caches every nonzero request reply it encounters
|
||||
// and ignores PipeReady, preserving all edit-session-owned frames.
|
||||
(void)TryReadDataFromServerPipeWithTimeout(FANY_IME_UNSOLICITED_REQUEST_ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to read selected candiate string data from server pipe with timeout
|
||||
*
|
||||
* @return struct FanyImeNamedpipeDataToTsf*
|
||||
*/
|
||||
struct FanyImeNamedpipeDataToTsf *TryReadDataFromServerPipeWithTimeout(uint64_t expectedRequestId)
|
||||
{
|
||||
return TryReadDataFromServerPipeWithTimeout(expectedRequestId, true);
|
||||
}
|
||||
|
||||
static struct FanyImeNamedpipeDataToTsf *TryReadDataFromServerPipeWithDeadline(uint64_t expectedRequestId,
|
||||
bool abortTransportOnTimeout,
|
||||
DWORD timeoutMs);
|
||||
@@ -1448,18 +1416,6 @@ static struct FanyImeNamedpipeDataToTsf *TryReadDataFromServerPipeWithDeadline(u
|
||||
return transportUnavailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data sent by server
|
||||
*
|
||||
* TODO: Cancel when time exceed, we should set a timeout
|
||||
*
|
||||
* @return struct FanyImeNamedpipeDataToTsf*
|
||||
*/
|
||||
struct FanyImeNamedpipeDataToTsf *ReadDataFromServerViaNamedPipe(uint64_t expectedRequestId)
|
||||
{
|
||||
return TryReadDataFromServerPipeWithTimeout(expectedRequestId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 即用即断,不要求一直连接,但是,要让 Server 端的管道一直在 connect 状态阻塞住等待连接
|
||||
*
|
||||
|
||||
@@ -103,12 +103,10 @@ int SendHideCaretStateEventToUIProcessViaNamedPipe();
|
||||
int SendShowCandidateWndEventToUIProcessViaNamedPipe();
|
||||
int SendMoveCandidateWndEventToUIProcessViaNamedPipe();
|
||||
int SendLangbarRightClickEventToUIProcessViaNamedPipe(const RECT *prcArea);
|
||||
void ClearNamedpipeDataIfExists(bool force = false);
|
||||
// Best-effort read of the Server-published current candidate page (comma-
|
||||
// separated). Used in UILess mode so ITfCandidateListUIElement::GetString can
|
||||
// return real candidates after PrepareCandidateList has written shared memory.
|
||||
bool TryReadCandidatePageFromSharedMemory(_Out_ std::wstring *candidatePage);
|
||||
struct FanyImeNamedpipeDataToTsf *TryReadDataFromServerPipeWithTimeout(uint64_t expectedRequestId);
|
||||
// When abortTransportOnTimeout is false, a missed reply leaves the pipe up and
|
||||
// returns a non-TransportUnavailable empty frame for the caller to fall back.
|
||||
struct FanyImeNamedpipeDataToTsf *TryReadDataFromServerPipeWithTimeout(uint64_t expectedRequestId,
|
||||
@@ -132,7 +130,6 @@ inline bool IsDeliveredServerRequestId(uint64_t requestId)
|
||||
// request was delivered. The key is dropped with the composition and never
|
||||
// sent again (DeferredKeyFailureReason::DeliveryAmbiguous).
|
||||
constexpr HRESULT FANY_E_COMMIT_REPLY_AMBIGUOUS = __HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
||||
struct FanyImeNamedpipeDataToTsf *ReadDataFromServerViaNamedPipe(uint64_t expectedRequestId);
|
||||
|
||||
//
|
||||
// Modifiers:
|
||||
|
||||
@@ -1070,8 +1070,8 @@ CMetasequoiaIME::KeyDownDispatchResult CMetasequoiaIME::_DispatchKeyDown(
|
||||
// a write success followed by a reply/edit failure takes the same
|
||||
// _FailDeferredKey path as a key that arrived behind a barrier.
|
||||
const bool healthyImmediateDispatch = _deferredKeyDowns.empty() && !_hasDeferredKeyInFlight;
|
||||
const bool queued =
|
||||
_QueueDeferredKeyDown(pContext, wParam, lParam, wch, capturedModifiers, KeystrokeState) != FALSE;
|
||||
const bool queued = _QueueDeferredKeyDown(pContext, wParam, lParam, wch, capturedModifiers, KeystrokeState,
|
||||
/*scheduleDrain=*/!healthyImmediateDispatch) != FALSE;
|
||||
*pIsEaten = queued ? TRUE : FALSE;
|
||||
DebugTsfIssue47(queued ? L"keydown-owned-queued" : L"keydown-owned-queue-failed", FANY_IME_NO_REQUEST_ID, code,
|
||||
wch, KeystrokeState.Category, KeystrokeState.Function, queued ? 1 : 0, _IsComposing(),
|
||||
@@ -1091,6 +1091,12 @@ CMetasequoiaIME::KeyDownDispatchResult CMetasequoiaIME::_DispatchKeyDown(
|
||||
// not ready, _DrainOneDeferredKeyDown leaves the key queued for the
|
||||
// ordinary asynchronous drain.
|
||||
_DrainOneDeferredKeyDown();
|
||||
// The drain is posted only when the synchronous one left the key
|
||||
// queued (no connected focus session, or a reset opened). A key it
|
||||
// dispatched is retired by its own completion, which schedules the
|
||||
// next drain, so a WM_DrainDeferredKeyDown posted up front would
|
||||
// only ever find the key in flight or gone.
|
||||
_ScheduleDeferredKeyDownDrain();
|
||||
}
|
||||
return KeyDownDispatchResult::Complete;
|
||||
}
|
||||
|
||||
@@ -636,7 +636,8 @@ bool CMetasequoiaIME::_ClassifyDeferredKeyDown(_In_ ITfContext *pContext, WPARAM
|
||||
}
|
||||
|
||||
bool CMetasequoiaIME::_QueueDeferredKeyDown(_In_ ITfContext *pContext, WPARAM wParam, LPARAM lParam,
|
||||
WCHAR translatedWch, UINT modifiersDown, const _KEYSTROKE_STATE &keyState)
|
||||
WCHAR translatedWch, UINT modifiersDown, const _KEYSTROKE_STATE &keyState,
|
||||
bool scheduleDrain)
|
||||
{
|
||||
// Repeats are owned but do not enqueue another global configuration toggle.
|
||||
if (keyState.Function == FUNCTION_TOGGLE_CHARACTER_SET && (lParam & 0x40000000) != 0)
|
||||
@@ -668,7 +669,10 @@ bool CMetasequoiaIME::_QueueDeferredKeyDown(_In_ ITfContext *pContext, WPARAM wP
|
||||
{
|
||||
_EnsureDeferredKeyProjection();
|
||||
}
|
||||
_ScheduleDeferredKeyDownDrain();
|
||||
if (scheduleDrain)
|
||||
{
|
||||
_ScheduleDeferredKeyDownDrain();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user