Revision: 5119 http://tigervnc.svn.sourceforge.net/tigervnc/?rev=5119&view=rev Author: ossman_ Date: 2013-05-30 14:50:57 +0000 (Thu, 30 May 2013) Log Message: ----------- Some applications (e.g. wine and rdesktop) tend to misbehave when we use fake shift to get different symbols on the numpad. So avoid using fake shifts on NumLock related keys and hope that other applications won't get upset by getting the non-numpad keysym counterparts.
Modified Paths: -------------- trunk/unix/xserver/hw/vnc/Input.cc trunk/unix/xserver/hw/vnc/Input.h trunk/unix/xserver/hw/vnc/InputCore.cc trunk/unix/xserver/hw/vnc/InputXKB.cc Modified: trunk/unix/xserver/hw/vnc/Input.cc =================================================================== --- trunk/unix/xserver/hw/vnc/Input.cc 2013-05-30 14:48:20 UTC (rev 5118) +++ trunk/unix/xserver/hw/vnc/Input.cc 2013-05-30 14:50:57 UTC (rev 5119) @@ -64,6 +64,8 @@ static LogWriter vlog("Input"); +rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock", "Avoid fake Shift presses for keys affected by NumLock.", true); + #define BUTTONS 7 /* Event queue is shared between all devices. */ @@ -520,6 +522,53 @@ } /* + * X11 generally lets shift toggle the keys on the numeric pad + * the same way NumLock does. This is however not the case on + * other systems like Windows. As a result, some applications + * get confused when we do a fake shift to get the same effect + * that having NumLock active would produce. + * + * Until we have proper NumLock synchronisation (so we can + * avoid faking shift), we try to avoid the fake shifts if we + * can use an alternative keysym. + */ + if (((state & ShiftMask) != (new_state & ShiftMask)) && + avoidShiftNumLock && isAffectedByNumLock(keycode)) { + KeyCode keycode2; + unsigned new_state2; + + vlog.debug("Finding alternative to keysym 0x%x to avoid fake shift for numpad", keysym); + + for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) { + KeySym altsym; + + if (altKeysym[i].a == keysym) + altsym = altKeysym[i].b; + else if (altKeysym[i].b == keysym) + altsym = altKeysym[i].a; + else + continue; + + keycode2 = keysymToKeycode(altsym, state, &new_state2); + if (keycode2 == 0) + continue; + + if (((state & ShiftMask) != (new_state2 & ShiftMask)) && + isAffectedByNumLock(keycode2)) + continue; + + break; + } + + if (i == sizeof(altKeysym)/sizeof(altKeysym[0])) + vlog.debug("No alternative keysym found"); + else { + keycode = keycode2; + new_state = new_state2; + } + } + + /* * "Shifted Tab" is a bit of a mess. Some systems have varying, * special keysyms for this symbol. VNC mandates that clients * should always send the plain XK_Tab keysym and the server Modified: trunk/unix/xserver/hw/vnc/Input.h =================================================================== --- trunk/unix/xserver/hw/vnc/Input.h 2013-05-30 14:48:20 UTC (rev 5118) +++ trunk/unix/xserver/hw/vnc/Input.h 2013-05-30 14:50:57 UTC (rev 5119) @@ -91,6 +91,8 @@ bool isLockModifier(KeyCode keycode, unsigned state); + bool isAffectedByNumLock(KeyCode keycode); + KeyCode addKeysym(KeySym keysym, unsigned state); private: Modified: trunk/unix/xserver/hw/vnc/InputCore.cc =================================================================== --- trunk/unix/xserver/hw/vnc/InputCore.cc 2013-05-30 14:48:20 UTC (rev 5118) +++ trunk/unix/xserver/hw/vnc/InputCore.cc 2013-05-30 14:50:57 UTC (rev 5119) @@ -514,6 +514,26 @@ return false; } +bool InputDevice::isAffectedByNumLock(KeyCode keycode) +{ + KeySymsPtr keymap; + int i, per; + KeySym *syms; + + keymap = &keyboardDev->key->curKeySyms; + per = keymap->mapWidth; + syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; + + for (i = 0;i < per;i++) { + if (IsKeypadKey(syms[i])) + return true; + if (IsPrivateKeypadKey(syms[i])) + return true; + } + + return false; +} + KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state) { KeyCode kc; Modified: trunk/unix/xserver/hw/vnc/InputXKB.cc =================================================================== --- trunk/unix/xserver/hw/vnc/InputXKB.cc 2013-05-30 14:48:20 UTC (rev 5118) +++ trunk/unix/xserver/hw/vnc/InputXKB.cc 2013-05-30 14:50:57 UTC (rev 5119) @@ -177,6 +177,36 @@ return &acts[col]; } +static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods) +{ + int nKeyGroups; + unsigned effectiveGroup; + + nKeyGroups= XkbKeyNumGroups(xkb,key); + if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) + return 0; + + effectiveGroup= XkbGroupForCoreState(mods); + if ( effectiveGroup>=nKeyGroups ) { + unsigned groupInfo= XkbKeyGroupInfo(xkb,key); + switch (XkbOutOfRangeGroupAction(groupInfo)) { + default: + effectiveGroup %= nKeyGroups; + break; + case XkbClampIntoRange: + effectiveGroup = nKeyGroups-1; + break; + case XkbRedirectIntoRange: + effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); + if (effectiveGroup>=nKeyGroups) + effectiveGroup= 0; + break; + } + } + + return effectiveGroup; +} + void InputDevice::PrepareInputDevices(void) { #if XORG < 19 @@ -479,6 +509,53 @@ return true; } +bool InputDevice::isAffectedByNumLock(KeyCode keycode) +{ + unsigned state; + + KeyCode numlock_keycode; + unsigned numlock_mask; + + XkbDescPtr xkb; + XkbAction *act; + + unsigned group; + XkbKeyTypeRec *type; + + /* Group state is still important */ + state = getKeyboardState(); + state &= ~0xff; + + /* + * Not sure if hunting for a virtual modifier called "NumLock", + * or following the keysym Num_Lock is the best approach. We + * try the latter. + */ + numlock_keycode = keysymToKeycode(XK_Num_Lock, state, NULL); + if (numlock_keycode == 0) + return false; + + xkb = GetMaster(keyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc; + + act = XkbKeyActionPtr(xkb, numlock_keycode, state); + if (act == NULL) + return false; + if (act->type != XkbSA_LockMods) + return false; + + if (act->mods.flags & XkbSA_UseModMapMods) + numlock_mask = xkb->map->modmap[keycode]; + else + numlock_mask = act->mods.mask; + + group = XkbKeyEffectiveGroup(xkb, keycode, state); + type = XkbKeyKeyType(xkb, keycode, group); + if ((type->mods.mask & numlock_mask) == 0) + return false; + + return true; +} + KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state) { DeviceIntPtr master; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET Get 100% visibility into your production application - at no cost. Code-level diagnostics for performance bottlenecks with <2% overhead Download for free and get started troubleshooting in minutes. http://p.sf.net/sfu/appdyn_d2d_ap1 _______________________________________________ Tigervnc-commits mailing list Tigervnc-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tigervnc-commits