From 22edbc1b373860be2230b88b2a5ec707b3ec0d4b Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 11 Aug 2022 23:22:23 +0200 Subject: [PATCH] Fix issues with Japanese & Vietnamese IME (#13678) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit builds directly on the changes made in #13677 and fixes: * TSF resetting to AlphaNumeric ("ASCII") input mode when pressing enter * Vietnamese IME not composing a new word after pressing whitespace, etc. Closes #11479 Closes #13398 ## Validation Steps Performed * Japanese IME (Full-Width Katakana) Typing "saitama" produces "サイタマ" ✅ * Korean IME Typing "gksrmf" produces "한글" ✅ * Vietnamese IME Typing "xin chaof" produces "xin chào" ✅ * Emoji Picker (Win+.) ✅ (cherry picked from commit ed800dc72de9e51201becf1f752093f4c1b4e155) Service-Card-Id: 84832470 Service-Version: 1.15 --- .github/actions/spelling/expect/expect.txt | 4 ++++ .../TerminalControl/TSFInputControl.cpp | 4 +--- src/cascadia/TerminalControl/TermControl.cpp | 19 +++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index c1a1a3015f0..3b918c6ac4b 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -233,6 +233,7 @@ CFuzz cgscrn chafa changelist +chaof charinfo charlespetzold charset @@ -2892,6 +2893,9 @@ xff xfg XFile XFORM +xin +xinchaof +xinxinchaof XManifest XMath XMFLOAT diff --git a/src/cascadia/TerminalControl/TSFInputControl.cpp b/src/cascadia/TerminalControl/TSFInputControl.cpp index 8cee7ffe154..7e9de19e99a 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.cpp +++ b/src/cascadia/TerminalControl/TSFInputControl.cpp @@ -102,9 +102,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _inputBuffer.clear(); _selection = {}; _activeTextStart = 0; - _editContext.NotifyFocusLeave(); _editContext.NotifyTextChanged({ 0, INT32_MAX }, 0, _selection); - _editContext.NotifyFocusEnter(); TextBlock().Text({}); } } @@ -375,7 +373,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation incomingText); _selection = args.NewSelection(); // GH#5054: Pressing backspace might move the caret before the _activeTextStart. - _activeTextStart = ::base::ClampMin(_activeTextStart, ::base::ClampedNumeric(range.StartCaretPosition)); + _activeTextStart = std::min(_activeTextStart, _inputBuffer.size()); // Emojis/Kaomojis/Symbols chosen through the IME without starting composition // will be sent straight through to the terminal. diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 91bcdac62f0..4896fa1aa37 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -904,6 +904,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } + // GH#11479: TSF wants to be notified of any character input via ICoreTextEditContext::NotifyTextChanged(). + // TSF is built and tested around the idea that you inform it of any text changes that happen + // when it doesn't currently compose characters. For instance writing "xin chaof" with the + // Vietnamese IME should produce "xin chào". After writing "xin" it'll emit a composition + // completion event and we'll write "xin" to the shell. It now has no input focus and won't know + // about the whitespace. If you then write "chaof", it'll emit another composition completion + // event for "xinchaof" and the resulting output in the shell will finally read "xinxinchaof". + // A composition completion event technically doesn't mean that the completed text is now + // immutable after all. We could (and probably should) inform TSF of any input changes, + // but we technically aren't a text input field. The immediate solution was + // to simply force TSF to clear its text whenever we have input focus. + TSFInputControl().ClearBuffer(); + _HidePointerCursorHandlers(*this, nullptr); const auto ch = e.Character(); @@ -1165,12 +1178,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation { const auto window = CoreWindow::GetForCurrentThread(); - if (vkey == VK_ESCAPE || - vkey == VK_RETURN) - { - TSFInputControl().ClearBuffer(); - } - // If the terminal translated the key, mark the event as handled. // This will prevent the system from trying to get the character out // of it and sending us a CharacterReceived event.