checkpoint. made changes to support key autorepeats on X.
This commit is contained in:
parent
570d85c842
commit
5641a875c1
|
@ -221,30 +221,33 @@ void CXWindowsSecondaryScreen::keyDown(
|
||||||
Keystrokes keys;
|
Keystrokes keys;
|
||||||
KeyCode keycode;
|
KeyCode keycode;
|
||||||
|
|
||||||
CDisplayLock display(this);
|
|
||||||
|
|
||||||
// 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, keycode, key, mask, True);
|
m_mask = mapKey(keys, keycode, 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);
|
||||||
XTestFakeKeyEvent(display, k->first, k->second, CurrentTime);
|
|
||||||
|
|
||||||
// note that key is now down
|
// note that key is now down
|
||||||
m_keys[keycode] = true;
|
m_keys[keycode] = true;
|
||||||
|
|
||||||
// update
|
|
||||||
XSync(display, False);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsSecondaryScreen::keyRepeat(
|
void CXWindowsSecondaryScreen::keyRepeat(
|
||||||
KeyID, KeyModifierMask, SInt32)
|
KeyID key, KeyModifierMask mask, SInt32 count)
|
||||||
{
|
{
|
||||||
CDisplayLock display(this);
|
Keystrokes keys;
|
||||||
// FIXME
|
KeyCode keycode;
|
||||||
|
|
||||||
|
// get the sequence of keys to simulate key repeat and the final
|
||||||
|
// modifier state.
|
||||||
|
m_mask = mapKey(keys, keycode, key, mask, kRepeat);
|
||||||
|
if (keys.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// generate key events
|
||||||
|
doKeystrokes(keys, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsSecondaryScreen::keyUp(
|
void CXWindowsSecondaryScreen::keyUp(
|
||||||
|
@ -253,23 +256,17 @@ void CXWindowsSecondaryScreen::keyUp(
|
||||||
Keystrokes keys;
|
Keystrokes keys;
|
||||||
KeyCode keycode;
|
KeyCode keycode;
|
||||||
|
|
||||||
CDisplayLock display(this);
|
|
||||||
|
|
||||||
// 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, keycode, key, mask, False);
|
m_mask = mapKey(keys, keycode, 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);
|
||||||
XTestFakeKeyEvent(display, k->first, k->second, CurrentTime);
|
|
||||||
|
|
||||||
// note that key is now up
|
// note that key is now up
|
||||||
m_keys[keycode] = false;
|
m_keys[keycode] = false;
|
||||||
|
|
||||||
// update
|
|
||||||
XSync(display, False);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWindowsSecondaryScreen::mouseDown(ButtonID button)
|
void CXWindowsSecondaryScreen::mouseDown(ButtonID button)
|
||||||
|
@ -408,7 +405,7 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
Keystrokes& keys,
|
Keystrokes& keys,
|
||||||
KeyCode& keycode,
|
KeyCode& keycode,
|
||||||
KeyID id, KeyModifierMask mask,
|
KeyID id, KeyModifierMask mask,
|
||||||
Bool press) const
|
EKeyAction action) const
|
||||||
{
|
{
|
||||||
// note -- must have display locked on entry
|
// note -- must have display locked on entry
|
||||||
|
|
||||||
|
@ -425,8 +422,8 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
// note if the key is the caps lock and it's "half-duplex"
|
// note if the key is the caps lock and it's "half-duplex"
|
||||||
const bool isHalfDuplex = (id == XK_Caps_Lock && m_capsLockHalfDuplex);
|
const bool isHalfDuplex = (id == XK_Caps_Lock && m_capsLockHalfDuplex);
|
||||||
|
|
||||||
// ignore releases for half-duplex keys
|
// ignore releases and repeats for half-duplex keys
|
||||||
if (isHalfDuplex && !press) {
|
if (isHalfDuplex && action != kPress) {
|
||||||
return m_mask;
|
return m_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +454,7 @@ KeyModifierMask CXWindowsSecondaryScreen::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 < 8; ++i) {
|
for (unsigned int i = 0; i < 8; ++i) {
|
||||||
unsigned int bit = (1 << i);
|
unsigned int bit = (1 << i);
|
||||||
|
@ -472,20 +470,26 @@ KeyModifierMask CXWindowsSecondaryScreen::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. use the first keycode for the modifier.
|
// press. use the first keycode for the modifier.
|
||||||
const KeyCode modifierKey = modifierKeys[0];
|
keystroke.m_keycode = modifierKeys[0];
|
||||||
keys.push_back(std::make_pair(modifierKey, True));
|
keystroke.m_press = True;
|
||||||
|
keystroke.m_repeat = False;
|
||||||
|
keys.push_back(keystroke);
|
||||||
if ((bit & m_toggleModifierMask) != 0) {
|
if ((bit & m_toggleModifierMask) != 0) {
|
||||||
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
undo.push_back(std::make_pair(modifierKey, False));
|
keystroke.m_press = False;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,24 +500,34 @@ KeyModifierMask CXWindowsSecondaryScreen::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 ((bit & m_toggleModifierMask) != 0) {
|
if ((bit & m_toggleModifierMask) != 0) {
|
||||||
const KeyCode modifierKey = modifierKeys[0];
|
keystroke.m_keycode = modifierKeys[0];
|
||||||
|
keystroke.m_repeat = False;
|
||||||
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
if (bit != m_capsLockMask || !m_capsLockHalfDuplex) {
|
||||||
keys.push_back(std::make_pair(modifierKey, True));
|
keystroke.m_press = True;
|
||||||
keys.push_back(std::make_pair(modifierKey, False));
|
keys.push_back(keystroke);
|
||||||
undo.push_back(std::make_pair(modifierKey, False));
|
keystroke.m_press = False;
|
||||||
undo.push_back(std::make_pair(modifierKey, True));
|
keys.push_back(keystroke);
|
||||||
|
undo.push_back(keystroke);
|
||||||
|
keystroke.m_press = True;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
keys.push_back(std::make_pair(modifierKey, False));
|
keystroke.m_press = False;
|
||||||
undo.push_back(std::make_pair(modifierKey, True));
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = True;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
||||||
const KeyCode key = modifierKeys[j];
|
const KeyCode key = modifierKeys[j];
|
||||||
if (m_keys[key]) {
|
if (m_keys[key]) {
|
||||||
keys.push_back(std::make_pair(key, False));
|
keystroke.m_keycode = 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,11 +538,32 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
|
|
||||||
// note if the press of a half-duplex key should be treated as a release
|
// note if the press of a half-duplex key should be treated as a release
|
||||||
if (isHalfDuplex && (m_mask & (1 << index->second)) != 0) {
|
if (isHalfDuplex && (m_mask & (1 << index->second)) != 0) {
|
||||||
press = false;
|
action = kRelease;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the key event
|
// add the key event
|
||||||
keys.push_back(std::make_pair(keycode, press));
|
keystroke.m_keycode = keycode;
|
||||||
|
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 = False;
|
||||||
|
keystroke.m_repeat = True;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = 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.
|
||||||
|
@ -538,9 +573,9 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the key is a modifier key then compute the modifier map after
|
// if the key is a modifier key then compute the modifier map after
|
||||||
// this key is pressed.
|
// this key is pressed or released. if repeating then ignore.
|
||||||
mask = m_mask;
|
mask = m_mask;
|
||||||
if (isModifier) {
|
if (isModifier && action != kRepeat) {
|
||||||
// get modifier
|
// get modifier
|
||||||
const unsigned int modifierBit = (1 << index->second);
|
const unsigned int modifierBit = (1 << index->second);
|
||||||
|
|
||||||
|
@ -549,10 +584,10 @@ KeyModifierMask CXWindowsSecondaryScreen::mapKey(
|
||||||
// and clear the bit on release. if half-duplex then toggle
|
// and clear the bit on release. if half-duplex then toggle
|
||||||
// each time we get here.
|
// each time we get here.
|
||||||
if ((modifierBit & m_toggleModifierMask) != 0) {
|
if ((modifierBit & m_toggleModifierMask) != 0) {
|
||||||
if (((mask & modifierBit) == 0) == press)
|
if (((mask & modifierBit) == 0) == (action == kPress))
|
||||||
mask ^= modifierBit;
|
mask ^= modifierBit;
|
||||||
}
|
}
|
||||||
else if (press) {
|
else if (action == kPress) {
|
||||||
mask |= modifierBit;
|
mask |= modifierBit;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -640,7 +675,7 @@ bool CXWindowsSecondaryScreen::findKeyCode(
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the keycode
|
// save the keycode
|
||||||
keycode = index->second.keycode;
|
keycode = index->second.m_keycode;
|
||||||
|
|
||||||
// compute output mask. that's the set of modifiers that need to
|
// compute output mask. that's the set of modifiers that need to
|
||||||
// be enabled when the keycode event is encountered in order to
|
// be enabled when the keycode event is encountered in order to
|
||||||
|
@ -649,22 +684,68 @@ bool CXWindowsSecondaryScreen::findKeyCode(
|
||||||
// it impossible to generate the keysym. in that case we must
|
// it impossible to generate the keysym. in that case we must
|
||||||
// override maskIn. this is complicated by caps/shift-lock and
|
// override maskIn. this is complicated by caps/shift-lock and
|
||||||
// num-lock.
|
// num-lock.
|
||||||
maskOut = (maskIn & ~index->second.keyMaskMask);
|
maskOut = (maskIn & ~index->second.m_keyMaskMask);
|
||||||
if (IsKeypadKey(id) || IsPrivateKeypadKey(id)) {
|
if (IsKeypadKey(id) || IsPrivateKeypadKey(id)) {
|
||||||
maskOut |= index->second.keyMask;
|
maskOut |= index->second.m_keyMask;
|
||||||
maskOut &= ~m_numLockMask;
|
maskOut &= ~m_numLockMask;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned int maskShift = (index->second.keyMask & ShiftMask);
|
unsigned int maskShift = (index->second.m_keyMask & ShiftMask);
|
||||||
if (index->second.keyMaskMask != 0 && (m_mask & m_capsLockMask) != 0)
|
if (index->second.m_keyMaskMask != 0 && (m_mask & m_capsLockMask) != 0)
|
||||||
maskShift ^= ShiftMask;
|
maskShift ^= ShiftMask;
|
||||||
maskOut |= maskShift | (m_mask & m_capsLockMask);
|
maskOut |= maskShift | (m_mask & m_capsLockMask);
|
||||||
maskOut |= (index->second.keyMask & ~(ShiftMask | LockMask));
|
maskOut |= (index->second.m_keyMask & ~(ShiftMask | LockMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXWindowsSecondaryScreen::doKeystrokes(
|
||||||
|
const Keystrokes& keys, SInt32 count)
|
||||||
|
{
|
||||||
|
// do nothing if no keys or no repeats
|
||||||
|
if (count < 1 || keys.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// lock display
|
||||||
|
CDisplayLock display(this);
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
// we generally want repeating keys to use the exact
|
||||||
|
// same event time for each release/press pair so we
|
||||||
|
// don't want to use CurrentTime which can't ensure
|
||||||
|
// that.
|
||||||
|
Time time = getCurrentTime(m_window);
|
||||||
|
|
||||||
|
// send repeating events
|
||||||
|
for (k = start; k != keys.end() && k->m_repeat; ++k) {
|
||||||
|
XTestFakeKeyEvent(display,
|
||||||
|
k->m_keycode, k->m_press, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
XTestFakeKeyEvent(display, k->m_keycode, k->m_press, CurrentTime);
|
||||||
|
|
||||||
|
// next key
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
XSync(display, False);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int CXWindowsSecondaryScreen::maskToX(
|
unsigned int CXWindowsSecondaryScreen::maskToX(
|
||||||
KeyModifierMask inMask) const
|
KeyModifierMask inMask) const
|
||||||
{
|
{
|
||||||
|
@ -764,12 +845,12 @@ void CXWindowsSecondaryScreen::updateKeycodeMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the mask of modifiers that this keycode uses
|
// set the mask of modifiers that this keycode uses
|
||||||
entry.keyMaskMask = (n == 1) ? 0 : (ShiftMask | LockMask);
|
entry.m_keyMaskMask = (n == 1) ? 0 : (ShiftMask | LockMask);
|
||||||
|
|
||||||
// add entries for this keycode
|
// add entries for this keycode
|
||||||
entry.keycode = static_cast<KeyCode>(minKeycode + i);
|
entry.m_keycode = static_cast<KeyCode>(minKeycode + i);
|
||||||
for (int j = 0; j < numKeysyms; ++j) {
|
for (int j = 0; j < numKeysyms; ++j) {
|
||||||
entry.keyMask = (j == 0) ? 0 : ShiftMask;
|
entry.m_keyMask = (j == 0) ? 0 : ShiftMask;
|
||||||
m_keycodeMap.insert(std::make_pair(keysyms[i *
|
m_keycodeMap.insert(std::make_pair(keysyms[i *
|
||||||
keysymsPerKeycode + j], entry));
|
keysymsPerKeycode + j], entry));
|
||||||
}
|
}
|
||||||
|
@ -841,7 +922,7 @@ void CXWindowsSecondaryScreen::toggleKey(
|
||||||
KeyCodeMap::const_iterator index = m_keycodeMap.find(keysym);
|
KeyCodeMap::const_iterator index = m_keycodeMap.find(keysym);
|
||||||
if (index == m_keycodeMap.end())
|
if (index == m_keycodeMap.end())
|
||||||
return;
|
return;
|
||||||
KeyCode keycode = index->second.keycode;
|
KeyCode keycode = index->second.m_keycode;
|
||||||
|
|
||||||
// toggle the key
|
// toggle the key
|
||||||
if (keysym == XK_Caps_Lock && m_capsLockHalfDuplex) {
|
if (keysym == XK_Caps_Lock && m_capsLockHalfDuplex) {
|
||||||
|
|
|
@ -38,13 +38,19 @@ protected:
|
||||||
virtual long getEventMask(Window) const;
|
virtual long getEventMask(Window) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct KeyCodeMask {
|
enum EKeyAction { kPress, kRelease, kRepeat };
|
||||||
|
class KeyCodeMask {
|
||||||
public:
|
public:
|
||||||
KeyCode keycode;
|
KeyCode m_keycode;
|
||||||
unsigned int keyMask;
|
unsigned int m_keyMask;
|
||||||
unsigned int keyMaskMask;
|
unsigned int m_keyMaskMask;
|
||||||
|
};
|
||||||
|
class Keystroke {
|
||||||
|
public:
|
||||||
|
KeyCode m_keycode;
|
||||||
|
Bool m_press;
|
||||||
|
bool m_repeat;
|
||||||
};
|
};
|
||||||
typedef std::pair<KeyCode, Bool> Keystroke;
|
|
||||||
typedef std::vector<Keystroke> Keystrokes;
|
typedef std::vector<Keystroke> Keystrokes;
|
||||||
typedef std::vector<KeyCode> KeyCodes;
|
typedef std::vector<KeyCode> KeyCodes;
|
||||||
typedef std::map<KeyID, KeyCodeMask> KeyCodeMap;
|
typedef std::map<KeyID, KeyCodeMask> KeyCodeMap;
|
||||||
|
@ -54,9 +60,10 @@ private:
|
||||||
unsigned int mapButton(ButtonID button) const;
|
unsigned int mapButton(ButtonID button) const;
|
||||||
|
|
||||||
unsigned int mapKey(Keystrokes&, KeyCode&, KeyID,
|
unsigned int mapKey(Keystrokes&, KeyCode&, KeyID,
|
||||||
KeyModifierMask, Bool press) const;
|
KeyModifierMask, EKeyAction) const;
|
||||||
bool findKeyCode(KeyCode&, unsigned int&,
|
bool findKeyCode(KeyCode&, unsigned int&,
|
||||||
KeyID id, unsigned int) const;
|
KeyID id, unsigned int) const;
|
||||||
|
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||||
unsigned int maskToX(KeyModifierMask) const;
|
unsigned int maskToX(KeyModifierMask) const;
|
||||||
|
|
||||||
void updateKeys(Display* display);
|
void updateKeys(Display* display);
|
||||||
|
|
|
@ -63,16 +63,40 @@ void CXWindowsPrimaryScreen::run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME -- simulate key repeat. X sends press/release for
|
|
||||||
// repeat. must detect auto repeat and use kKeyRepeat.
|
|
||||||
case KeyRelease: {
|
case KeyRelease: {
|
||||||
log((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
|
||||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||||
const KeyID key = mapKey(&xevent.xkey);
|
const KeyID key = mapKey(&xevent.xkey);
|
||||||
if (key != kKeyNone) {
|
if (key != kKeyNone) {
|
||||||
if (key == XK_Caps_Lock && m_capsLockHalfDuplex)
|
// check if this is a key repeat by getting the next
|
||||||
m_server->onKeyDown(key, mask);
|
// KeyPress event that has the same key and time as
|
||||||
m_server->onKeyUp(key, mask);
|
// this release event, if any. first prepare the
|
||||||
|
// filter info.
|
||||||
|
CKeyEventInfo filter;
|
||||||
|
filter.m_event = KeyPress;
|
||||||
|
filter.m_window = xevent.xkey.window;
|
||||||
|
filter.m_time = xevent.xkey.time;
|
||||||
|
filter.m_keycode = xevent.xkey.keycode;
|
||||||
|
|
||||||
|
// now check for event
|
||||||
|
XEvent xevent2;
|
||||||
|
CDisplayLock display(this);
|
||||||
|
if (XCheckIfEvent(display, &xevent2,
|
||||||
|
&CXWindowsPrimaryScreen::findKeyEvent,
|
||||||
|
(XPointer)&filter) != True) {
|
||||||
|
// no press event follows so it's a plain release
|
||||||
|
log((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||||
|
if (key == XK_Caps_Lock && m_capsLockHalfDuplex)
|
||||||
|
m_server->onKeyDown(key, mask);
|
||||||
|
m_server->onKeyUp(key, mask);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// found a press event following so it's a repeat.
|
||||||
|
// we could attempt to count the already queued
|
||||||
|
// repeats but we'll just send a repeat of 1.
|
||||||
|
// note that we discard the press event.
|
||||||
|
log((CLOG_DEBUG1 "event: repeat code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||||
|
m_server->onKeyRepeat(key, mask, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -550,3 +574,13 @@ void CXWindowsPrimaryScreen::updateModifierMap(
|
||||||
|
|
||||||
XFreeModifiermap(keymap);
|
XFreeModifiermap(keymap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool CXWindowsPrimaryScreen::findKeyEvent(
|
||||||
|
Display*, XEvent* xevent, XPointer arg)
|
||||||
|
{
|
||||||
|
CKeyEventInfo* filter = reinterpret_cast<CKeyEventInfo*>(arg);
|
||||||
|
return (xevent->type == filter->m_event &&
|
||||||
|
xevent->xkey.window == filter->m_window &&
|
||||||
|
xevent->xkey.time == filter->m_time &&
|
||||||
|
xevent->xkey.keycode == filter->m_keycode) ? True : False;
|
||||||
|
}
|
||||||
|
|
|
@ -43,6 +43,15 @@ private:
|
||||||
|
|
||||||
void updateModifierMap(Display* display);
|
void updateModifierMap(Display* display);
|
||||||
|
|
||||||
|
class CKeyEventInfo {
|
||||||
|
public:
|
||||||
|
int m_event;
|
||||||
|
Window m_window;
|
||||||
|
Time m_time;
|
||||||
|
KeyCode m_keycode;
|
||||||
|
};
|
||||||
|
static Bool findKeyEvent(Display*, XEvent* xevent, XPointer arg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CServer* m_server;
|
CServer* m_server;
|
||||||
bool m_active;
|
bool m_active;
|
||||||
|
|
Loading…
Reference in New Issue