From 03a1ec5eafc1455f9400fa8014907f543fe7f030 Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Wed, 8 Dec 2010 16:31:39 +0000 Subject: [PATCH] [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 --- unix/xserver/hw/vnc/Input.cc | 99 ++++++++++++++++++++++-------------- 1 file 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; -- 2.39.5