From a91694108c71833e246538bdaaaca0aa49f7c77d Mon Sep 17 00:00:00 2001 From: reuk Date: Fri, 20 May 2022 12:44:44 +0100 Subject: [PATCH] Windows: Fix virtual keyboard hide/show on Windows 11 This change fixes an issue where the touch keyboard failed to show when selecting a TextEditor. On the current versions of Windows 10 and 11, the undocumented ITipInvocation workaround no longer seems to be required, so it has been removed. The isTabletModeActivatedForWindow function is no longer needed, and has been removed. This function also appears to return inconsistent results: the window may be in 'desktop mode', but devices with touchscreens should still display the keyboard when selecting a TextEditor by touch. --- .../native/juce_win32_Windowing.cpp | 137 ++---------------- 1 file changed, 16 insertions(+), 121 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index eb1c937774..92c85739a2 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -1252,93 +1252,6 @@ __CRT_UUID_DECL (juce::ITipInvocation, 0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0 namespace juce { -struct OnScreenKeyboard : public DeletedAtShutdown, - private Timer -{ - void activate() - { - shouldBeActive = true; - startTimer (10); - } - - void deactivate() - { - shouldBeActive = false; - startTimer (10); - } - - JUCE_DECLARE_SINGLETON_SINGLETHREADED (OnScreenKeyboard, false) - -private: - OnScreenKeyboard() - { - tipInvocation.CoCreateInstance (ITipInvocation::getCLSID(), CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER); - } - - ~OnScreenKeyboard() override - { - clearSingletonInstance(); - } - - void timerCallback() override - { - stopTimer(); - - if (reentrant || tipInvocation == nullptr) - return; - - const ScopedValueSetter setter (reentrant, true, false); - - auto isActive = isKeyboardVisible(); - - if (isActive != shouldBeActive) - { - if (! isActive) - { - tipInvocation->Toggle (GetDesktopWindow()); - } - else - { - if (auto hwnd = FindWindow (L"IPTip_Main_Window", nullptr)) - PostMessage (hwnd, WM_SYSCOMMAND, (int) SC_CLOSE, 0); - } - } - } - - bool isVisible() - { - if (auto hwnd = FindWindowEx (nullptr, nullptr, L"ApplicationFrameWindow", nullptr)) - return FindWindowEx (hwnd, nullptr, L"Windows.UI.Core.CoreWindow", L"Microsoft Text Input Application") != nullptr; - - return false; - } - - bool isVisibleLegacy() - { - if (auto hwnd = FindWindow (L"IPTip_Main_Window", nullptr)) - { - auto style = GetWindowLong (hwnd, GWL_STYLE); - return (style & WS_DISABLED) == 0 && (style & WS_VISIBLE) != 0; - } - - return false; - } - - bool isKeyboardVisible() - { - if (isVisible()) - return true; - - // isVisible() may fail on Win10 versions < 1709 so try the old method too - return isVisibleLegacy(); - } - - bool shouldBeActive = false, reentrant = false; - ComSmartPtr tipInvocation; -}; - -JUCE_IMPLEMENT_SINGLETON (OnScreenKeyboard) - //============================================================================== struct HSTRING_PRIVATE; typedef HSTRING_PRIVATE* HSTRING; @@ -1418,30 +1331,6 @@ struct UWPUIViewSettings } } - bool isTabletModeActivatedForWindow (::HWND hWnd) const - { - if (viewSettingsInterop == nullptr) - return false; - - ComSmartPtr viewSettings; - - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token") - - if (viewSettingsInterop->GetForWindow (hWnd, __uuidof (IUIViewSettings), - (void**) viewSettings.resetAndGetPointerAddress()) == S_OK - && viewSettings != nullptr) - { - IUIViewSettings::UserInteractionMode mode; - - if (viewSettings->GetUserInteractionMode (&mode) == S_OK) - return mode == IUIViewSettings::Touch; - } - - JUCE_END_IGNORE_WARNINGS_GCC_LIKE - - return false; - } - private: //============================================================================== struct ComBaseModule @@ -1497,8 +1386,6 @@ public: setTitle (component.getName()); updateShadower(); - OnScreenKeyboard::getInstance(); - getNativeRealtimeModifiers = [] { HWNDComponentPeer::updateKeyModifiers(); @@ -1857,16 +1744,22 @@ public: void textInputRequired (Point, TextInputTarget&) override { if (! hasCreatedCaret) + hasCreatedCaret = CreateCaret (hwnd, (HBITMAP) 1, 0, 0); + + if (hasCreatedCaret) { - hasCreatedCaret = true; - CreateCaret (hwnd, (HBITMAP) 1, 0, 0); + SetCaretPos (0, 0); + ShowCaret (hwnd); } - ShowCaret (hwnd); - SetCaretPos (0, 0); + ImmAssociateContext (hwnd, nullptr); - if (uwpViewSettings.isTabletModeActivatedForWindow (hwnd)) - OnScreenKeyboard::getInstance()->activate(); + // MSVC complains about the nullptr argument, but the docs for this + // function say that the second argument is ignored when the third + // argument is IACE_DEFAULT. + JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6387) + ImmAssociateContextEx (hwnd, nullptr, IACE_DEFAULT); + JUCE_END_IGNORE_WARNINGS_MSVC } void closeInputMethodContext() override @@ -1878,8 +1771,10 @@ public: { closeInputMethodContext(); - if (uwpViewSettings.isTabletModeActivatedForWindow (hwnd)) - OnScreenKeyboard::getInstance()->deactivate(); + ImmAssociateContext (hwnd, nullptr); + + if (std::exchange (hasCreatedCaret, false)) + DestroyCaret(); } void repaint (const Rectangle& area) override