issue #4060 - Key stuck down on Windows server

finished solving issue.
This commit is contained in:
jerry 2014-05-23 15:01:29 +00:00
parent 5545d8af2a
commit 1dfe867c54
5 changed files with 62 additions and 3 deletions

View File

@ -909,7 +909,10 @@ CMSWindowsKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const
}
for (KeyButton i = 1; i < 256; ++i) {
if ((keyState[i] & 0x80) != 0) {
pressedKeys.insert(i);
KeyButton keyButton = virtualKeyToButton(i);
if (keyButton != 0) {
pressedKeys.insert(keyButton);
}
}
}
}
@ -1344,6 +1347,12 @@ CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button)
return s_virtualKey[virtualKey];
}
UINT
CMSWindowsKeyState::mapButtonToVirtualKey(KeyButton button) const
{
return m_buttonToVK[button];
}
KeyID
CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item,
KeyButton button, UINT virtualKey,

View File

@ -124,6 +124,14 @@ public:
*/
static KeyID getKeyID(UINT virtualKey, KeyButton button);
//! Map button to virtual key
/*!
Returns the virtual key for button \p button
(button should include the extended key bit), or kKeyNone if there is
no such key.
*/
UINT mapButtonToVirtualKey(KeyButton button) const;
//@}
// IKeyState overrides

View File

@ -46,6 +46,7 @@
#include <pbt.h>
#include <Shlobj.h>
#include <comutil.h>
#include <algorithm>
//
// add backwards compatible multihead support (and suppress bogus warning).
@ -302,7 +303,10 @@ CMSWindowsScreen::enter()
// all messages prior to now are invalid
nextMark();
} else {
m_primaryKeyDownList.clear();
}
else {
// Entering a secondary screen. Ensure that no screensaver is active
// and that the screen is not in powersave mode.
CArchMiscWindows::wakeupDisplay();
@ -351,6 +355,14 @@ CMSWindowsScreen::leave()
m_keyState->saveModifiers();
m_hook.setMode(kHOOK_RELAY_EVENTS);
m_primaryKeyDownList.clear();
for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
if (m_keyState->isKeyDown(i)) {
m_primaryKeyDownList.push_back(i);
LOG((CLOG_DEBUG1 "key button %d is down before leaving to another screen", i));
}
}
}
// now off screen
@ -1137,6 +1149,18 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
// record keyboard state
m_keyState->onKey(button, down, oldState);
if (!down && m_isPrimary && !m_isOnScreen) {
PrimaryKeyDownList::iterator find = std::find(m_primaryKeyDownList.begin(), m_primaryKeyDownList.end(), button);
if (find != m_primaryKeyDownList.end()) {
LOG((CLOG_DEBUG1 "release key button %d on primary", *find));
m_hook.setMode(kHOOK_WATCH_JUMP_ZONE);
fakeLocalKey(*find, false);
m_primaryKeyDownList.erase(find);
m_hook.setMode(kHOOK_RELAY_EVENTS);
return true;
}
}
// windows doesn't tell us the modifier key state on mouse or key
// events so we have to figure it out. most apps would use
// GetKeyState() or even GetAsyncKeyState() for that but we can't
@ -1802,6 +1826,19 @@ CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return result;
}
void
CMSWindowsScreen::fakeLocalKey(KeyButton button, bool press) const
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = m_keyState->mapButtonToVirtualKey(button);
DWORD pressFlag = press ? KEYEVENTF_EXTENDEDKEY : KEYEVENTF_KEYUP;
input.ki.dwFlags = pressFlag;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
SendInput(1,&input,sizeof(input));
}
//
// CMSWindowsScreen::CHotKeyItem
//

View File

@ -127,6 +127,9 @@ protected:
virtual void updateButtons();
virtual IKeyState* getKeyState() const;
// simulate a local key to the system directly
void fakeLocalKey(KeyButton button, bool press) const;
private:
// initialization and shutdown operations
HCURSOR createBlankCursor() const;
@ -236,6 +239,7 @@ private:
typedef std::map<UInt32, CHotKeyItem> HotKeyMap;
typedef std::vector<UInt32> HotKeyIDList;
typedef std::map<CHotKeyItem, UInt32> HotKeyToIDMap;
typedef std::vector<KeyButton> PrimaryKeyDownList;
static HINSTANCE s_windowInstance;
@ -335,4 +339,6 @@ private:
const int m_dropWindowSize;
CThread* m_sendDragThread;
PrimaryKeyDownList m_primaryKeyDownList;
};

View File

@ -903,7 +903,6 @@ CKeyState::updateModifierKeyState(KeyButton button,
}
}
//
// CKeyState::CAddActiveModifierContext
//