File xorg-server-xf4vnc-bug605015-fix-keycode-lookup-and-isolevel3shift.diff of Package xorg-x11-server.import4447

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,
openSUSE Build Service is sponsored by