Simplify GHOST modifier key handling on Windows.

This commit is contained in:
Nathan Letwory 2010-10-15 14:52:47 +00:00
parent 99bd5f2f3b
commit f631a8b5be
2 changed files with 69 additions and 158 deletions

@ -136,9 +136,7 @@
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0),
m_separateLeftRight(false),
m_separateLeftRightInitialized(false)
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
{
m_displayManager = new GHOST_DisplayManagerWin32 ();
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
@ -287,43 +285,24 @@ GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32
GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
{
if (m_separateLeftRight && m_separateLeftRightInitialized) {
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
keys.set(GHOST_kModifierKeyLeftShift, down);
down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
keys.set(GHOST_kModifierKeyRightShift, down);
down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
keys.set(GHOST_kModifierKeyLeftAlt, down);
down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
keys.set(GHOST_kModifierKeyRightAlt, down);
down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 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)
keys.set(GHOST_kModifierKeyOS, true);
else
keys.set(GHOST_kModifierKeyOS, false);
}
else {
bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
keys.set(GHOST_kModifierKeyLeftShift, down);
keys.set(GHOST_kModifierKeyRightShift, down);
down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
keys.set(GHOST_kModifierKeyLeftAlt, down);
keys.set(GHOST_kModifierKeyRightAlt, down);
down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
keys.set(GHOST_kModifierKeyLeftControl, down);
keys.set(GHOST_kModifierKeyRightControl, down);
bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
if(lwindown || rwindown)
keys.set(GHOST_kModifierKeyOS, true);
else
keys.set(GHOST_kModifierKeyOS, false);
}
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
keys.set(GHOST_kModifierKeyLeftShift, down);
down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
keys.set(GHOST_kModifierKeyRightShift, down);
down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
keys.set(GHOST_kModifierKeyLeftAlt, down);
down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
keys.set(GHOST_kModifierKeyRightAlt, down);
down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 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)
keys.set(GHOST_kModifierKeyOS, true);
else
keys.set(GHOST_kModifierKeyOS, false);
return GHOST_kSuccess;
}
@ -405,6 +384,10 @@ GHOST_TSuccess GHOST_SystemWin32::exit()
GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
{
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')) {
@ -469,15 +452,43 @@ GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
case VK_QUOTE: key = GHOST_kKeyQuote; break;
case VK_GR_LESS: key = GHOST_kKeyGrLess; break;
// Process these keys separately because we need to distinguish right from left modifier keys
case VK_SHIFT:
{
bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftShift) != newModifiers.get(GHOST_kModifierKeyLeftShift);
if(lchanged) {
key = GHOST_kKeyLeftShift;
} else {
key = GHOST_kKeyRightShift;
}
}
break;
case VK_CONTROL:
{
bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftControl) != newModifiers.get(GHOST_kModifierKeyLeftControl);
if(lchanged) {
key = GHOST_kKeyLeftControl;
} else {
key = GHOST_kKeyRightControl;
}
}
break;
case VK_MENU:
// Ignore these keys
case VK_NUMLOCK:
case VK_SCROLL:
case VK_CAPITAL:
{
bool lchanged = oldModifiers.get(GHOST_kModifierKeyLeftAlt) != newModifiers.get(GHOST_kModifierKeyLeftAlt);
if(lchanged) {
key = GHOST_kKeyLeftAlt;
} else {
key = GHOST_kKeyRightAlt;
}
}
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;
default:
key = GHOST_kKeyUnknown;
break;
@ -486,38 +497,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
return key;
}
void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
{
GHOST_ModifierKeys oldModifiers, newModifiers;
// Retrieve old state of the modifier keys
((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
// Retrieve current state of the modifier keys
((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
// Compare the old and the new
if (!newModifiers.equals(oldModifiers)) {
// Create events for the masks that changed
for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
// Convert the mask to a key code
GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
GHOST_EventKey* event;
if (key != GHOST_kKeyUnknown) {
// Create an event
event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
pushEvent(event);
}
}
}
}
// Store new modifier keys state
((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
}
GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
{
return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
@ -655,85 +634,22 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
// Keyboard events, processed
////////////////////////////////////////////////////////////////////////
case WM_KEYDOWN:
/* The WM_KEYDOWN message is posted to the window with the keyboard focus when a
* nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
* key is not pressed.
*/
case WM_SYSKEYDOWN:
/* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when
* the user presses the F10 key (which activates the menu bar) or holds down the
* alt key and then presses another key. It also occurs when no window currently
* has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the
* active window. The window that receives the message can distinguish between these
* two contexts by checking the context code in the lKeyData parameter.
*/
switch (wParam) {
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
case VK_LWIN:
case VK_RWIN:
if (!system->m_separateLeftRightInitialized) {
// Check whether this system supports separate left and right keys
switch (wParam) {
case VK_SHIFT:
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
(HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
true : false;
break;
case VK_CONTROL:
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
(HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
true : false;
break;
case VK_MENU:
system->m_separateLeftRight =
(HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
(HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
true : false;
break;
case VK_LWIN:
case VK_RWIN:
system->m_separateLeftRight = true;
break;
}
system->m_separateLeftRightInitialized = true;
}
system->processModifierKeys(window);
// Bypass call to DefWindowProc
return 0;
default:
event = processKeyEvent(window, true, wParam, lParam);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;
}
event = processKeyEvent(window, true, 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:
switch (wParam) {
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
case VK_LWIN:
case VK_RWIN:
system->processModifierKeys(window);
// Bypass call to DefWindowProc
return 0;
default:
event = processKeyEvent(window, false, wParam, lParam);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;
event = processKeyEvent(window, false, wParam, lParam);
if (!event) {
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
GHOST_PRINT(msg)
GHOST_PRINT(" key ignored\n")
}
break;

@ -248,7 +248,7 @@ protected:
* events generated for both keys.
* @param window The window receiving the event (the active window).
*/
void processModifierKeys(GHOST_IWindow *window);
GHOST_EventKey* processModifierKeys(GHOST_IWindow *window);
/**
* Creates mouse button event.
@ -324,11 +324,6 @@ protected:
__int64 m_freq;
/** High frequency timer variable. */
__int64 m_start;
/** Stores the capability of this system to distinguish left and right modifier keys. */
bool m_separateLeftRight;
/** Stores the initialization state of the member m_leftRightDistinguishable. */
bool m_separateLeftRightInitialized;
};
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const