Adam Tkac a3e64fa
diff -up tigervnc-1.0.90-20100813svn4123/unix/xserver/hw/vnc/Input.cc.rh607866 tigervnc-1.0.90-20100813svn4123/unix/xserver/hw/vnc/Input.cc
Adam Tkac a3e64fa
--- tigervnc-1.0.90-20100813svn4123/unix/xserver/hw/vnc/Input.cc.rh607866	2011-01-14 14:09:31.503156325 +0100
Adam Tkac a3e64fa
+++ tigervnc-1.0.90-20100813svn4123/unix/xserver/hw/vnc/Input.cc	2011-01-14 14:22:37.750812172 +0100
Adam Tkac a3e64fa
@@ -495,6 +495,49 @@ static struct altKeysym_t {
Adam Tkac a3e64fa
 #define FREE_MAPS
Adam Tkac a3e64fa
 #endif
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
+#if XORG >= 17
Adam Tkac a3e64fa
+/*
Adam Tkac a3e64fa
+ * Modifier keysyms must be handled differently. Instead of finding
Adam Tkac a3e64fa
+ * the right row and collumn in the keymap, directly press/release
Adam Tkac a3e64fa
+ * the keycode which is mapped as modifier with the same keysym.
Adam Tkac a3e64fa
+ *
Adam Tkac a3e64fa
+ * This will avoid issues when there are multiple modifier keysyms
Adam Tkac a3e64fa
+ * in the keymap but only some of them are mapped as modifiers in
Adam Tkac a3e64fa
+ * the modmap.
Adam Tkac a3e64fa
+ *
Adam Tkac a3e64fa
+ * Returns keycode of the modifier key.
Adam Tkac a3e64fa
+ */
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+static inline int isModifier(KeySymsPtr keymap, KeyCode *modmap,
Adam Tkac a3e64fa
+                             int maxKeysPerMod, rdr::U32 keysym)
Adam Tkac a3e64fa
+{
Adam Tkac a3e64fa
+	KeySym *map = keymap->map;
Adam Tkac a3e64fa
+	KeyCode minKeyCode = keymap->minKeyCode;
Adam Tkac a3e64fa
+	int mapWidth = keymap->mapWidth;
Adam Tkac a3e64fa
+	int i, j, k;
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+	/* Find modifier index in the modmap */
Adam Tkac a3e64fa
+	for (i = 0; i < 8; i++) {
Adam Tkac a3e64fa
+		for (k = 0; k < maxKeysPerMod; k++) {
Adam Tkac a3e64fa
+			int index = i * maxKeysPerMod + k;
Adam Tkac a3e64fa
+			int keycode = modmap[index];
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+			if (keycode == 0)
Adam Tkac a3e64fa
+				continue;
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+			for (j = 0; j < mapWidth; j++) {
Adam Tkac a3e64fa
+				if (map[(keycode - minKeyCode) * mapWidth + j]
Adam Tkac a3e64fa
+				    == keysym) {
Adam Tkac a3e64fa
+					return keycode;
Adam Tkac a3e64fa
+				}
Adam Tkac a3e64fa
+			}
Adam Tkac a3e64fa
+		}
Adam Tkac a3e64fa
+	}
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+	return -1; /* Not a modifier */
Adam Tkac a3e64fa
+}
Adam Tkac a3e64fa
+#endif
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
 void InputDevice::keyEvent(rdr::U32 keysym, bool down)
Adam Tkac a3e64fa
 {
Adam Tkac a3e64fa
 	DeviceIntPtr master;
Adam Tkac a3e64fa
@@ -506,6 +549,9 @@ void InputDevice::keyEvent(rdr::U32 keys
Adam Tkac a3e64fa
 	int mapWidth;
Adam Tkac a3e64fa
 	unsigned int i;
Adam Tkac a3e64fa
 	int j, k, state, maxKeysPerMod;
Adam Tkac a3e64fa
+#if XORG >= 18
Adam Tkac a3e64fa
+	KeybdCtrl ctrl;
Adam Tkac a3e64fa
+#endif
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
 	initInputDevice();
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
@@ -555,6 +601,18 @@ void InputDevice::keyEvent(rdr::U32 keys
Adam Tkac a3e64fa
 	maxKeyCode = keymap->maxKeyCode;
Adam Tkac a3e64fa
 	mapWidth = keymap->mapWidth;
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
+#if XORG >= 18
Adam Tkac a3e64fa
+	/*
Adam Tkac a3e64fa
+	 * No server-side key repeating, please. Some clients won't work well,
Adam Tkac a3e64fa
+	 * check https://bugzilla.redhat.com/show_bug.cgi?id=607866.
Adam Tkac a3e64fa
+	 */
Adam Tkac a3e64fa
+	ctrl = keyboardDev->kbdfeed->ctrl;
Adam Tkac a3e64fa
+	if (ctrl.autoRepeat != FALSE) {
Adam Tkac a3e64fa
+		ctrl.autoRepeat = FALSE;
Adam Tkac a3e64fa
+		XkbSetRepeatKeys(keyboardDev, -1, ctrl.autoRepeat);
Adam Tkac a3e64fa
+	}
Adam Tkac a3e64fa
+#endif
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
 	/* find which modifier Mode_switch is on. */
Adam Tkac a3e64fa
 	int modeSwitchMapIndex = 0;
Adam Tkac a3e64fa
 	for (i = 3; i < 8; i++) {
Adam Tkac a3e64fa
@@ -576,7 +634,26 @@ void InputDevice::keyEvent(rdr::U32 keys
Adam Tkac a3e64fa
 	}
Adam Tkac a3e64fa
 ModeSwitchFound:
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
+	int kc;
Adam Tkac a3e64fa
 	int col = 0;
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+#if XORG >= 17
Adam Tkac a3e64fa
+	if ((kc = isModifier(keymap, modmap, maxKeysPerMod, keysym)) != -1) {
Adam Tkac a3e64fa
+		/*
Adam Tkac a3e64fa
+		 * It is a modifier key event.
Adam Tkac a3e64fa
+		 *
Adam Tkac a3e64fa
+		 * Don't do any auto-repeat because the X server will translate
Adam Tkac a3e64fa
+		 * each press into a release followed by a press.
Adam Tkac a3e64fa
+		 */
Adam Tkac a3e64fa
+		if (IS_PRESSED(keyc, kc) && down) {
Adam Tkac a3e64fa
+			FREE_MAPS;
Adam Tkac a3e64fa
+			return;
Adam Tkac a3e64fa
+		}
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
+		goto press;
Adam Tkac a3e64fa
+	}
Adam Tkac a3e64fa
+#endif
Adam Tkac a3e64fa
+
Adam Tkac a3e64fa
 	if (maxKeysPerMod != 0) {
Adam Tkac a3e64fa
 		if ((state & (1 << ShiftMapIndex)) != 0)
Adam Tkac a3e64fa
 			col |= 1;
Adam Tkac a3e64fa
@@ -585,7 +662,7 @@ ModeSwitchFound:
Adam Tkac a3e64fa
 			col |= 2;
Adam Tkac a3e64fa
 	}
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
-	int kc = KeysymToKeycode(keymap, keysym, &col);
Adam Tkac a3e64fa
+	kc = KeysymToKeycode(keymap, keysym, &col);
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
 	/*
Adam Tkac a3e64fa
 	 * Sort out the "shifted Tab" mess.  If we are sent a shifted Tab,
Adam Tkac a3e64fa
@@ -662,6 +739,7 @@ ModeSwitchFound:
Adam Tkac a3e64fa
 		return;
Adam Tkac a3e64fa
 	}
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
+#if XORG < 17
Adam Tkac a3e64fa
 	/*
Adam Tkac a3e64fa
 	 * See if it's a modifier key.  If so, then don't do any auto-repeat,
Adam Tkac a3e64fa
 	 * because the X server will translate each press into a release
Adam Tkac a3e64fa
@@ -676,6 +754,17 @@ ModeSwitchFound:
Adam Tkac a3e64fa
 			}	
Adam Tkac a3e64fa
 		}
Adam Tkac a3e64fa
 	}
Adam Tkac a3e64fa
+#else
Adam Tkac a3e64fa
+	/*
Adam Tkac a3e64fa
+	 * If you would like to press a key which is already pressed then
Adam Tkac a3e64fa
+	 * viewer didn't send the "release" event. In this case release it
Adam Tkac a3e64fa
+	 * before the press.
Adam Tkac a3e64fa
+	 */
Adam Tkac a3e64fa
+	if (IS_PRESSED(keyc, kc) && down) {
Adam Tkac a3e64fa
+		vlog.debug("KeyRelease for %d wasn't sent, releasing", kc);
Adam Tkac a3e64fa
+		pressKey(keyboardDev, kc, false, "fixing keycode");
Adam Tkac a3e64fa
+	}
Adam Tkac a3e64fa
+#endif
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
 	if (maxKeysPerMod != 0) {
Adam Tkac a3e64fa
 		ModifierState shift(keyboardDev, ShiftMapIndex);
Adam Tkac a3e64fa
@@ -697,8 +786,10 @@ ModeSwitchFound:
Adam Tkac a3e64fa
 		 * pressKey call, otherwise fake modifier keypress can be lost.
Adam Tkac a3e64fa
 		 */
Adam Tkac a3e64fa
 		pressKey(keyboardDev, kc, down, "keycode");
Adam Tkac a3e64fa
-	} else
Adam Tkac a3e64fa
+	} else {
Adam Tkac a3e64fa
+press:
Adam Tkac a3e64fa
 		pressKey(keyboardDev, kc, down, "keycode");
Adam Tkac a3e64fa
+	}
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
 
Adam Tkac a3e64fa
         FREE_MAPS;