Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorNathan Letwory <nathan@letworyinteractive.com>2011-03-10 01:10:51 +0300
committerNathan Letwory <nathan@letworyinteractive.com>2011-03-10 01:10:51 +0300
commitca63b151318d5798bc49a93f5b52de294e8476e5 (patch)
treee6f7225d981a7602fd9c3f250d6400eb17b96221 /intern
parent63e37a6133d794e086e3a7a87b9482483c0c2ff6 (diff)
Apply [#26364] New Windows keyboard handling
Submitted by Alexander Kuznetsov Fixes [#25279] Shift-Numpad Combinations fail to align view to selected and addresses [#26328] Blender uses global keyboard message hook which hurts system responsiveness on Windows A whole new way of handling keyboard input improves greatly both code readability and event handling. Thanks for the great patch, Alexander!
Diffstat (limited to 'intern')
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp407
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h189
2 files changed, 260 insertions, 336 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 2dee44272be..db53e97705b 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -56,7 +56,7 @@
#ifdef WIN32
#ifndef GWL_USERDATA
#define GWL_USERDATA GWLP_USERDATA
-#define GWL_WNDPROC GWLP_WNDPROC
+#define GWL_WNDPROC GWLP_WNDPROC
#endif
#endif
@@ -154,6 +154,18 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
+/*
+ Initiates WM_INPUT messages from keyboard
+ That way GHOST can retrieve true keys
+*/
+GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
+{
+ RAWINPUTDEVICE device = {0};
+ device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
+ device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
+
+ return RegisterRawInputDevices(&device, 1, sizeof(device));
+};
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
@@ -161,7 +173,7 @@ GHOST_SystemWin32::GHOST_SystemWin32()
m_displayManager = new GHOST_DisplayManagerWin32 ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
m_displayManager->initialize();
-
+
// Check if current keyboard layout uses AltGr and save keylayout ID for
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
// generates VK_OEM_8 for their exclamation key (key left of right shift)
@@ -357,19 +369,23 @@ GHOST_TSuccess GHOST_SystemWin32::init()
{
GHOST_TSuccess success = GHOST_System::init();
- for(int i = 0; i < 255; i++) {
- m_prevKeyStatus[i] = false;
- m_curKeyStatus[i] = false;
- }
-
/* Disable scaling on high DPI displays on Vista */
- HMODULE user32 = ::LoadLibraryA("user32.dll");
+ user32 = ::LoadLibraryA("user32.dll");
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
if (SetProcessDPIAware)
SetProcessDPIAware();
- FreeLibrary(user32);
+ #ifdef NEED_RAW_PROC
+ pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
+ pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
+ #else
+ FreeLibrary(user32);
+ #endif
+
+ /* Initiates WM_INPUT messages from keyboard */
+ initKeyboardRawInput();
+
// Determine whether this system has a high frequency performance counter. */
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
@@ -402,9 +418,6 @@ GHOST_TSuccess GHOST_SystemWin32::init()
if (::RegisterClass(&wc) == 0) {
success = GHOST_kFailure;
}
-
- // Add low-level keyboard hook for our process.
- m_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, s_llKeyboardProc, wc.hInstance, 0);
}
return success;
@@ -413,170 +426,122 @@ GHOST_TSuccess GHOST_SystemWin32::init()
GHOST_TSuccess GHOST_SystemWin32::exit()
{
- // remove our low-level keyboard hook.
- UnhookWindowsHookEx(m_llKeyboardHook);
-
+ #ifdef NEED_RAW_PROC
+ FreeLibrary(user32);
+ #endif
+
return GHOST_System::exit();
}
-void GHOST_SystemWin32::triggerKey(GHOST_IWindow *window, bool down, GHOST_TKey key)
-{
- GHOST_Event *extra = new GHOST_EventKey(getSystem()->getMilliSeconds(), down ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, key, '\0');
- ((GHOST_SystemWin32*)getSystem())->pushEvent(extra);
-}
-void GHOST_SystemWin32::handleModifierKeys(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, GHOST_ModifierKeys &oldModifiers, GHOST_ModifierKeys &newModifiers) const
+GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
{
- switch(wParam) {
- case VK_SHIFT:
- {
- bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftAlt) != newModifiers.get(GHOST_kModifierKeyLeftAlt);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftAlt), GHOST_kKeyLeftAlt);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightAlt) != newModifiers.get(GHOST_kModifierKeyRightAlt);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightAlt), GHOST_kKeyRightAlt);
- }
- }
- lchanged = oldModifiers.get(GHOST_kModifierKeyLeftControl) != newModifiers.get(GHOST_kModifierKeyLeftControl);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftControl), GHOST_kKeyLeftControl);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightControl) != newModifiers.get(GHOST_kModifierKeyRightControl);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightControl), GHOST_kKeyRightControl);
- }
- }
- }
- break;
- case VK_CONTROL:
- {
- bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftAlt) != newModifiers.get(GHOST_kModifierKeyLeftAlt);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftAlt), GHOST_kKeyLeftAlt);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightAlt) != newModifiers.get(GHOST_kModifierKeyRightAlt);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightAlt), GHOST_kKeyRightAlt);
- }
- }
- lchanged = oldModifiers.get(GHOST_kModifierKeyLeftShift) != newModifiers.get(GHOST_kModifierKeyLeftShift);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftShift), GHOST_kKeyLeftShift);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightShift) != newModifiers.get(GHOST_kModifierKeyRightShift);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightShift), GHOST_kKeyRightShift);
- }
- }
- }
- break;
- case VK_MENU:
- {
- bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftShift) != newModifiers.get(GHOST_kModifierKeyLeftShift);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftShift), GHOST_kKeyLeftShift);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightShift) != newModifiers.get(GHOST_kModifierKeyRightShift);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightShift), GHOST_kKeyRightShift);
- }
- }
- lchanged = oldModifiers.get(GHOST_kModifierKeyLeftControl) != newModifiers.get(GHOST_kModifierKeyLeftControl);
- if(lchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyLeftControl), GHOST_kKeyLeftControl);
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightControl) != newModifiers.get(GHOST_kModifierKeyRightControl);
- if (rchanged) {
- ((GHOST_SystemWin32*)getSystem())->triggerKey(window, newModifiers.get(GHOST_kModifierKeyRightControl), GHOST_kKeyRightControl);
- }
- }
- }
- break;
- default:
- break;
- }
+ unsigned int size = 0;
+ char * data;
+ GHOST_TKey key = GHOST_kKeyUnknown;
+
+
+ if(!keyDown)
+ return GHOST_kKeyUnknown;
+
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
+
+
+ if((data = (char*)malloc(size)) &&
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
+ {
+ RAWINPUT ri;
+ memcpy(&ri,data,sizeof(ri));
+
+ if (ri.header.dwType == RIM_TYPEKEYBOARD)
+ {
+ *keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
+ key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
+ if(vk) *vk = ri.data.keyboard.VKey;
+ };
+
+ };
+ free(data);
+
+ return key;
}
//! note: this function can be extended to include other exotic cases as they arise.
// This function was added in response to bug [#25715]
-GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const
+GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
switch(PRIMARYLANGID(m_langId)) {
case LANG_FRENCH:
- if(wParam==VK_OEM_8) key = GHOST_kKey1; // on 'normal' shift + 1 to create '!' we also get GHOST_kKey1. ASCII will be '!'.
+ if(vKey==VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
break;
}
return key;
}
-GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const
+GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const
{
- GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- bool isExtended = (lParam&(1<<24))?true:false;
-
GHOST_TKey key;
- GHOST_ModifierKeys oldModifiers, newModifiers;
- system->retrieveModifierKeys(oldModifiers);
- system->getModifierKeys(newModifiers);
-
- //std::cout << wParam << " " << system->m_curKeyStatus[wParam] << " shift pressed: " << system->shiftPressed() << std::endl;
- if ((wParam >= '0') && (wParam <= '9')) {
+ if ((vKey >= '0') && (vKey <= '9')) {
// VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
- key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
+ key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0);
}
- else if ((wParam >= 'A') && (wParam <= 'Z')) {
+ else if ((vKey >= 'A') && (vKey <= 'Z')) {
// VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
- key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
+ key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA);
}
- else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
- key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
+ else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
+ key = (GHOST_TKey)(vKey - VK_F1 + GHOST_kKeyF1);
}
else {
- switch (wParam) {
+ switch (vKey) {
case VK_RETURN:
- key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
- break;
-
+ key = (extend)?GHOST_kKeyNumpadEnter : GHOST_kKeyEnter; break;
+
case VK_BACK: key = GHOST_kKeyBackSpace; break;
case VK_TAB: key = GHOST_kKeyTab; break;
case VK_ESCAPE: key = GHOST_kKeyEsc; break;
case VK_SPACE: key = GHOST_kKeySpace; break;
- case VK_PRIOR: key = GHOST_kKeyUpPage; break;
- case VK_NEXT: key = GHOST_kKeyDownPage; break;
- case VK_END: key = GHOST_kKeyEnd; break;
+
+ case VK_INSERT:
+ case VK_NUMPAD0:
+ key = (extend) ? GHOST_kKeyInsert : GHOST_kKeyNumpad0; break;
+ case VK_END:
+ case VK_NUMPAD1:
+ key = (extend) ? GHOST_kKeyEnd : GHOST_kKeyNumpad1; break;
+ case VK_DOWN:
+ case VK_NUMPAD2:
+ key = (extend) ? GHOST_kKeyDownArrow : GHOST_kKeyNumpad2; break;
+ case VK_NEXT:
+ case VK_NUMPAD3:
+ key = (extend) ? GHOST_kKeyDownPage : GHOST_kKeyNumpad3; break;
+ case VK_LEFT:
+ case VK_NUMPAD4:
+ key = (extend) ? GHOST_kKeyLeftArrow : GHOST_kKeyNumpad4; break;
+ case VK_CLEAR:
+ case VK_NUMPAD5:
+ key = (extend) ? GHOST_kKeyUnknown: GHOST_kKeyNumpad5; break;
+ case VK_RIGHT:
+ case VK_NUMPAD6:
+ key = (extend) ? GHOST_kKeyRightArrow : GHOST_kKeyNumpad6; break;
case VK_HOME:
- {
- if(system->m_curKeyStatus[VK_NUMPAD7] && system->shiftPressed())
- key = GHOST_kKeyNumpad7;
- else
- key = GHOST_kKeyHome;
- }
- break;
- case VK_INSERT: key = GHOST_kKeyInsert; break;
- case VK_DELETE: key = GHOST_kKeyDelete; break;
- case VK_LEFT: key = GHOST_kKeyLeftArrow; break;
- case VK_RIGHT: key = GHOST_kKeyRightArrow; break;
- case VK_UP: key = GHOST_kKeyUpArrow; break;
- case VK_DOWN: key = GHOST_kKeyDownArrow; break;
- case VK_NUMPAD0: key = GHOST_kKeyNumpad0; break;
- case VK_NUMPAD1: key = GHOST_kKeyNumpad1; break;
- case VK_NUMPAD2: key = GHOST_kKeyNumpad2; break;
- case VK_NUMPAD3: key = GHOST_kKeyNumpad3; break;
- case VK_NUMPAD4: key = GHOST_kKeyNumpad4; break;
- case VK_NUMPAD5: key = GHOST_kKeyNumpad5; break;
- case VK_NUMPAD6: key = GHOST_kKeyNumpad6; break;
- case VK_NUMPAD7: key = GHOST_kKeyNumpad7; break;
- case VK_NUMPAD8: key = GHOST_kKeyNumpad8; break;
- case VK_NUMPAD9: key = GHOST_kKeyNumpad9; break;
+ case VK_NUMPAD7:
+ key = (extend) ? GHOST_kKeyHome : GHOST_kKeyNumpad7; break;
+ case VK_UP:
+ case VK_NUMPAD8:
+ key = (extend) ? GHOST_kKeyUpArrow : GHOST_kKeyNumpad8; break;
+ case VK_PRIOR:
+ case VK_NUMPAD9:
+ key = (extend) ? GHOST_kKeyUpPage : GHOST_kKeyNumpad9; break;
+ case VK_DECIMAL:
+ case VK_DELETE:
+ key = (extend) ? GHOST_kKeyDelete : GHOST_kKeyNumpadPeriod; break;
+
case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen; break;
case VK_PAUSE: key = GHOST_kKeyPause; break;
- case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break;
+ case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break;
case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus; break;
- case VK_DECIMAL: key = GHOST_kKeyNumpadPeriod; break;
case VK_DIVIDE: key = GHOST_kKeyNumpadSlash; break;
case VK_ADD: key = GHOST_kKeyNumpadPlus; break;
@@ -594,59 +559,13 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, L
case VK_GR_LESS: key = GHOST_kKeyGrLess; break;
case VK_SHIFT:
- {
- bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftShift) != newModifiers.get(GHOST_kModifierKeyLeftShift);
- if(lchanged) {
- key = GHOST_kKeyLeftShift;
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightShift) != newModifiers.get(GHOST_kModifierKeyRightShift);
- if(rchanged) {
- key = GHOST_kKeyRightShift;
- } else {
- key = GHOST_kKeyUnknown;
- }
- }
- }
+ key = (scanCode == 0x36)? GHOST_kKeyRightShift : GHOST_kKeyLeftShift;
break;
case VK_CONTROL:
- {
- bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftControl) != newModifiers.get(GHOST_kModifierKeyLeftControl);
- if(lchanged) {
- key = GHOST_kKeyLeftControl;
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightControl) != newModifiers.get(GHOST_kModifierKeyRightControl);
- if(rchanged) {
- key = GHOST_kKeyRightControl;
- } else {
- key = GHOST_kKeyUnknown;
- }
- }
- }
+ key = (extend)? GHOST_kKeyRightControl : GHOST_kKeyLeftControl;
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;
- } else {
- bool rchanged = oldModifiers.get(GHOST_kModifierKeyRightAlt) != newModifiers.get(GHOST_kModifierKeyRightAlt);
- if(rchanged) {
- key = GHOST_kKeyRightAlt;
- } else {
- key = GHOST_kKeyUnknown;
- }
- }
- }
+ key = (extend)? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt;
break;
case VK_LWIN:
case VK_RWIN:
@@ -656,7 +575,7 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, L
case VK_SCROLL: key = GHOST_kKeyScrollLock; break;
case VK_CAPITAL: key = GHOST_kKeyCapsLock; break;
case VK_OEM_8:
- key = ((GHOST_SystemWin32*)getSystem())->processSpecialKey(window, wParam, lParam);
+ key = ((GHOST_SystemWin32*)getSystem())->processSpecialKey(window, vKey, scanCode);
break;
case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break;
case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break;
@@ -667,7 +586,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, L
break;
}
}
- ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
return key;
}
@@ -745,22 +663,27 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP
}
-GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
+GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
{
- GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(window, wParam, lParam);
+ int keyDown=0;
+ char vk;
+ GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem();
+ GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk);
GHOST_EventKey* event;
if (key != GHOST_kKeyUnknown) {
- MSG keyMsg;
char ascii = '\0';
- /* Eat any character related messages */
-
- if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_DEADCHAR, PM_REMOVE) ||
- ::PeekMessage(&keyMsg, NULL, WM_SYSCHAR, WM_SYSDEADCHAR, PM_REMOVE))
- {
- ascii = (char) keyMsg.wParam;
- if(ascii > 126) ascii = 0;
- };
- event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
+
+ unsigned short utf16[2]={0};
+ BYTE state[256];
+ GetKeyboardState((PBYTE)state);
+
+ if(ToAsciiEx(vk, 0, state, utf16, 0, system->m_keylayout))
+ WideCharToMultiByte(CP_ACP, 0x00000400,
+ (wchar_t*)utf16, 1,
+ (LPSTR) &ascii, 1,
+ NULL,NULL);
+
+ event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
#ifdef BF_GHOST_DEBUG
std::cout << ascii << std::endl;
@@ -798,53 +721,6 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
minmax->ptMinTrackSize.y=240;
}
-/* Note that this function gets *all* key events from the entire system (all
- * threads running in this desktop session. So when getting event here, don't assume
- * it's for Blender. Thus we only do status bookkeeping, so we can check
- * in s_wndProc and processKeyEvent what the real keyboard status is.
- * This is needed for proper handling of shift+numpad keys for instance.
- */
-LRESULT CALLBACK GHOST_SystemWin32::s_llKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
-{
- GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
-
- bool down = false;
- if(wParam==WM_KEYDOWN || wParam==WM_SYSKEYDOWN ){
- down = true;
- }
-
- if(nCode!=HC_ACTION)
- return CallNextHookEx(system->m_llKeyboardHook, nCode, wParam, lParam);
-
- KBDLLHOOKSTRUCT &keyb = *(PKBDLLHOOKSTRUCT)(lParam);
- system->m_prevKeyStatus[keyb.vkCode] = system->m_curKeyStatus[keyb.vkCode];
- //std::cout << "ll: " << keyb.vkCode << " " << down << " ||| ";
- if(keyb.flags) {
- if((keyb.flags & LLKHF_EXTENDED) == LLKHF_EXTENDED) {
- //std::cout << "extended ";
- }
- if((keyb.flags & LLKHF_ALTDOWN) == LLKHF_ALTDOWN) {
- //std::cout << "alt ";
- }
- if((keyb.flags & LLKHF_INJECTED)== LLKHF_INJECTED) {
- //std::cout << "injected ";
- }
- if((keyb.flags & LLKHF_UP) == LLKHF_UP) {
- system->m_curKeyStatus[keyb.vkCode] = false;
- //std::cout << "up" << std::endl;
- } else {
- system->m_curKeyStatus[keyb.vkCode] = true;
- //std::cout << "down" << std::endl;
- }
- }
- else {
- system->m_curKeyStatus[keyb.vkCode] = true;
- //std::cout << "down" << std::endl;
- }
-
- return CallNextHookEx(system->m_llKeyboardHook, nCode, wParam, lParam);
-}
-
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
GHOST_Event* event = 0;
@@ -863,29 +739,22 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
////////////////////////////////////////////////////////////////////////
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- event = processKeyEvent(window, true, wParam, lParam);
+ case WM_INPUT:
+ event = processKeyEvent(window, wParam, lParam);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;
-
- case WM_KEYUP:
- case WM_SYSKEYUP:
- event = processKeyEvent(window, false, wParam, lParam);
- if (!event) {
- GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
- GHOST_PRINT(msg)
- GHOST_PRINT(" key ignored\n")
- }
- break;
-
////////////////////////////////////////////////////////////////////////
// Keyboard events, ignored
////////////////////////////////////////////////////////////////////////
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ /* These functions were replaced by WM_INPUT*/
case WM_CHAR:
/* The WM_CHAR message is posted to the window with the keyboard focus when
* a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
@@ -900,13 +769,21 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* character (Ö) is generated by typing the dead key for the umlaut character, and
* then typing the O key.
*/
+ break;
case WM_SYSDEADCHAR:
/* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
* a WM_SYSKEYDOWN message is translated by the TranslateMessage function.
* WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
* a dead key that is pressed while holding down the alt key.
*/
- break;
+ case WM_SYSCHAR:
+ /* The WM_SYSCHAR message is sent to the window with the keyboard focus when
+ * a WM_SYSCHAR message is translated by the TranslateMessage function.
+ * WM_SYSCHAR specifies the character code of a dead key - that is,
+ * a dead key that is pressed while holding down the alt key.
+ * To prevent the sound, DefWindowProc must be avoided by return
+ */
+ return 0;
////////////////////////////////////////////////////////////////////////
// Tablet events, processed
////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index c3714b56832..ca1297adfc5 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -46,6 +46,93 @@
# define __int64 long long
#endif
+#ifndef WM_INPUT
+#define WM_INPUT 0x00FF
+#endif
+#ifndef RID_INPUT
+#define RID_INPUT 0x10000003
+#endif
+#ifndef RI_KEY_BREAK
+#define RI_KEY_BREAK 0x1
+#endif
+#ifndef RI_KEY_E0
+#define RI_KEY_E0 0x1
+#endif
+#ifndef RI_KEY_E1
+#define RI_KEY_E1 0x4
+#endif
+#ifndef RIM_TYPEMOUSE
+#define RIM_TYPEMOUSE 0x0
+#define RIM_TYPEKEYBOARD 0x1
+#define RIM_TYPEHID 0x2
+
+typedef struct tagRAWINPUTDEVICE {
+ USHORT usUsagePage;
+ USHORT usUsage;
+ DWORD dwFlags;
+ HWND hwndTarget;
+} RAWINPUTDEVICE;
+
+
+
+typedef struct tagRAWINPUTHEADER {
+ DWORD dwType;
+ DWORD dwSize;
+ HANDLE hDevice;
+ WPARAM wParam;
+} RAWINPUTHEADER;
+
+typedef struct tagRAWMOUSE {
+ USHORT usFlags;
+ union {
+ ULONG ulButtons;
+ struct {
+ USHORT usButtonFlags;
+ USHORT usButtonData;
+ };
+ };
+ ULONG ulRawButtons;
+ LONG lLastX;
+ LONG lLastY;
+ ULONG ulExtraInformation;
+} RAWMOUSE;
+
+typedef struct tagRAWKEYBOARD {
+ USHORT MakeCode;
+ USHORT Flags;
+ USHORT Reserved;
+ USHORT VKey;
+ UINT Message;
+ ULONG ExtraInformation;
+} RAWKEYBOARD;
+
+typedef struct tagRAWHID {
+ DWORD dwSizeHid;
+ DWORD dwCount;
+ BYTE bRawData[1];
+} RAWHID;
+
+typedef struct tagRAWINPUT {
+ RAWINPUTHEADER header;
+ union {
+ RAWMOUSE mouse;
+ RAWKEYBOARD keyboard;
+ RAWHID hid;
+ } data;
+} RAWINPUT;
+
+DECLARE_HANDLE(HRAWINPUT);
+#endif
+
+#ifdef FREE_WINDOWS
+#define NEED_RAW_PROC
+typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT);
+#define RegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize) ((pRegisterRawInputDevices)?pRegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize):0)
+
+
+typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT);
+#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1)
+#endif
class GHOST_EventButton;
class GHOST_EventCursor;
@@ -217,36 +304,24 @@ protected:
/**
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
* @param window-> The window for this handling
- * @param wParam The wParam from the wndproc
- * @param lParam The lParam from the wndproc
+ * @param vKey The virtual key from hardKey
+ * @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
+ * @param extend Flag if key is not primerly (left or right)
* @return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual GHOST_TKey convertKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const;
+ virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const;
/**
- * @param window The window for this handling
+ * Catches raw WIN32 key codes from WM_INPUT in the wndproc.
+ * @param window-> The window for this handling
* @param wParam The wParam from the wndproc
* @param lParam The lParam from the wndproc
- * @param oldModifiers The old modifiers
- * @param newModifiers The new modifiers
- */
- virtual void handleModifierKeys(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, GHOST_ModifierKeys &oldModifiers, GHOST_ModifierKeys &newModifiers) const;
- /**
- * Immediately push key event for given key
- * @param window The window for this handling
- * @param down Whether we send up or down event
- * @param key The key to send the event for
+ * @param keyDown Pointer flag that specify if a key is down
+ * @param vk Pointer to virtual key
+ * @return The GHOST key (GHOST_kKeyUnknown if no match).
*/
- virtual void triggerKey(GHOST_IWindow *window, bool down, GHOST_TKey key);
+ virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk);
- /**
- * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
- * With the modifier keys, we want to distinguish left and right keys.
- * Sometimes this is not possible (Windows ME for instance). Then, we want
- * events generated for both keys.
- * @param window The window receiving the event (the active window).
- */
- //GHOST_EventKey* processModifierKeys(GHOST_IWindow *window);
/**
* Creates mouse button event.
@@ -281,16 +356,16 @@ protected:
* @param wParam The wParam from the wndproc
* @param lParam The lParam from the wndproc
*/
- static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam);
+ static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
/**
* Process special keys (VK_OEM_*), to see if current key layout
* gives us anything special, like ! on french AZERTY.
* @param window The window receiving the event (the active window).
- * @param wParam The wParam from the wndproc
- * @param lParam The lParam from the wndproc
+ * @param vKey The virtual key from hardKey
+ * @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
*/
- virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) const;
+ virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const;
/**
* Creates a window event.
@@ -306,19 +381,6 @@ protected:
static void processMinMaxInfo(MINMAXINFO * minmax);
/**
- * Returns the local state of the modifier keys (from the message queue).
- * @param keys The state of the keys.
- */
- inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
-
- /**
- * Stores the state of the modifier keys locally.
- * For internal use only!
- * @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 handleKeyboardChange(void);
@@ -327,19 +389,12 @@ protected:
* Windows call back routine for our window class.
*/
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
- /**
- * Low-level inspection of keyboard events
- */
- static LRESULT CALLBACK s_llKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
-
+
/**
- * Check if any shiftkey is pressed
+ * Initiates WM_INPUT messages from keyboard
*/
- inline virtual bool shiftPressed(void);
+ GHOST_TInt32 initKeyboardRawInput(void);
- /** The current state of the modifier keys. */
- GHOST_ModifierKeys m_modifierKeys;
/** State variable set at initialization. */
bool m_hasPerformanceCounter;
/** High frequency timer variable. */
@@ -350,33 +405,30 @@ protected:
bool m_hasAltGr;
/** language identifier. */
WORD m_langId;
- /** holding hook handle for low-level keyboard handling */
- HHOOK m_llKeyboardHook;
- bool m_prevKeyStatus[255]; /* VK_* codes 0x01-0xFF, with 0xFF reserved */
- bool m_curKeyStatus[255]; /* VK_* codes 0x01-0xFF, with 0xFF reserved */
+ /** stores keyboard layout. */
+ HKL m_keylayout;
+
+ /** handle for user32.dll*/
+ HMODULE user32;
+ #ifdef NEED_RAW_PROC
+ /* pointer to RegisterRawInputDevices function */
+ LPFNDLLRRID pRegisterRawInputDevices;
+ /* pointer to GetRawInputData function */
+ LPFNDLLGRID pGetRawInputData;
+ #endif
};
-inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
-{
- keys = m_modifierKeys;
-}
-
-inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys)
-{
- m_modifierKeys = keys;
-}
-
inline void GHOST_SystemWin32::handleKeyboardChange(void)
{
- HKL keylayout = GetKeyboardLayout(0); // get keylayout for current thread
+ m_keylayout = GetKeyboardLayout(0); // get keylayout for current thread
int i;
SHORT s;
// save the language identifier.
- m_langId = LOWORD(keylayout);
+ m_langId = LOWORD(m_keylayout);
for(m_hasAltGr = false, i = 32; i < 256; ++i) {
- s = VkKeyScanEx((char)i, keylayout);
+ s = VkKeyScanEx((char)i, m_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
@@ -387,10 +439,5 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void)
}
}
-inline bool GHOST_SystemWin32::shiftPressed(void)
-{
- return (m_curKeyStatus[VK_SHIFT] || m_curKeyStatus[VK_RSHIFT] || m_curKeyStatus[VK_LSHIFT]);
-}
-
#endif // _GHOST_SYSTEM_WIN32_H_