now synthesizing key release events for each pressed key when

the client screen is closed.  this fixes the bug where the
client's keyboard was left with some keys logically pressed
when the client died (e.g. using ctrl+c on the client program
from the server's keyboard would leave the ctrl key logically
pressed).
This commit is contained in:
crs 2002-07-01 13:03:16 +00:00
parent a0eba4c337
commit e267d1dc1c
5 changed files with 82 additions and 2 deletions

View File

@ -111,6 +111,9 @@ CMSWindowsSecondaryScreen::close()
{
assert(m_client != NULL);
// release keys that are logically pressed
releaseKeys();
// restore the screen saver settings
getScreenSaver()->enable();
@ -1698,6 +1701,57 @@ CMSWindowsSecondaryScreen::doKeystrokes(const Keystrokes& keys, SInt32 count)
}
}
void
CMSWindowsSecondaryScreen::releaseKeys()
{
CLock lock(&m_mutex);
syncDesktop();
// release left/right modifier keys first. if the platform doesn't
// support them then they won't be set and the non-side-distinuishing
// key will retain its state. if the platform does support them then
// the non-side-distinguishing will be reset.
if ((m_keys[VK_LSHIFT] & 0x80) != 0) {
sendKeyEvent(VK_LSHIFT, false);
m_keys[VK_SHIFT] = 0;
m_keys[VK_LSHIFT] = 0;
}
if ((m_keys[VK_RSHIFT] & 0x80) != 0) {
sendKeyEvent(VK_RSHIFT, false);
m_keys[VK_SHIFT] = 0;
m_keys[VK_RSHIFT] = 0;
}
if ((m_keys[VK_LCONTROL] & 0x80) != 0) {
sendKeyEvent(VK_LCONTROL, false);
m_keys[VK_CONTROL] = 0;
m_keys[VK_LCONTROL] = 0;
}
if ((m_keys[VK_RCONTROL] & 0x80) != 0) {
sendKeyEvent(VK_RCONTROL, false);
m_keys[VK_CONTROL] = 0;
m_keys[VK_RCONTROL] = 0;
}
if ((m_keys[VK_LMENU] & 0x80) != 0) {
sendKeyEvent(VK_LMENU, false);
m_keys[VK_MENU] = 0;
m_keys[VK_LMENU] = 0;
}
if ((m_keys[VK_RMENU] & 0x80) != 0) {
sendKeyEvent(VK_RMENU, false);
m_keys[VK_MENU] = 0;
m_keys[VK_RMENU] = 0;
}
// now check all the other keys
for (UInt32 i = 0; i < sizeof(m_keys) / sizeof(m_keys[0]); ++i) {
if ((m_keys[i] & 0x80) != 0) {
sendKeyEvent(i, false);
m_keys[i] = 0;
}
}
}
void
CMSWindowsSecondaryScreen::updateKeys()
{

View File

@ -85,6 +85,7 @@ private:
KeyModifierMask, EKeyAction) const;
void doKeystrokes(const Keystrokes&, SInt32 count);
void releaseKeys();
void updateKeys();
void updateModifiers();
void toggleKey(UINT virtualKey, KeyModifierMask mask);

View File

@ -130,6 +130,9 @@ CXWindowsSecondaryScreen::close()
{
assert(m_client != NULL);
// release keys that are logically pressed
releaseKeys();
// restore the screen saver settings
getScreenSaver()->enable();
@ -847,6 +850,24 @@ CXWindowsSecondaryScreen::maskToX(KeyModifierMask inMask) const
return outMask;
}
void
CXWindowsSecondaryScreen::releaseKeys()
{
CDisplayLock display(this);
// key up for each key that's down
for (UInt32 i = 0; i < 256; ++i) {
if (m_keys[i]) {
XTestFakeKeyEvent(display, i, False, CurrentTime);
m_keys[i] = false;
}
}
// update
XSync(display, False);
}
void
CXWindowsSecondaryScreen::updateKeys(Display* display)
{
@ -855,7 +876,7 @@ CXWindowsSecondaryScreen::updateKeys(Display* display)
XQueryKeymap(display, keys);
// transfer to our state
for (unsigned int i = 0, j = 0; i < 32; j += 8, ++i) {
for (UInt32 i = 0, j = 0; i < 32; j += 8, ++i) {
m_keys[j + 0] = ((keys[i] & 0x01) != 0);
m_keys[j + 1] = ((keys[i] & 0x02) != 0);
m_keys[j + 2] = ((keys[i] & 0x04) != 0);

View File

@ -72,6 +72,7 @@ private:
void doKeystrokes(const Keystrokes&, SInt32 count);
unsigned int maskToX(KeyModifierMask) const;
void releaseKeys();
void updateKeys(Display* display);
void updateKeycodeMap(Display* display);
void updateModifiers(Display* display);

View File

@ -27,7 +27,10 @@ public:
// stolen and screen size changed).
virtual void open(CClient*) = 0;
// close the screen. should restore the screen saver.
// close the screen. should restore the screen saver. it should
// also simulate key up events for any keys that have simulate key
// down events without a matching key up. without this the client
// will leave its keyboard in the wrong logical state.
virtual void close() = 0;
// called when the user navigates to the secondary screen. warp