From 5feabe9687bdafa0d1db71702fd2457a9432ecd7 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 19 Mar 2014 21:00:47 +0000 Subject: [PATCH] Another attempt to fix the infamous VST cubase key focus problem. --- .../utility/juce_WindowsHooks.h | 27 ++++++++++------- .../native/juce_win32_Windowing.cpp | 30 +++++++++++++++++-- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h b/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h index c4866de521..b1038f7d26 100644 --- a/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h +++ b/modules/juce_audio_plugin_client/utility/juce_WindowsHooks.h @@ -24,9 +24,15 @@ #if JUCE_WINDOWS +namespace juce +{ + // This function is in juce_win32_Windowing.cpp + extern bool offerKeyMessageToJUCEWindow (MSG&); +} + namespace { - static HHOOK mouseWheelHook = 0; + static HHOOK mouseWheelHook = 0, keyboardHook = 0; static int numHookUsers = 0; struct WindowsHooks @@ -39,11 +45,9 @@ namespace (HINSTANCE) Process::getCurrentModuleInstanceHandle(), GetCurrentThreadId()); - #if 0 // XXX temporary for testing - keyboardHook = SetWindowsHookEx (WH_KEYBOARD, keyboardHookCallback, + keyboardHook = SetWindowsHookEx (WH_GETMESSAGE, keyboardHookCallback, (HINSTANCE) Process::getCurrentModuleInstanceHandle(), GetCurrentThreadId()); - #endif } } @@ -57,13 +61,11 @@ namespace mouseWheelHook = 0; } - #if 0 // XXX temporary for testing if (keyboardHook != 0) { UnhookWindowsHookEx (keyboardHook); keyboardHook = 0; } - #endif } } @@ -85,16 +87,19 @@ namespace return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam); } - #if 0 // XXX temporary for testing static LRESULT CALLBACK keyboardHookCallback (int nCode, WPARAM wParam, LPARAM lParam) { - if (nCode >= 0 && nCode == HC_ACTION) - if (passKeyUpDownToPeer (GetFocus(), wParam, (lParam & (1 << 31)) == 0)) - return 1; + MSG& msg = *(MSG*) lParam; + + if (nCode == HC_ACTION && offerKeyMessageToJUCEWindow (msg)) + { + zerostruct (msg); + msg.message = WM_USER; + return 1; + } return CallNextHookEx (keyboardHook, nCode, wParam, lParam); } - #endif }; } diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index ebe414097d..ff55c4fde2 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -1113,6 +1113,20 @@ public: JUCE_DECLARE_NON_COPYABLE (JuceDropTarget) }; + #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client + static bool offerKeyMessageToJUCEWindow (MSG& m) + { + if (m.message == WM_KEYDOWN || m.message == WM_KEYUP) + if (Component::getCurrentlyFocusedComponent() != nullptr) + if (HWNDComponentPeer* h = getOwnerOfWindow (m.hwnd)) + if (m.message == WM_KEYDOWN ? h->doKeyDown (m.wParam) + : h->doKeyUp (m.wParam)) + return true; + + return false; + } + #endif + private: HWND hwnd, parentToAddTo; ScopedPointer shadower; @@ -2024,14 +2038,20 @@ private: { MSG msg; - if (! PeekMessage (&msg, hwnd, WM_CHAR, WM_DEADCHAR, PM_NOREMOVE)) { // if there isn't a WM_CHAR or WM_DEADCHAR message pending, we need to // manually generate the key-press event that matches this key-down. + const UINT keyChar = MapVirtualKey ((UINT) key, 2); + const UINT scanCode = MapVirtualKey ((UINT) key, 0); + BYTE keyState[256]; + GetKeyboardState (keyState); - const UINT keyChar = MapVirtualKey ((UINT) key, 2); - used = handleKeyPress ((int) LOWORD (keyChar), 0) || used; + WCHAR text[16] = { 0 }; + if (ToUnicode ((UINT) key, scanCode, keyState, text, 8, 0) != 1) + text[0] = 0; + + used = handleKeyPress ((int) LOWORD (keyChar), (juce_wchar) text[0]) || used; } } @@ -2935,6 +2955,10 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) return HWNDComponentPeer::isKeyDown (k); } +#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client +bool offerKeyMessageToJUCEWindow (MSG& m) { return HWNDComponentPeer::offerKeyMessageToJUCEWindow (m); } +#endif + //============================================================================== bool JUCE_CALLTYPE Process::isForegroundProcess() {