[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [32524] trunk/blender/intern/ghost/intern: Fix AltGr problem on Windows

Nathan Letwory nathan at letworyinteractive.com
Sat Oct 16 17:21:56 CEST 2010


Revision: 32524
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=32524
Author:   jesterking
Date:     2010-10-16 17:21:55 +0200 (Sat, 16 Oct 2010)

Log Message:
-----------
Fix AltGr problem on Windows

It was impossible for keyboard layouts that use AltGr to create certain characters to insert
them in Text and Console.

The keyboard driver in Windows sends left control events when AltGr is pressed. This meant that
Blender thought control was being held, which is a PASS_THROUGH condition for the insert operator
in both editors.

Add testing of keyboard layout for AltGr, both on initialization and WM_INPUTLANGCHANGE.

To remedy AltGr problem, we send now a left control key up event to Blender before further processing
the AltGr key.

Modified Paths:
--------------
    trunk/blender/intern/ghost/intern/GHOST_SystemWin32.cpp
    trunk/blender/intern/ghost/intern/GHOST_SystemWin32.h

Modified: trunk/blender/intern/ghost/intern/GHOST_SystemWin32.cpp
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_SystemWin32.cpp	2010-10-16 15:01:01 UTC (rev 32523)
+++ trunk/blender/intern/ghost/intern/GHOST_SystemWin32.cpp	2010-10-16 15:21:55 UTC (rev 32524)
@@ -34,6 +34,8 @@
  * @date	May 7, 2001
  */
 
+#include <iostream>
+
 #include "GHOST_SystemWin32.h"
 #include "GHOST_EventDragnDrop.h"
 
@@ -142,6 +144,8 @@
 	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::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 @@
 		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_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 @@
 			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 @@
 			break;
 		}
 	}
+	((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
 	return key;
 }
 
@@ -573,7 +588,7 @@
 
 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 @@
 			/* 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 @@
 		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
 				////////////////////////////////////////////////////////////////////////

Modified: trunk/blender/intern/ghost/intern/GHOST_SystemWin32.h
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_SystemWin32.h	2010-10-16 15:01:01 UTC (rev 32523)
+++ trunk/blender/intern/ghost/intern/GHOST_SystemWin32.h	2010-10-16 15:21:55 UTC (rev 32524)
@@ -239,7 +239,7 @@
 	 * @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 @@
 	 * @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 @@
 	__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 @@
 	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_
 





More information about the Bf-blender-cvs mailing list