--- server/vino-input.c.orig	2006-12-28 17:02:25.000000000 -0500
+++ server/vino-input.c	2006-12-28 16:58:51.000000000 -0500
@@ -73,6 +73,20 @@
  * receives just the keypress event. (This is because we assume that
  * the client side will handle "key repeat", and if we left the key
  * pressed down on the server as well, we'd get double repeating.)
+ *
+ * Shift and Alt-Gr are treated slightly different from the other
+ * modifier keys; they are considered to be just implementation
+ * details of how you type a particular keysym. Eg, if you type
+ * Control+Shift+? (on a US keyboard), you're typing Control because
+ * you want the Control key to be pressed, but you're only typing
+ * Shift because it's required to get a "?" rather than a "/".
+ * Different keyboard layouts require Shift and Alt-Gr to be used for
+ * different keysyms, so if the client and server keyboards are not of
+ * the same type, vino will sometimes need to send fake press and
+ * release events for Shift and Alt-Gr in order to be able to type the
+ * keys the client intended to type. (On keys that have no shifted
+ * state, like the arrow and function keys, Shift and Alt-Gr behave
+ * as ordinary modifiers, the same way Control and Alt do.)
  * 
  * Two further bits of special behavior are needed for NumLock; first,
  * the second key level, which is normally "Shift", actually
@@ -219,6 +233,7 @@
       for (keycode = min_keycodes; keycode < max_keycodes; keycode++)
 	{
 	  VinoKeybinding *binding;
+	  gboolean unmodifiable;
 
 	  sym = XKeycodeToKeysym (xdisplay, keycode, level);
 	  if (sym == NoSymbol)
@@ -236,7 +251,23 @@
 	  binding[0].keycode = keycode;
 	  binding[0].keypad = VINO_IS_KEYPAD_KEYSYM (sym);
 
-	  if (binding[0].keypad && level == VINO_LEVEL_SHIFT)
+	  /* Check if this is a key like XK_uparrow that doesn't change
+	   * when you press Shift/Alt-Gr.
+	   */
+	  if (level == VINO_LEVEL_PLAIN)
+	    {
+	      KeySym shiftsym, altgrsym;
+
+	      shiftsym = XKeycodeToKeysym (xdisplay, keycode, VINO_LEVEL_SHIFT);
+	      altgrsym = (keysyms_per_keycode <= VINO_LEVEL_ALTGR) ? NoSymbol :
+		XKeycodeToKeysym (xdisplay, keycode, VINO_LEVEL_ALTGR);
+
+	      unmodifiable = (shiftsym == NoSymbol) && (altgrsym == NoSymbol);
+	    }
+
+	  if (unmodifiable)
+	    binding[0].level = -1;
+	  else if (binding[0].keypad && level == VINO_LEVEL_SHIFT)
 	    binding[0].level = VINO_LEVEL_NUM_LOCK;
 	  else
 	    binding[0].level = level;
@@ -368,7 +399,9 @@
 		{
 		  binding[group].keycode = kc;
 		  binding[group].keypad = (kt == XkbKeypadIndex);
-		  if (binding[group].keypad && level == VINO_LEVEL_SHIFT)
+		  if (xkb->map->types[kt].num_levels == 1)
+		    binding[group].level = -1;
+		  else if (binding[group].keypad && level == VINO_LEVEL_SHIFT)
 		    binding[group].level = VINO_LEVEL_NUM_LOCK;
 		  else
 		    binding[group].level = level;
@@ -604,6 +637,14 @@
   VinoModifierState modifier_state = input_data->modifier_state;
   int cur_level;
 
+  if (binding->level == -1)
+    {
+      /* The keysym is unaffected by modifier keys, so we should leave
+       * the modifiers in their current state.
+       */
+      return;
+    }
+
   if (binding->keypad && !input_data->xkb_supported)
     {
       Window root, child;
