]> source.dussan.org Git - tigervnc.git/commitdiff
Copy 5104:5109 from trunk.
authorPierre Ossman <ossman@cendio.se>
Thu, 23 May 2013 11:50:15 +0000 (11:50 +0000)
committerPierre Ossman <ossman@cendio.se>
Thu, 23 May 2013 11:50:15 +0000 (11:50 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/1_3@5110 3789f03b-4d11-0410-bbf8-ca57d06f2519

unix/xserver/hw/vnc/Input.cc
unix/xserver/hw/vnc/InputXKB.cc

index f1f8e112560b28008dc8555f68d0d07291cf43f9..5f96f3804b72d6ce2c68f94370e4a39ba8ec42de 100644 (file)
@@ -507,7 +507,16 @@ void InputDevice::keyEvent(rdr::U32 keysym, bool down)
                vlog.info("Added unknown keysym 0x%x to keycode %d",
                          keysym, keycode);
 
-               new_state = state;
+               /*
+                * The state given to addKeysym() is just a hint and
+                * the actual result might still require some state
+                * changes.
+                */
+               keycode = keysymToKeycode(keysym, state, &new_state);
+               if (keycode == 0) {
+                       vlog.error("Newly added keysym 0x%x cannot be generated", keysym);
+                       return;
+               }
        }
 
        /*
index 6fca36249edfe86e2e488c8268b170124981574c..7bc23778146078b234a81f221e8befb1c0217902 100644 (file)
@@ -408,13 +408,21 @@ KeyCode InputDevice::keysymToKeycode(KeySym keysym, unsigned state,
        xkb = GetMaster(keyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
        for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
                unsigned int state_out;
+               KeySym dummy;
 
                XkbTranslateKeyCode(xkb, key, state, &state_out, &ks);
                if (ks == NoSymbol)
                        continue;
 
-               if (state_out & state & LockMask)
-                       XkbConvertCase(ks, NULL, &ks);
+               /*
+                * Despite every known piece of documentation on
+                * XkbTranslateKeyCode() stating that mods_rtrn returns
+                * the unconsumed modifiers, in reality it always
+                * returns the _potentially consumed_ modifiers.
+                */
+               state_out = state & ~state_out;
+               if (state_out & LockMask)
+                       XkbConvertCase(ks, &dummy, &ks);
 
                if (ks == keysym)
                        return key;
@@ -477,6 +485,7 @@ KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state)
 
        int types[1];
        KeySym *syms;
+       KeySym upper, lower;
 
        master = GetMaster(keyboardDev, KEYBOARD_OR_FLOAT);
        xkb = master->key->xkbInfo->desc;
@@ -491,15 +500,46 @@ KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state)
        memset(&changes, 0, sizeof(changes));
        memset(&cause, 0, sizeof(cause));
 
-       XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, NULL);
+       XkbSetCauseUnknown(&cause);
+
+       /*
+        * Tools like xkbcomp get confused if there isn't a name
+        * assigned to the keycode we're trying to use.
+        */
+       if (xkb->names && xkb->names->keys &&
+           (xkb->names->keys[key].name[0] == '\0')) {
+               xkb->names->keys[key].name[0] = 'I';
+               xkb->names->keys[key].name[1] = '0' + (key / 100) % 10;
+               xkb->names->keys[key].name[2] = '0' + (key /  10) % 10;
+               xkb->names->keys[key].name[3] = '0' + (key /   1) % 10;
+
+               changes.names.changed |= XkbKeyNamesMask;
+               changes.names.first_key = key;
+               changes.names.num_keys = 1;
+       }
 
-       /* FIXME: Verify that ONE_LEVEL isn't screwed up */
+       /* FIXME: Verify that ONE_LEVEL/ALPHABETIC isn't screwed up */
+
+       /*
+        * For keysyms that are affected by Lock, we are better off
+        * using ALPHABETIC rather than ONE_LEVEL as the latter
+        * generally cannot produce lower case when Lock is active.
+        */
+       XkbConvertCase(keysym, &lower, &upper);
+       if (upper == lower)
+               types[XkbGroup1Index] = XkbOneLevelIndex;
+       else
+               types[XkbGroup1Index] = XkbAlphabeticIndex;
 
-       types[XkbGroup1Index] = XkbOneLevelIndex;
        XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes.map);
 
        syms = XkbKeySymsPtr(xkb,key);
-       syms[0] = keysym;
+       if (upper == lower)
+               syms[0] = keysym;
+       else {
+               syms[0] = lower;
+               syms[1] = upper;
+       }
 
        changes.map.changed |= XkbKeySymsMask;
        changes.map.first_key_sym = key;