diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index d63ac700831..1f1fc65adc4 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -34,6 +34,8 @@ * @date May 7, 2001 */ +#include + #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" @@ -142,6 +144,8 @@ GHOST_SystemWin32::GHOST_SystemWin32() GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); m_displayManager->initialize(); + this->keyboardAltGr(); + // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); } @@ -285,18 +289,18 @@ GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const { - bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0; + bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0; keys.set(GHOST_kModifierKeyLeftShift, down); - down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0; keys.set(GHOST_kModifierKeyRightShift, down); - down = HIBYTE(::GetKeyState(VK_LMENU)) != 0; + + down = HIBYTE(::GetKeyState(VK_MENU)) != 0; keys.set(GHOST_kModifierKeyLeftAlt, down); - down = HIBYTE(::GetKeyState(VK_RMENU)) != 0; keys.set(GHOST_kModifierKeyRightAlt, down); - down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0; + + down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0; keys.set(GHOST_kModifierKeyLeftControl, down); - down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0; keys.set(GHOST_kModifierKeyRightControl, down); + bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0; bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0; if(lwindown || rwindown) @@ -365,7 +369,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName= GHOST_WindowWin32::getWindowClassName(); - + // Use RegisterClassEx for setting small icon if (::RegisterClass(&wc) == 0) { success = GHOST_kFailure; @@ -381,14 +385,14 @@ GHOST_TSuccess GHOST_SystemWin32::exit() } -GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const +GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const { + bool isExtended = (lParam&(1<<24))?true:false; + GHOST_TKey key; GHOST_ModifierKeys oldModifiers, newModifiers; ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers); ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers); - - bool isExtended = (lParam&(1<<24))?true:false; if ((wParam >= '0') && (wParam <= '9')) { // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) @@ -474,6 +478,16 @@ GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const break; case VK_MENU: { + if(m_hasAltGr && isExtended) { + // We have here an extended RAlt, which is AltGr. The keyboard driver on Windows sends before this a LControl, so + // to be able to input characters created with AltGr (normal on German, French, Finnish and other keyboards) we + // push an extra LControl up event. This ensures we don't have a 'hanging' ctrl event in Blender windowmanager + // when typing in Text editor or Console. + GHOST_Event *extra = new GHOST_EventKey(getSystem()->getMilliSeconds(), GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl, '\0'); + ((GHOST_SystemWin32*)getSystem())->pushEvent(extra); + newModifiers.set(GHOST_kModifierKeyRightControl, false); + newModifiers.set(GHOST_kModifierKeyLeftControl, false); + } bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftAlt) != newModifiers.get(GHOST_kModifierKeyLeftAlt); if(lchanged) { key = GHOST_kKeyLeftAlt; @@ -494,6 +508,7 @@ GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const break; } } + ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); return key; } @@ -573,7 +588,7 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam) { - GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam); + GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(window, wParam, lParam); GHOST_EventKey* event; if (key != GHOST_kKeyUnknown) { MSG keyMsg; @@ -582,6 +597,7 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool k /* Eat any character related messages */ if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) { ascii = (char) keyMsg.wParam; + } event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); @@ -630,6 +646,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA); if (window) { switch (msg) { + // we need to check if new key layout has altgr + case WM_INPUTLANGCHANGE: + system->keyboardAltGr(); + break; //////////////////////////////////////////////////////////////////////// // Keyboard events, processed //////////////////////////////////////////////////////////////////////// diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 03f5349a606..3cd1deefda0 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -239,7 +239,7 @@ protected: * @param lParam The lParam from the wndproc * @return The GHOST key (GHOST_kKeyUnknown if no match). */ - virtual GHOST_TKey convertKey(WPARAM wParam, LPARAM lParam) const; + virtual GHOST_TKey convertKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const; /** * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys). @@ -310,6 +310,11 @@ protected: * @param keys The new state of the modifier keys. */ inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys); + + /** + * Check current key layout for AltGr + */ + inline virtual void keyboardAltGr(); /** * Windows call back routine for our window class. @@ -324,6 +329,8 @@ protected: __int64 m_freq; /** High frequency timer variable. */ __int64 m_start; + /** AltGr on current keyboard layout. */ + bool m_hasAltGr; }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const @@ -336,5 +343,22 @@ inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys) m_modifierKeys = keys; } +inline void GHOST_SystemWin32::keyboardAltGr() +{ + HKL keylayout = GetKeyboardLayout(0); // get keylayout for current thread + int i; + SHORT s; + for(m_hasAltGr = false, i = 32; i < 256; ++i) { + s = VkKeyScanEx((char)i, keylayout); + // s == -1 means no key that translates passed char code + // high byte contains shift state. bit 2 ctrl pressed, bit 4 alt pressed + // if both are pressed, we have AltGr keycombo on keylayout + if(s!=-1 && (s & 0x600) == 0x600) { + m_hasAltGr = true; + break; + } + } +} + #endif // _GHOST_SYSTEM_WIN32_H_