summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorAdam Tkac <atkac@redhat.com>2010-12-08 16:31:39 +0000
committerAdam Tkac <atkac@redhat.com>2010-12-08 16:31:39 +0000
commit03a1ec5eafc1455f9400fa8014907f543fe7f030 (patch)
treea72e1306e392dfb8812ffdc771c84ab21d514150 /unix
parent76ffb8ef1cb8d5e9419d6d7f6c07234e74fbd69b (diff)
downloadtigervnc-03a1ec5eafc1455f9400fa8014907f543fe7f030.tar.gz
tigervnc-03a1ec5eafc1455f9400fa8014907f543fe7f030.zip
[Bugfix] Handle situation when keyboard has no modifiers in Input.cc well.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4225 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'unix')
-rw-r--r--unix/xserver/hw/vnc/Input.cc99
1 files changed, 61 insertions, 38 deletions
diff --git a/unix/xserver/hw/vnc/Input.cc b/unix/xserver/hw/vnc/Input.cc
index c0e28bcc..87151d9b 100644
--- a/unix/xserver/hw/vnc/Input.cc
+++ b/unix/xserver/hw/vnc/Input.cc
@@ -296,6 +296,19 @@ void InputDevice::initInputDevice(void)
#endif
}
+static inline void pressKey(DeviceIntPtr dev, int kc, bool down, const char *msg)
+{
+ int action;
+ unsigned int n;
+
+ if (msg != NULL)
+ vlog.debug("%s %d %s", msg, kc, down ? "down" : "up");
+
+ action = down ? KeyPress : KeyRelease;
+ n = GetKeyboardEvents(eventq, dev, action, kc);
+ enqueueEvents(dev, n);
+}
+
#define IS_PRESSED(keyc, keycode) \
((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
@@ -319,7 +332,7 @@ public:
~ModifierState()
{
for (int i = 0; i < nKeys; i++)
- generateXKeyEvent(keys[i], !pressed);
+ pressKey(dev, keys[i], !pressed, "fake keycode");
delete [] keys;
}
@@ -344,6 +357,12 @@ public:
return;
}
+ if (maxKeysPerMod == 0) {
+ vlog.debug("Keyboard has no modifiers");
+ xfree(modmap);
+ return;
+ }
+
keycode = modmap[modIndex * maxKeysPerMod];
xfree(modmap);
#else
@@ -376,6 +395,12 @@ public:
vlog.error("generate_modkeymap failed");
return;
}
+
+ if (maxKeysPerMod == 0) {
+ vlog.debug("Keyboard has no modifiers");
+ xfree(modmap);
+ return;
+ }
#else
maxKeysPerMod = keyc->maxKeysPerModifier;
#endif
@@ -402,22 +427,10 @@ private:
if (keycode) {
if (!keys) keys = new int[maxKeysPerMod];
keys[nKeys++] = keycode;
- generateXKeyEvent(keycode, down);
+ pressKey(dev, keycode, down, "fake keycode");
}
}
- void generateXKeyEvent(int keycode, bool down)
- {
- int n, action;
-
- action = down ? KeyPress : KeyRelease;
- n = GetKeyboardEvents(eventq, dev, action, keycode);
- enqueueEvents(dev, n);
-
- vlog.debug("fake keycode %d %s", keycode,
- down ? "down" : "up");
- }
-
int modIndex;
int nKeys;
int *keys;
@@ -518,8 +531,8 @@ void InputDevice::keyEvent(rdr::U32 keysym, bool down)
KeyCode minKeyCode, maxKeyCode;
KeyCode *modmap = NULL;
int mapWidth;
- unsigned int i, n;
- int j, k, action, state, maxKeysPerMod;
+ unsigned int i;
+ int j, k, state, maxKeysPerMod;
initInputDevice();
@@ -553,6 +566,9 @@ void InputDevice::keyEvent(rdr::U32 keysym, bool down)
return;
}
+ if (maxKeysPerMod == 0)
+ vlog.debug("Keyboard has no modifiers");
+
state = XkbStateFieldFromRec(&keyc->xkbInfo->state);
#else
keyc = keyboardDev->key;
@@ -588,11 +604,13 @@ void InputDevice::keyEvent(rdr::U32 keysym, bool down)
ModeSwitchFound:
int col = 0;
- if ((state & (1 << ShiftMapIndex)) != 0)
- col |= 1;
- if (modeSwitchMapIndex != 0 &&
- ((state & (1 << modeSwitchMapIndex))) != 0)
- col |= 2;
+ if (maxKeysPerMod != 0) {
+ if ((state & (1 << ShiftMapIndex)) != 0)
+ col |= 1;
+ if (modeSwitchMapIndex != 0 &&
+ ((state & (1 << modeSwitchMapIndex))) != 0)
+ col |= 2;
+ }
int kc = KeysymToKeycode(keymap, keysym, &col);
@@ -604,7 +622,8 @@ ModeSwitchFound:
* We never get ISO_Left_Tab here because it's already been translated
* in VNCSConnectionST.
*/
- if (keysym == XK_Tab && ((state & (1 << ShiftMapIndex))) != 0)
+ if (maxKeysPerMod != 0 && keysym == XK_Tab &&
+ ((state & (1 << ShiftMapIndex))) != 0)
col |= 1;
if (kc == 0) {
@@ -685,25 +704,29 @@ ModeSwitchFound:
}
}
- ModifierState shift(keyboardDev, ShiftMapIndex);
- ModifierState modeSwitch(keyboardDev, modeSwitchMapIndex);
- if (down) {
- if (col & 1)
- shift.press();
- else
- shift.release();
- if (modeSwitchMapIndex) {
- if (col & 2)
- modeSwitch.press();
+ if (maxKeysPerMod != 0) {
+ ModifierState shift(keyboardDev, ShiftMapIndex);
+ ModifierState modeSwitch(keyboardDev, modeSwitchMapIndex);
+ if (down) {
+ if (col & 1)
+ shift.press();
else
- modeSwitch.release();
+ shift.release();
+ if (modeSwitchMapIndex) {
+ if (col & 2)
+ modeSwitch.press();
+ else
+ modeSwitch.release();
+ }
}
- }
+ /*
+ * Ensure ModifierState objects are not destroyed before
+ * pressKey call, otherwise fake modifier keypress can be lost.
+ */
+ pressKey(keyboardDev, kc, down, "keycode");
+ } else
+ pressKey(keyboardDev, kc, down, "keycode");
- vlog.debug("keycode %d %s", kc, down ? "down" : "up");
- action = down ? KeyPress : KeyRelease;
- n = GetKeyboardEvents(eventq, keyboardDev, action, kc);
- enqueueEvents(keyboardDev, n);
FREE_MAPS;