From b37cb0db72576e03aa80ee578ebe044a1e86cde0 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Mon, 16 Oct 2023 03:55:09 +0000 Subject: [PATCH] Work around for MS Word's rejecting sync edit sessions This is a workaround for Microsoft Word's suddenly stopping accepting synchronous edit sessions after moving ruler UI. While MS Word's stack trace after entering the failure mode strongly implies that this is an unexpected behavior in Microsoft Word [1], realistically Mozc needs to work around this by avoiding synchronous edit sessions whenever possible as TSF team has recommended [2]. Also MS-IME in Windows 11 22H2 does use asynchronous edit sessions even from the key event handler unless "Use previous version of Microsoft IME" settings is enabled. This means that stopping relying on synchronous edit sessions in Mozc also benefits the general app compatibility. The problem is that redesigning edit session handling is a relatively big project [3]. As a quick workaround, this commit aims to address the main typing issue in MS Word by tweaking 'OnOutputReceivedImpl'. The following features remains to be unavailable in the failure mode. * Reconversion triggered from IMEs. * Undo-commit Closes #819 with known issues. [1]: https://github.com/google/mozc/issues/819 [2]: https://learn.microsoft.com/en-us/archive/blogs/tsfaware/rules-of-text-services [3]: https://github.com/google/mozc/issues/821 PiperOrigin-RevId: 573696936 --- src/win32/tip/tip_edit_session.cc | 17 +++++++++++++++++ src/win32/tip/tip_thread_context.h | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/win32/tip/tip_edit_session.cc b/src/win32/tip/tip_edit_session.cc index cecf844e54..44758b7519 100644 --- a/src/win32/tip/tip_edit_session.cc +++ b/src/win32/tip/tip_edit_session.cc @@ -506,6 +506,15 @@ bool OnOutputReceivedImpl(TipTextService *text_service, ITfContext *context, auto edit_session = MakeComPtr(text_service, context, std::move(new_output)); + TipThreadContext *thread_context = text_service->GetThreadContext(); + + if (mode == kSync && thread_context->use_async_lock_in_key_handler()) { + // A workaround for MS Word's failure mode. + // See https://github.com/google/mozc/issues/819 for details. + // TODO(https://github.com/google/mozc/issues/821): Remove this workaround. + mode = kAsync; + } + DWORD edit_session_flag = TF_ES_READWRITE; switch (mode) { case kAsync: @@ -526,6 +535,14 @@ bool OnOutputReceivedImpl(TipTextService *text_service, ITfContext *context, const HRESULT hr = context->RequestEditSession( text_service->GetClientID(), edit_session.get(), edit_session_flag, &edit_session_result); + + if (mode == kSync && edit_session_result == TF_E_SYNCHRONOUS) { + // A workaround for MS Word's failure mode. + // See https://github.com/google/mozc/issues/819 for details. + // TODO(https://github.com/google/mozc/issues/821): Remove this workaround. + thread_context->set_use_async_lock_in_key_handler(true); + } + return SUCCEEDED(hr) && SUCCEEDED(edit_session_result); } diff --git a/src/win32/tip/tip_thread_context.h b/src/win32/tip/tip_thread_context.h index 1176acbf52..7f29ed2548 100644 --- a/src/win32/tip/tip_thread_context.h +++ b/src/win32/tip/tip_thread_context.h @@ -47,9 +47,21 @@ class TipThreadContext { int32_t GetFocusRevision() const { return focus_revision_; } void IncrementFocusRevision(); + void set_use_async_lock_in_key_handler(bool value) { + use_async_lock_in_key_handler_ = value; + } + bool use_async_lock_in_key_handler() const { + return use_async_lock_in_key_handler_; + } + private: TipInputModeManager input_mode_manager_; int32_t focus_revision_ = 0; + + // A workaround for MS Word's failure mode. + // See https://github.com/google/mozc/issues/819 for details. + // TODO(https://github.com/google/mozc/issues/821): Remove this workaround. + bool use_async_lock_in_key_handler_ = false; }; } // namespace tsf