This patch fixes keycode lookup (not using any static keyboard layout any more) and ISO-Level3-Shift handling (enabling the use of keyboard layouts that use AltGr for reaching certain characters). Note that the implementation is still imperfect. Keyboard layouts that use a different key than AltGr for ISO-Level3-Shift will show some weird behavior. Mode_Switch is also not supported, so keyboard switching via Mode_Switch might not work as intended either. Suggesting the use of input methods in these cases (they will hopefully work). mhopf - 21/04/2011 Index: xorg-server-1.9.3/hw/vnc/kbdptr.c =================================================================== --- xorg-server-1.9.3.orig/hw/vnc/kbdptr.c +++ xorg-server-1.9.3/hw/vnc/kbdptr.c @@ -142,6 +142,10 @@ KbdAddEvent(Bool down, KeySym keySym, rf Bool fakeShiftRRelease = FALSE; Bool shiftMustBeReleased = FALSE; Bool shiftMustBePressed = FALSE; + Bool fakeLevel3Press = FALSE; + Bool fakeLevel3Release = FALSE; + Bool level3MustBeReleased = FALSE; + Bool level3MustBePressed = FALSE; keySyms = XkbGetCoreMap(inputInfo.keyboard); @@ -161,6 +165,12 @@ KbdAddEvent(Bool down, KeySym keySym, rf * * Alan. */ + /* Never use predefined keys. + * This is inherently incapable of dealing with changing + * keyboard layouts. Not being able to work with non-local xmodmaps + * is a nuisance at worst, and probably even preferred. + * 2011-04-15 mhopf@suse.de */ +#if 0 #if !XFREE86VNC /* First check if it's one of our predefined keys. If so then we can make some attempt at allowing an xmodmap inside a VNC desktop behave @@ -187,6 +197,7 @@ KbdAddEvent(Bool down, KeySym keySym, rf } } #endif +#endif if (!keyCode) { @@ -201,18 +212,27 @@ KbdAddEvent(Bool down, KeySym keySym, rf for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) { if (keySym == keySyms->map[i]) { + int j, numSyms = 0; keyCode = MIN_KEY_CODE + i / keySyms->mapWidth; - if (keySyms->map[(i / keySyms->mapWidth) - * keySyms->mapWidth + 1] != NoSymbol) { - + for (j = 0; j < keySyms->mapWidth; j++) + if (keySyms->map[(i / keySyms->mapWidth) + * keySyms->mapWidth + j] != NoSymbol) + numSyms++; + if (numSyms > 1) { /* this keycode has more than one symbol associated with - it, so shift state is important */ + it, so shift/Level3_shift state is important */ - if ((i % keySyms->mapWidth) == 0) + if (((i % keySyms->mapWidth) & 1) == 0) shiftMustBeReleased = TRUE; else shiftMustBePressed = TRUE; + /* Does NOT consider Mode_shift (entries 2-3) */ + if (((i % keySyms->mapWidth) & 4) == 0) + level3MustBeReleased = TRUE; + else { + level3MustBePressed = TRUE; + } } break; } @@ -252,6 +272,7 @@ KbdAddEvent(Bool down, KeySym keySym, rf shiftMustBeReleased = TRUE; else shiftMustBePressed = TRUE; + level3MustBeReleased = TRUE; } XkbApplyMappingChange(inputInfo.keyboard, keySyms, keyCode, 1, NULL, serverClient); @@ -262,6 +283,16 @@ KbdAddEvent(Bool down, KeySym keySym, rf xkb = &inputInfo.keyboard->key->xkbInfo->state; if (down) { + // TODO: would require to check which keycodes are actually + // bound to ISO_Level3_Shift and/or Shift_L + if (level3MustBePressed && !KEY_IS_PRESSED(ISO_LEVEL3_KEY_CODE)) { + fakeLevel3Press = TRUE; + EnqueueKey(inputInfo.keyboard, KeyPress, ISO_LEVEL3_KEY_CODE); + } + if (level3MustBeReleased && KEY_IS_PRESSED(ISO_LEVEL3_KEY_CODE)) { + fakeLevel3Release = TRUE; + EnqueueKey(inputInfo.keyboard, KeyRelease, ISO_LEVEL3_KEY_CODE); + } if (shiftMustBePressed && !(XkbStateFieldFromRec(xkb) & ShiftMask)) { fakeShiftPress = TRUE; EnqueueKey(inputInfo.keyboard, KeyPress, SHIFT_L_KEY_CODE); @@ -289,6 +320,12 @@ KbdAddEvent(Bool down, KeySym keySym, rf if (fakeShiftRRelease) { EnqueueKey(inputInfo.keyboard, KeyPress, SHIFT_R_KEY_CODE); } + if (fakeLevel3Press) { + EnqueueKey(inputInfo.keyboard, KeyRelease, ISO_LEVEL3_KEY_CODE); + } + if (fakeLevel3Release) { + EnqueueKey(inputInfo.keyboard, KeyPress, ISO_LEVEL3_KEY_CODE); + } } Index: xorg-server-1.9.3/hw/vnc/keyboard.h =================================================================== --- xorg-server-1.9.3.orig/hw/vnc/keyboard.h +++ xorg-server-1.9.3/hw/vnc/keyboard.h @@ -32,6 +32,7 @@ #define META_R_KEY_CODE (MIN_KEY_CODE + 108) #define ALT_L_KEY_CODE (MIN_KEY_CODE + 56) #define ALT_R_KEY_CODE (MIN_KEY_CODE + 105) +#define ISO_LEVEL3_KEY_CODE ALT_R_KEY_CODE static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = { /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,