Fixes for win32 key handling.
This commit is contained in:
parent
f3c70dc300
commit
4d11079095
|
@ -5,6 +5,7 @@
|
||||||
#include "CThread.h"
|
#include "CThread.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CMSWindowsSecondaryScreen
|
// CMSWindowsSecondaryScreen
|
||||||
|
@ -40,7 +41,7 @@ static BOOL CALLBACK WINAPI debugProc(HWND, UINT msg, WPARAM wParam, LPARAM lPar
|
||||||
|
|
||||||
case WM_APP:
|
case WM_APP:
|
||||||
if (!s_logMore.empty()) {
|
if (!s_logMore.empty()) {
|
||||||
if (s_log.size() > 20000)
|
if (s_log.size() > 40000)
|
||||||
s_log = s_logMore;
|
s_log = s_logMore;
|
||||||
else
|
else
|
||||||
s_log += s_logMore;
|
s_log += s_logMore;
|
||||||
|
@ -189,15 +190,12 @@ void CMSWindowsSecondaryScreen::keyDown(
|
||||||
|
|
||||||
// get the sequence of keys to simulate key press and the final
|
// get the sequence of keys to simulate key press and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
m_mask = mapKey(keys, virtualKey, key, mask, true);
|
m_mask = mapKey(keys, virtualKey, key, mask, kPress);
|
||||||
if (keys.empty())
|
if (keys.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// generate key events
|
// generate key events
|
||||||
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ++k) {
|
doKeystrokes(keys, 1);
|
||||||
const UINT code = MapVirtualKey(k->first, 0);
|
|
||||||
keybd_event(k->first, code, k->second ? 0 : KEYEVENTF_KEYUP, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that key is now down
|
// note that key is now down
|
||||||
m_keys[virtualKey] |= 0x80;
|
m_keys[virtualKey] |= 0x80;
|
||||||
|
@ -209,22 +207,14 @@ void CMSWindowsSecondaryScreen::keyRepeat(
|
||||||
Keystrokes keys;
|
Keystrokes keys;
|
||||||
UINT virtualKey;
|
UINT virtualKey;
|
||||||
|
|
||||||
// get the sequence of keys to simulate key release and the final
|
// get the sequence of keys to simulate key repeat and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
m_mask = mapKey(keys, virtualKey, key, mask, true);
|
m_mask = mapKey(keys, virtualKey, key, mask, kRepeat);
|
||||||
if (keys.empty())
|
if (keys.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// generate key events
|
// generate key events
|
||||||
// YYY -- need to know which code in Keystrokes should be repeated;
|
doKeystrokes(keys, count);
|
||||||
// then repeat only that key count times
|
|
||||||
for (SInt32 i = 0; i < count; ++i) {
|
|
||||||
for (Keystrokes::const_iterator k = keys.begin();
|
|
||||||
k != keys.end(); ++k) {
|
|
||||||
const UINT code = MapVirtualKey(k->first, 0);
|
|
||||||
keybd_event(k->first, code, k->second ? 0 : KEYEVENTF_KEYUP, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::keyUp(
|
void CMSWindowsSecondaryScreen::keyUp(
|
||||||
|
@ -235,15 +225,12 @@ void CMSWindowsSecondaryScreen::keyUp(
|
||||||
|
|
||||||
// get the sequence of keys to simulate key release and the final
|
// get the sequence of keys to simulate key release and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
m_mask = mapKey(keys, virtualKey, key, mask, false);
|
m_mask = mapKey(keys, virtualKey, key, mask, kRelease);
|
||||||
if (keys.empty())
|
if (keys.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// generate key events
|
// generate key events
|
||||||
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ++k) {
|
doKeystrokes(keys, 1);
|
||||||
const UINT code = MapVirtualKey(k->first, 0);
|
|
||||||
keybd_event(k->first, code, k->second ? 0 : KEYEVENTF_KEYUP, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that key is now up
|
// note that key is now up
|
||||||
m_keys[virtualKey] &= ~0x80;
|
m_keys[virtualKey] &= ~0x80;
|
||||||
|
@ -252,7 +239,7 @@ void CMSWindowsSecondaryScreen::keyUp(
|
||||||
void CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
void CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||||
{
|
{
|
||||||
// map button id to button flag
|
// map button id to button flag
|
||||||
DWORD flags = mapButton(button);
|
DWORD flags = mapButton(button, true);
|
||||||
|
|
||||||
// send event
|
// send event
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
|
@ -262,7 +249,7 @@ void CMSWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||||
void CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
|
void CMSWindowsSecondaryScreen::mouseUp(ButtonID button)
|
||||||
{
|
{
|
||||||
// map button id to button flag
|
// map button id to button flag
|
||||||
DWORD flags = mapButton(button);
|
DWORD flags = mapButton(button, false);
|
||||||
|
|
||||||
// send event
|
// send event
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
|
@ -786,7 +773,7 @@ static const UINT g_function[] =
|
||||||
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x20 */ VK_TAB, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x28 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -815,10 +802,6 @@ static const UINT g_function[] =
|
||||||
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
/* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
/* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
// FIXME -- will this work?
|
|
||||||
// 0x100 + = shift
|
|
||||||
// 0x200 + = ctrl
|
|
||||||
// 0x400 + = alt
|
|
||||||
/* XK_KP_Space to XK_KP_Equal */
|
/* XK_KP_Space to XK_KP_Equal */
|
||||||
static const UINT g_miscellany[] =
|
static const UINT g_miscellany[] =
|
||||||
{
|
{
|
||||||
|
@ -919,18 +902,18 @@ static const UINT* g_mapTable[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
DWORD CMSWindowsSecondaryScreen::mapButton(
|
DWORD CMSWindowsSecondaryScreen::mapButton(
|
||||||
ButtonID button) const
|
ButtonID button, bool press) const
|
||||||
{
|
{
|
||||||
// map button id to button flag
|
// map button id to button flag
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case kButtonLeft:
|
case kButtonLeft:
|
||||||
return MOUSEEVENTF_LEFTDOWN;
|
return press ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
|
||||||
|
|
||||||
case kButtonMiddle:
|
case kButtonMiddle:
|
||||||
return MOUSEEVENTF_MIDDLEDOWN;
|
return press ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
|
||||||
|
|
||||||
case kButtonRight:
|
case kButtonRight:
|
||||||
return MOUSEEVENTF_RIGHTDOWN;
|
return press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -941,7 +924,7 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
Keystrokes& keys,
|
Keystrokes& keys,
|
||||||
UINT& virtualKey,
|
UINT& virtualKey,
|
||||||
KeyID id, KeyModifierMask mask,
|
KeyID id, KeyModifierMask mask,
|
||||||
bool press) const
|
EKeyAction action) const
|
||||||
{
|
{
|
||||||
// lookup the key table
|
// lookup the key table
|
||||||
const UInt32 mapID = ((id >> 8) & 0xff);
|
const UInt32 mapID = ((id >> 8) & 0xff);
|
||||||
|
@ -959,17 +942,20 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
(KeyModifierCapsLock |
|
(KeyModifierCapsLock |
|
||||||
KeyModifierNumLock |
|
KeyModifierNumLock |
|
||||||
KeyModifierScrollLock));
|
KeyModifierScrollLock));
|
||||||
|
log((CLOG_DEBUG2 "key id %d -> virtual key %d", id, virtualKey));
|
||||||
|
|
||||||
// if not in map then ask system to convert ascii character
|
// if not in map then ask system to convert ascii character
|
||||||
if (virtualKey == 0) {
|
if (virtualKey == 0) {
|
||||||
if (mapID != 0) {
|
if (mapID != 0) {
|
||||||
// not ascii
|
// not ascii
|
||||||
|
log((CLOG_DEBUG2 "not ascii"));
|
||||||
return m_mask;
|
return m_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate. return no keys if unknown key.
|
// translate. return no keys if unknown key.
|
||||||
SHORT vk = VkKeyScan(code);
|
SHORT vk = VkKeyScan(code);
|
||||||
if (vk == 0xffff) {
|
if (vk == 0xffff) {
|
||||||
|
log((CLOG_DEBUG2 "no virtual key for character %d", code));
|
||||||
return m_mask;
|
return m_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,11 +966,30 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
outMask |= KeyModifierControl;
|
outMask |= KeyModifierControl;
|
||||||
if (HIBYTE(vk) & 4)
|
if (HIBYTE(vk) & 4)
|
||||||
outMask |= KeyModifierAlt;
|
outMask |= KeyModifierAlt;
|
||||||
|
log((CLOG_DEBUG2 "character %d to virtual key %d mask 0x%04x", code, LOBYTE(vk), outMask));
|
||||||
|
|
||||||
// if caps-lock is on and so is shift then turn off caps-lock
|
// handle combination of caps-lock and shift. if caps-lock is
|
||||||
if (outMask & (KeyModifierShift | KeyModifierCapsLock) ==
|
// off locally then use shift as necessary. if caps-lock is on
|
||||||
(KeyModifierShift | KeyModifierCapsLock))
|
// locally then shift reverses its meaning (for keys that are
|
||||||
outMask &= ~KeyModifierCapsLock;
|
// subject to case conversion).
|
||||||
|
if ((m_mask & KeyModifierCapsLock) != 0) {
|
||||||
|
// caps-lock is on. note if shift is required.
|
||||||
|
log((CLOG_DEBUG2 "caps-lock is on"));
|
||||||
|
const bool needShift = ((outMask & KeyModifierShift) != 0);
|
||||||
|
|
||||||
|
// if needShift is true then see if the key is subject to
|
||||||
|
// case conversion. if it is then caps-lock and shift
|
||||||
|
// cancel out. if not then caps-lock is ignored and shift
|
||||||
|
// is required.
|
||||||
|
if (needShift) {
|
||||||
|
// FIXME -- there should be some system call to test
|
||||||
|
// if a key is subject to case conversion.
|
||||||
|
if (tolower(code) != toupper(code)) {
|
||||||
|
log((CLOG_DEBUG2 "turn off shift"));
|
||||||
|
outMask &= ~KeyModifierShift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get virtual key
|
// get virtual key
|
||||||
virtualKey = LOBYTE(vk);
|
virtualKey = LOBYTE(vk);
|
||||||
|
@ -1001,11 +1006,22 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
// virtual keys but not for numeric keys.
|
// virtual keys but not for numeric keys.
|
||||||
if (virtualKey >= VK_NUMPAD0 && virtualKey <= VK_DIVIDE) {
|
if (virtualKey >= VK_NUMPAD0 && virtualKey <= VK_DIVIDE) {
|
||||||
// set required shift state based on current numlock state
|
// set required shift state based on current numlock state
|
||||||
if ((outMask & KeyModifierNumLock) == 0)
|
if ((outMask & KeyModifierNumLock) == 0) {
|
||||||
|
if ((m_mask & KeyModifierNumLock) == 0) {
|
||||||
|
log((CLOG_DEBUG2 "turn on num lock for keypad key"));
|
||||||
|
outMask |= KeyModifierNumLock;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log((CLOG_DEBUG2 "turn on shift for keypad key"));
|
||||||
outMask |= KeyModifierShift;
|
outMask |= KeyModifierShift;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME -- should check for LeftTab KeySym
|
// check for ISO_Left_Tab
|
||||||
|
else if (id == 0xfe20) {
|
||||||
|
outMask |= KeyModifierShift;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a list of modifier key info
|
// a list of modifier key info
|
||||||
|
@ -1078,6 +1094,7 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
// a modifier key then skip this because modifiers should not
|
// a modifier key then skip this because modifiers should not
|
||||||
// modify modifiers.
|
// modify modifiers.
|
||||||
Keystrokes undo;
|
Keystrokes undo;
|
||||||
|
Keystroke keystroke;
|
||||||
if (outMask != m_mask && !isModifier) {
|
if (outMask != m_mask && !isModifier) {
|
||||||
for (unsigned int i = 0; i < s_numModifiers; ++i) {
|
for (unsigned int i = 0; i < s_numModifiers; ++i) {
|
||||||
KeyModifierMask bit = s_modifier[i].mask;
|
KeyModifierMask bit = s_modifier[i].mask;
|
||||||
|
@ -1087,15 +1104,20 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
// modifier is a toggle then toggle it on with a
|
// modifier is a toggle then toggle it on with a
|
||||||
// press/release, otherwise activate it with a
|
// press/release, otherwise activate it with a
|
||||||
// press.
|
// press.
|
||||||
const UINT modifierKey = s_modifier[i].virtualKey;
|
keystroke.m_virtualKey = s_modifier[i].virtualKey;
|
||||||
keys.push_back(std::make_pair(modifierKey, true));
|
keystroke.m_press = true;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
if (s_modifier[i].isToggle) {
|
if (s_modifier[i].isToggle) {
|
||||||
keys.push_back(std::make_pair(modifierKey, false));
|
keystroke.m_press = false;
|
||||||
undo.push_back(std::make_pair(modifierKey, false));
|
keys.push_back(keystroke);
|
||||||
undo.push_back(std::make_pair(modifierKey, true));
|
undo.push_back(keystroke);
|
||||||
|
keystroke.m_press = true;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
undo.push_back(std::make_pair(modifierKey, false));
|
keystroke.m_press = false;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,22 +1128,34 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
// release. we must check each keycode for the
|
// release. we must check each keycode for the
|
||||||
// modifier if not a toggle.
|
// modifier if not a toggle.
|
||||||
if (s_modifier[i].isToggle) {
|
if (s_modifier[i].isToggle) {
|
||||||
const UINT modifierKey = s_modifier[i].virtualKey;
|
keystroke.m_virtualKey = s_modifier[i].virtualKey;
|
||||||
keys.push_back(std::make_pair(modifierKey, true));
|
keystroke.m_press = true;
|
||||||
keys.push_back(std::make_pair(modifierKey, false));
|
keystroke.m_repeat = false;
|
||||||
undo.push_back(std::make_pair(modifierKey, false));
|
keys.push_back(keystroke);
|
||||||
undo.push_back(std::make_pair(modifierKey, true));
|
keystroke.m_press = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
undo.push_back(keystroke);
|
||||||
|
keystroke.m_press = true;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UINT key = s_modifier[i].virtualKey;
|
UINT key = s_modifier[i].virtualKey;
|
||||||
if ((m_keys[key] & 0x80) != 0) {
|
if ((m_keys[key] & 0x80) != 0) {
|
||||||
keys.push_back(std::make_pair(key, false));
|
keystroke.m_virtualKey = key;
|
||||||
undo.push_back(std::make_pair(key, true));
|
keystroke.m_press = false;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = true;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
key = s_modifier[i].virtualKey2;
|
key = s_modifier[i].virtualKey2;
|
||||||
if ((m_keys[key] & 0x80) != 0) {
|
if (key != 0 && (m_keys[key] & 0x80) != 0) {
|
||||||
keys.push_back(std::make_pair(key, false));
|
keystroke.m_virtualKey = key;
|
||||||
undo.push_back(std::make_pair(key, true));
|
keystroke.m_press = false;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = true;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1130,7 +1164,26 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the key event
|
// add the key event
|
||||||
keys.push_back(std::make_pair(virtualKey, press));
|
keystroke.m_virtualKey = virtualKey;
|
||||||
|
switch (action) {
|
||||||
|
case kPress:
|
||||||
|
keystroke.m_press = true;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kRelease:
|
||||||
|
keystroke.m_press = false;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kRepeat:
|
||||||
|
keystroke.m_press = true;
|
||||||
|
keystroke.m_repeat = true;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// add key events to restore the modifier state. apply events in
|
// add key events to restore the modifier state. apply events in
|
||||||
// the reverse order that they're stored in undo.
|
// the reverse order that they're stored in undo.
|
||||||
|
@ -1142,16 +1195,15 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
// if the key is a modifier key then compute the modifier mask after
|
// if the key is a modifier key then compute the modifier mask after
|
||||||
// this key is pressed.
|
// this key is pressed.
|
||||||
mask = m_mask;
|
mask = m_mask;
|
||||||
if (isModifier) {
|
if (isModifier && action != kRepeat) {
|
||||||
// toggle keys modify the state on press if toggling on and on
|
// toggle keys modify the state on release. other keys set
|
||||||
// release if toggling off. other keys set the bit on press
|
// the bit on press and clear the bit on release.
|
||||||
// and clear the bit on release.
|
|
||||||
// FIXME -- verify if that's true on win32
|
|
||||||
if (s_modifier[modifierIndex].isToggle) {
|
if (s_modifier[modifierIndex].isToggle) {
|
||||||
if (((mask & s_modifier[modifierIndex].mask) == 0) == press)
|
if (action == kRelease) {
|
||||||
mask ^= s_modifier[modifierIndex].mask;
|
mask ^= s_modifier[modifierIndex].mask;
|
||||||
}
|
}
|
||||||
else if (press) {
|
}
|
||||||
|
else if (action == kPress) {
|
||||||
mask |= s_modifier[modifierIndex].mask;
|
mask |= s_modifier[modifierIndex].mask;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1161,7 +1213,8 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
if ((m_keys[s_modifier[modifierIndex].virtualKey] & 0x80) != 0) {
|
if ((m_keys[s_modifier[modifierIndex].virtualKey] & 0x80) != 0) {
|
||||||
down = true;
|
down = true;
|
||||||
}
|
}
|
||||||
if ((m_keys[s_modifier[modifierIndex].virtualKey2] & 0x80) != 0) {
|
if (s_modifier[modifierIndex].virtualKey2 != 0 &&
|
||||||
|
(m_keys[s_modifier[modifierIndex].virtualKey2] & 0x80) != 0) {
|
||||||
down = true;
|
down = true;
|
||||||
}
|
}
|
||||||
if (!down)
|
if (!down)
|
||||||
|
@ -1169,12 +1222,65 @@ KeyModifierMask CMSWindowsSecondaryScreen::mapKey(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log((CLOG_DEBUG2 "previous modifiers 0x%04x, final modifiers 0x%04x", m_mask, mask));
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMSWindowsSecondaryScreen::doKeystrokes(
|
||||||
|
const Keystrokes& keys, SInt32 count)
|
||||||
|
{
|
||||||
|
// do nothing if no keys or no repeats
|
||||||
|
if (count < 1 || keys.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// generate key events
|
||||||
|
for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) {
|
||||||
|
if (k->m_repeat) {
|
||||||
|
// repeat from here up to but not including the next key
|
||||||
|
// with m_repeat == false count times.
|
||||||
|
Keystrokes::const_iterator start = k;
|
||||||
|
for (; count > 0; --count) {
|
||||||
|
// send repeating events
|
||||||
|
for (k = start; k != keys.end() && k->m_repeat; ++k) {
|
||||||
|
const UINT code = MapVirtualKey(k->m_virtualKey, 0);
|
||||||
|
keybd_event(k->m_virtualKey, code,
|
||||||
|
k->m_press ? 0 : KEYEVENTF_KEYUP, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note -- k is now on the first non-repeat key after the
|
||||||
|
// repeat keys, exactly where we'd like to continue from.
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// send event
|
||||||
|
const UINT code = MapVirtualKey(k->m_virtualKey, 0);
|
||||||
|
keybd_event(k->m_virtualKey, code,
|
||||||
|
k->m_press ? 0 : KEYEVENTF_KEYUP, 0);
|
||||||
|
|
||||||
|
// next key
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::updateKeys()
|
void CMSWindowsSecondaryScreen::updateKeys()
|
||||||
{
|
{
|
||||||
GetKeyboardState(m_keys);
|
// GetKeyboardKeys() doesn't seem to do the expected thing
|
||||||
|
memset(m_keys, 0, sizeof(m_keys));
|
||||||
|
m_keys[VK_LSHIFT] = GetKeyState(VK_LSHIFT);
|
||||||
|
m_keys[VK_RSHIFT] = GetKeyState(VK_RSHIFT);
|
||||||
|
m_keys[VK_SHIFT] = GetKeyState(VK_SHIFT);
|
||||||
|
m_keys[VK_LCONTROL] = GetKeyState(VK_LCONTROL);
|
||||||
|
m_keys[VK_RCONTROL] = GetKeyState(VK_RCONTROL);
|
||||||
|
m_keys[VK_CONTROL] = GetKeyState(VK_CONTROL);
|
||||||
|
m_keys[VK_LMENU] = GetKeyState(VK_LMENU);
|
||||||
|
m_keys[VK_RMENU] = GetKeyState(VK_RMENU);
|
||||||
|
m_keys[VK_MENU] = GetKeyState(VK_MENU);
|
||||||
|
m_keys[VK_LWIN] = GetKeyState(VK_LWIN);
|
||||||
|
m_keys[VK_RWIN] = GetKeyState(VK_RWIN);
|
||||||
|
m_keys[VK_CAPITAL] = GetKeyState(VK_CAPITAL);
|
||||||
|
m_keys[VK_NUMLOCK] = GetKeyState(VK_NUMLOCK);
|
||||||
|
m_keys[VK_SCROLL] = GetKeyState(VK_SCROLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::updateModifiers()
|
void CMSWindowsSecondaryScreen::updateModifiers()
|
||||||
|
@ -1195,6 +1301,7 @@ void CMSWindowsSecondaryScreen::updateModifiers()
|
||||||
m_mask |= KeyModifierNumLock;
|
m_mask |= KeyModifierNumLock;
|
||||||
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
if ((m_keys[VK_SCROLL] & 0x01) != 0)
|
||||||
m_mask |= KeyModifierScrollLock;
|
m_mask |= KeyModifierScrollLock;
|
||||||
|
log((CLOG_DEBUG2 "modifiers on update: 0x%04x", m_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMSWindowsSecondaryScreen::toggleKey(
|
void CMSWindowsSecondaryScreen::toggleKey(
|
||||||
|
|
|
@ -40,12 +40,19 @@ protected:
|
||||||
virtual void onCloseDisplay();
|
virtual void onCloseDisplay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::pair<UINT, bool> Keystroke;
|
enum EKeyAction { kPress, kRelease, kRepeat };
|
||||||
|
class Keystroke {
|
||||||
|
public:
|
||||||
|
UINT m_virtualKey;
|
||||||
|
bool m_press;
|
||||||
|
bool m_repeat;
|
||||||
|
};
|
||||||
typedef std::vector<Keystroke> Keystrokes;
|
typedef std::vector<Keystroke> Keystrokes;
|
||||||
|
|
||||||
DWORD mapButton(ButtonID button) const;
|
DWORD mapButton(ButtonID button, bool press) const;
|
||||||
KeyModifierMask mapKey(Keystrokes&, UINT& virtualKey, KeyID,
|
KeyModifierMask mapKey(Keystrokes&, UINT& virtualKey, KeyID,
|
||||||
KeyModifierMask, bool press) const;
|
KeyModifierMask, EKeyAction) const;
|
||||||
|
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||||
|
|
||||||
void updateKeys();
|
void updateKeys();
|
||||||
void updateModifiers();
|
void updateModifiers();
|
||||||
|
|
|
@ -135,9 +135,11 @@ void CTCPSocket::init()
|
||||||
CNetwork::TCPNoDelayType flag = 1;
|
CNetwork::TCPNoDelayType flag = 1;
|
||||||
CNetwork::setsockopt(m_fd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
CNetwork::setsockopt(m_fd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
|
|
||||||
|
#if !defined(CONFIG_PLATFORM_WIN32)
|
||||||
// don't buffer sends, we merge messages ourself
|
// don't buffer sends, we merge messages ourself
|
||||||
int data = 0;
|
int data = 0;
|
||||||
CNetwork::setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &data, sizeof(data));
|
CNetwork::setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &data, sizeof(data));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTCPSocket::ioThread(void*)
|
void CTCPSocket::ioThread(void*)
|
||||||
|
|
|
@ -252,7 +252,7 @@ void CMSWindowsPrimaryScreen::getClipboard(
|
||||||
CClipboard::copy(dst, &src);
|
CClipboard::copy(dst, &src);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyModifierMask CXWindowsPrimaryScreen::getToggleMask() const
|
KeyModifierMask CMSWindowsPrimaryScreen::getToggleMask() const
|
||||||
{
|
{
|
||||||
KeyModifierMask mask;
|
KeyModifierMask mask;
|
||||||
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
|
if ((m_keys[VK_CAPITAL] & 0x01) != 0)
|
||||||
|
|
Loading…
Reference in New Issue