From 3f1befb06eab0f717b5db4abda5c79c4b9294d0b Mon Sep 17 00:00:00 2001 From: Yoshiko <91673781+yosuemask2@users.noreply.github.com> Date: Mon, 4 Oct 2021 23:29:56 +0900 Subject: [PATCH] Fix Touch Keyboard invocation issue (#11389) This fixes an issue that Touch Keyboard is not invoked when user taps on the PowerShell. Before this change, it was returning small rectangle on the right of the cursor. Touch Keyboard should be invoked by tapping anywhere inside the console. ## PR Checklist * [ ] Closes #xxx * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments ITfContextOwner::GetScreenExt is used to define rectangle that can invoke Touch Keyboard. https://docs.microsoft.com/en-us/windows/win32/api/msctf/nf-msctf-itfcontextowner-getscreenext ## Validation Steps Performed * [x] Touch keyboard was invoked by tapping inside the Console while Hardware Keyboard was not attached. * [x] Selecting text worked as expected without invoking touch keyboard. * [x] Long tapping the console invoked Touch Keyboard. I would like to confirm if this is the expected behavior. --- src/inc/contsf.h | 3 ++- src/interactivity/win32/WindowIme.cpp | 12 ++++++++++++ src/interactivity/win32/windowime.hpp | 1 + src/interactivity/win32/windowproc.cpp | 2 +- src/tsf/ConsoleTSF.h | 15 ++++++++++++--- src/tsf/contsf.cpp | 4 ++-- 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/inc/contsf.h b/src/inc/contsf.h index d7fbacdb4..07594e104 100644 --- a/src/inc/contsf.h +++ b/src/inc/contsf.h @@ -29,8 +29,9 @@ extern "C" { #endif typedef RECT (*GetSuggestionWindowPos)(); +typedef RECT (*GetTextBoxAreaPos)(); -BOOL ActivateTextServices(HWND hwndConsole, GetSuggestionWindowPos pfnPosition); +BOOL ActivateTextServices(HWND hwndConsole, GetSuggestionWindowPos pfnPosition, GetTextBoxAreaPos pfnTextArea); void DeactivateTextServices(); BOOL NotifyTextServices(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* lplResult); diff --git a/src/interactivity/win32/WindowIme.cpp b/src/interactivity/win32/WindowIme.cpp index 37e722f1f..547f098c0 100644 --- a/src/interactivity/win32/WindowIme.cpp +++ b/src/interactivity/win32/WindowIme.cpp @@ -54,3 +54,15 @@ RECT GetImeSuggestionWindowPos() return rcSuggestion; } + +// Routine Description: +// - This method gives a rectangle to where text box is currently rendered +// such that the touch keyboard can pop up when the rectangle is tapped. +// Arguments: +// - +// Return Value: +// - Rectangle specifying current text box area. +RECT GetTextBoxArea() +{ + return Microsoft::Console::Interactivity::ServiceLocator::LocateConsoleWindow()->GetWindowRect(); +} diff --git a/src/interactivity/win32/windowime.hpp b/src/interactivity/win32/windowime.hpp index dc44c7f2d..dc7e6d241 100644 --- a/src/interactivity/win32/windowime.hpp +++ b/src/interactivity/win32/windowime.hpp @@ -6,3 +6,4 @@ #pragma hdrstop RECT GetImeSuggestionWindowPos(); +RECT GetTextBoxArea(); diff --git a/src/interactivity/win32/windowproc.cpp b/src/interactivity/win32/windowproc.cpp index ad88dc7fa..1557dbe9a 100644 --- a/src/interactivity/win32/windowproc.cpp +++ b/src/interactivity/win32/windowproc.cpp @@ -263,7 +263,7 @@ using namespace Microsoft::Console::Types; HandleFocusEvent(TRUE); // ActivateTextServices does nothing if already active so this is OK to be called every focus. - ActivateTextServices(ServiceLocator::LocateConsoleWindow()->GetWindowHandle(), GetImeSuggestionWindowPos); + ActivateTextServices(ServiceLocator::LocateConsoleWindow()->GetWindowHandle(), GetImeSuggestionWindowPos, GetTextBoxArea); // set the text area to have focus for accessibility consumers if (_pUiaProvider) diff --git a/src/tsf/ConsoleTSF.h b/src/tsf/ConsoleTSF.h index 833106078..a38a4f621 100644 --- a/src/tsf/ConsoleTSF.h +++ b/src/tsf/ConsoleTSF.h @@ -33,9 +33,11 @@ class CConsoleTSF final : { public: CConsoleTSF(HWND hwndConsole, - GetSuggestionWindowPos pfnPosition) : + GetSuggestionWindowPos pfnPosition, + GetTextBoxAreaPos pfnTextArea) : _hwndConsole(hwndConsole), _pfnPosition(pfnPosition), + _pfnTextArea(pfnTextArea), _cRef(1), _tid() { @@ -66,21 +68,27 @@ public: return S_OK; } + // This returns Rectangle of the text box of whole console. + // When a user taps inside the rectangle while hardware keyboard is not available, + // touch keyboard is invoked. STDMETHODIMP GetScreenExt(RECT* pRect) { if (pRect) { - *pRect = _pfnPosition(); + *pRect = _pfnTextArea(); } return S_OK; } + // This returns rectangle of current command line edit area. + // When a user types in East Asian language, candidate window is shown at this position. + // Emoji and more panel (Win+.) is shown at the position, too. STDMETHODIMP GetTextExt(LONG, LONG, RECT* pRect, BOOL* pbClipped) { if (pRect) { - GetScreenExt(pRect); + *pRect = _pfnPosition(); } if (pbClipped) @@ -198,6 +206,7 @@ private: // Console info. HWND _hwndConsole; GetSuggestionWindowPos _pfnPosition; + GetTextBoxAreaPos _pfnTextArea; // Miscellaneous flags BOOL _fModifyingDoc = FALSE; // Set TRUE, when calls ITfRange::SetText diff --git a/src/tsf/contsf.cpp b/src/tsf/contsf.cpp index e83a8080a..81a98c5b8 100644 --- a/src/tsf/contsf.cpp +++ b/src/tsf/contsf.cpp @@ -5,11 +5,11 @@ CConsoleTSF* g_pConsoleTSF = nullptr; -extern "C" BOOL ActivateTextServices(HWND hwndConsole, GetSuggestionWindowPos pfnPosition) +extern "C" BOOL ActivateTextServices(HWND hwndConsole, GetSuggestionWindowPos pfnPosition, GetTextBoxAreaPos pfnTextArea) { if (!g_pConsoleTSF && hwndConsole) { - g_pConsoleTSF = new (std::nothrow) CConsoleTSF(hwndConsole, pfnPosition); + g_pConsoleTSF = new (std::nothrow) CConsoleTSF(hwndConsole, pfnPosition, pfnTextArea); if (g_pConsoleTSF && SUCCEEDED(g_pConsoleTSF->Initialize())) { // Conhost calls this function only when the console window has focus.