From e557d4f28b1a78b68baba382ffb3d483d914ab8c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 19 Sep 2011 10:39:19 +0000 Subject: [PATCH] From Wojciech Lewandowski, "There was a bug in reading modifier keys when focus to GraphicsWindowWin32 was restored. Handler of WM_SETFOCUS was reading pressed keys and sending WM_KEYDOWN messages to fill initial keyboard state. But WM_KEYDOWN messages sent had 0 on lParam and adaptKey method computing state of modifier mask was using lParam to find which modifier keys are down. Obviously when lParam was 0 it was not recording proper modifier masks. This patch fixes this code sending proper lParam and also makes sure LEFT_CONTROL will be not confused with RIGHT_CONTROL." --- src/osgViewer/GraphicsWindowWin32.cpp | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index bbef9ce44..1fe7b6297 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -2565,7 +2565,6 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W /////////////////// case WM_SETFOCUS : /////////////////// - // Check keys and send a message if the key is pressed when the // focus comes back to the window. // I don't really like this hard-coded loop, but the key codes @@ -2573,8 +2572,32 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W // ok. See winuser.h for the key codes. for (unsigned int i = 0x08; i < 0xFF; i++) { - if ((::GetAsyncKeyState(i) & 0x8000) != 0) - ::SendMessage(hwnd, WM_KEYDOWN, i, 0); + // Wojciech Lewandowski: 2011/09/12 + // Skip CONTROL | MENU | SHIFT tests because we are polling exact left or right keys + // above return press for both right and left so we may end up with incosistent + // modifier mask if we report left control & right control while only right was pressed + LONG rightSideCode = 0; + switch( i ) + { + case VK_CONTROL: + case VK_SHIFT: + case VK_MENU: + continue; + + case VK_RCONTROL: + case VK_RSHIFT: + case VK_RMENU: + rightSideCode = 0x01000000; + } + if ((::GetAsyncKeyState(i) & 0x8000) != 0) + { + // Compute lParam because subsequent adaptKey will rely on correct lParam + UINT scanCode = ::MapVirtualKeyEx( i, 0, ::GetKeyboardLayout(0)); + // Set Extended Key bit + Scan Code + 30 bit to indicate key was set before sending message + // See Windows SDK help on WM_KEYDOWN for explanation + LONG lParam = rightSideCode | ( ( scanCode & 0xFF ) << 16 ) | (1 << 30); + ::SendMessage(hwnd, WM_KEYDOWN, i, lParam ); + } } break;