Index: gdk/win32/gdkkeys-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkkeys-win32.c,v
retrieving revision 1.22
diff -u -2 -r1.22 gdkkeys-win32.c
--- gdk/win32/gdkkeys-win32.c	7 Aug 2004 23:35:41 -0000	1.22
+++ gdk/win32/gdkkeys-win32.c	10 Jan 2005 02:30:59 -0000
@@ -41,4 +41,5 @@
 guint _gdk_keymap_serial = 0;
 gboolean _gdk_keyboard_has_altgr = FALSE;
+static GdkModifierType gdk_shift_modifiers = GDK_SHIFT_MASK;
 
 static GdkKeymap *default_keymap = NULL;
@@ -52,5 +53,7 @@
   gint vk;
   
-  g_print ("keymap:%s\n", _gdk_keyboard_has_altgr ? " (uses AltGr)" : "");
+  g_print ("keymap:%s%s\n",
+	   _gdk_keyboard_has_altgr ? " (uses AltGr)" : "",
+	   (gdk_shift_modifiers & GDK_LOCK_MASK) ? " (has ShiftLock)" : "");
   for (vk = 0; vk < 256; vk++)
     {
@@ -75,7 +78,7 @@
   static guint current_serial = 0;
   guchar key_state[256], temp_key_state[256];
-  wchar_t wcs[1];
   guint scancode;
   guint vk;
+  gboolean capslock_tested = FALSE;
 
   if (keysym_tab != NULL && current_serial == _gdk_keymap_serial)
@@ -90,4 +93,5 @@
 
   _gdk_keyboard_has_altgr = FALSE;
+  gdk_shift_modifiers = GDK_SHIFT_MASK;
 
   for (vk = 0; vk < 256; vk++)
@@ -267,4 +271,5 @@
 	      if (*ksymp == 0)
 		{
+		  wchar_t wcs[1];
 		  gint k = ToAsciiEx (vk, scancode, key_state,
 				      (LPWORD) chars, 0, _gdk_input_locale);
@@ -382,10 +387,51 @@
 	    }
 	  key_state[vk] = 0;
+
+	  /* Check if keyboard has an AltGr key by checking if
+	   * the mapping with Control+Alt is different.
+	   */
+	  if (!_gdk_keyboard_has_altgr)
+	    if ((keysym_tab[vk*4 + 2] != GDK_VoidSymbol &&
+		 keysym_tab[vk*4] != keysym_tab[vk*4 + 2]) ||
+		(keysym_tab[vk*4 + 3] != GDK_VoidSymbol &&
+		 keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 3]))
+	      _gdk_keyboard_has_altgr = TRUE;
+	  
+	  if (!capslock_tested)
+	    {
+	      /* Can we use this virtual key to determine the CapsLock
+	       * key behaviour: CapsLock or ShiftLock? If it generates
+	       * keysyms for printable characters and has a shifted
+	       * keysym that isn't just the upperacase of the
+	       * unshifted keysym, check the behaviour of VK_CAPITAL.
+	       */
+	      if (g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 0])) &&
+		  keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 0] &&
+		  g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 1])) &&
+		  keysym_tab[vk*4 + 1] != gdk_keyval_to_upper (keysym_tab[vk*4 + 0]))
+		{
+		  guchar chars[2];
+		  
+		  capslock_tested = TRUE;
+		  
+		  key_state[VK_SHIFT] = 0;
+		  key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
+		  key_state[VK_CAPITAL] = 1;
+
+		  if (ToAsciiEx (vk, scancode, key_state,
+				 (LPWORD) chars, 0, _gdk_input_locale) == 1)
+		    {
+		      if (chars[0] >= GDK_space &&
+			  chars[0] <= GDK_asciitilde &&
+			  chars[0] == keysym_tab[vk*4 + 1])
+			{
+			  /* CapsLock acts as ShiftLock */
+			  gdk_shift_modifiers |= GDK_LOCK_MASK;
+			}
+		    }
+		  key_state[VK_CAPITAL] = 0;
+		}    
+	    }
 	}
-      if ((keysym_tab[vk*4 + 2] != GDK_VoidSymbol &&
-	   keysym_tab[vk*4] != keysym_tab[vk*4 + 2]) ||
-	  (keysym_tab[vk*4 + 3] != GDK_VoidSymbol &&
-	   keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 3]))
-	_gdk_keyboard_has_altgr = TRUE;
     }
   GDK_NOTE (EVENTS, print_keysym_tab ());
@@ -634,5 +680,4 @@
 {
   guint tmp_keyval;
-  guint tmp_modifiers;
   guint *keyvals;
   gint shift_level;
@@ -670,10 +715,13 @@
   keyvals = keysym_tab + hardware_keycode*4;
 
-  if ((state & GDK_SHIFT_MASK) &&
-      (state & GDK_LOCK_MASK) &&
-      keyvals[group*2 + 1] == gdk_keyval_to_upper (keyvals[group*2 + 0]))
-    /* Shift disables caps lock */
-    shift_level = 0;		
-  else if (state & GDK_SHIFT_MASK)
+  if ((state & GDK_LOCK_MASK) &&
+      (state & GDK_SHIFT_MASK) &&
+      ((gdk_shift_modifiers & GDK_LOCK_MASK) ||
+       (keyvals[group*2 + 1] == gdk_keyval_to_upper (keyvals[group*2 + 0]))))
+    /* Shift always disables ShiftLock. Shift disables CapsLock for
+     * keys with lowercase/uppercase letter pairs.
+     */
+    shift_level = 0;
+  else if (state & gdk_shift_modifiers)
     shift_level = 1;
   else
@@ -721,26 +769,33 @@
   tmp_keyval = keyvals[group*2 + shift_level];
 
-  tmp_modifiers = ignore_group ? 0 : GDK_MOD2_MASK;
-  tmp_modifiers |= ignore_shift ? 0 : (GDK_SHIFT_MASK | GDK_LOCK_MASK);
-
-  if (effective_group)
-    *effective_group = group;
-
-  if (!(state & GDK_SHIFT_MASK) && (state & GDK_LOCK_MASK))
+  /* If a true CapsLock is toggled, and Shift is not down,
+   * and the shifted keysym is the uppercase of the unshifted,
+   * use it.
+   */
+  if (!(gdk_shift_modifiers & GDK_LOCK_MASK) &&
+      !(state & GDK_SHIFT_MASK) &&
+      (state & GDK_LOCK_MASK))
     {
       guint upper = gdk_keyval_to_upper (tmp_keyval);
-      if (upper != tmp_keyval)
+      if (upper == keyvals[group*2 + 1])
 	tmp_keyval = upper;
     }
 
+  if (keyval)
+    *keyval = tmp_keyval;
+
+  if (effective_group)
+    *effective_group = group;
+
   if (level)
     *level = shift_level;
 
   if (consumed_modifiers)
-    *consumed_modifiers = tmp_modifiers;
+    {
+      *consumed_modifiers =
+	(ignore_group ? 0 : GDK_MOD2_MASK) |
+	(ignore_shift ? 0 : (GDK_SHIFT_MASK|GDK_LOCK_MASK));
+    }
 				
-  if (keyval)
-    *keyval = tmp_keyval;
-
 #if 0
   GDK_NOTE (EVENTS, g_print ("...group=%d level=%d cmods=%#x keyval=%s\n",
