GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int *keyDown, char *vk) { GHOST_TKey key = GHOST_kKeyUnknown; if (!keyDown) return GHOST_kKeyUnknown; GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); GHOST_ModifierKeys modifiers; system->retrieveModifierKeys(modifiers); // RI_KEY_BREAK doesn't work for sticky keys release, so we also // check for the up message unsigned int msg = raw.data.keyboard.Message; *keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK) && msg != WM_KEYUP && msg != WM_SYSKEYUP; key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags & (RI_KEY_E1 | RI_KEY_E0))); // extra handling of modifier keys: don't send repeats out from GHOST if (key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) { bool changed = false; GHOST_TModifierKeyMask modifier; switch (key) { case GHOST_kKeyLeftShift: { changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); modifier = GHOST_kModifierKeyLeftShift; } break; case GHOST_kKeyRightShift: { changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); modifier = GHOST_kModifierKeyRightShift; } break; case GHOST_kKeyLeftControl: { changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); modifier = GHOST_kModifierKeyLeftControl; } break; case GHOST_kKeyRightControl: { changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); modifier = GHOST_kModifierKeyRightControl; } break; case GHOST_kKeyLeftAlt: { changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); modifier = GHOST_kModifierKeyLeftAlt; } break; case GHOST_kKeyRightAlt: { changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); modifier = GHOST_kModifierKeyRightAlt; } break; default: break; } if (changed) { modifiers.set(modifier, (bool)*keyDown); system->storeModifierKeys(modifiers); } else { key = GHOST_kKeyUnknown; } } if (vk) *vk = raw.data.keyboard.VKey; return key; }
GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) 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')) { // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0); } else if ((wParam >= 'A') && (wParam <= 'Z')) { // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA); } else if ((wParam >= VK_F1) && (wParam <= VK_F24)) { key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1); } else { switch (wParam) { case VK_RETURN: key = isExtended?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_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_SNAPSHOT: key = GHOST_kKeyPrintScreen; break; case VK_PAUSE: key = GHOST_kKeyPause; 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; case VK_SEMICOLON: key = GHOST_kKeySemicolon; break; case VK_EQUALS: key = GHOST_kKeyEqual; break; case VK_COMMA: key = GHOST_kKeyComma; break; case VK_MINUS: key = GHOST_kKeyMinus; break; case VK_PERIOD: key = GHOST_kKeyPeriod; break; case VK_SLASH: key = GHOST_kKeySlash; break; case VK_BACK_QUOTE: key = GHOST_kKeyAccentGrave; break; case VK_OPEN_BRACKET: key = GHOST_kKeyLeftBracket; break; case VK_BACK_SLASH: key = GHOST_kKeyBackslash; break; case VK_CLOSE_BRACKET: key = GHOST_kKeyRightBracket; break; case VK_QUOTE: key = GHOST_kKeyQuote; break; 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; } } } 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; } } } 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; } } } break; case VK_LWIN: case VK_RWIN: key = GHOST_kKeyOS; break; case VK_NUMLOCK: key = GHOST_kKeyNumLock; break; 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); break; default: key = GHOST_kKeyUnknown; break; } } ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); return key; }