6680988: KeyEvent is still missing VK values for many keyboards
authoryan
Fri, 27 Mar 2009 12:01:24 +0300
changeset 2473 3f4bbd3be2f1
parent 2472 b7aba00cabb6
child 2474 7fb3026b79d1
6680988: KeyEvent is still missing VK values for many keyboards Summary: 2 new methods and some fields added to KeyEvent, plus hash of constants introduced Reviewed-by: art
jdk/make/sun/awt/FILES_export_unix.gmk
jdk/make/sun/awt/FILES_export_windows.gmk
jdk/make/sun/xawt/mapfile-vers
jdk/src/share/classes/java/awt/AWTKeyStroke.java
jdk/src/share/classes/java/awt/MenuItem.java
jdk/src/share/classes/java/awt/MenuShortcut.java
jdk/src/share/classes/java/awt/event/KeyEvent.java
jdk/src/share/classes/javax/swing/AbstractButton.java
jdk/src/share/classes/javax/swing/Action.java
jdk/src/share/classes/javax/swing/JComponent.java
jdk/src/share/classes/javax/swing/JLabel.java
jdk/src/share/classes/javax/swing/JTabbedPane.java
jdk/src/share/classes/javax/swing/KeyStroke.java
jdk/src/share/classes/javax/swing/KeyboardManager.java
jdk/src/share/classes/javax/swing/SwingUtilities.java
jdk/src/share/classes/sun/awt/ExtendedKeyCodes.java
jdk/src/solaris/classes/sun/awt/X11/XConstants.java
jdk/src/solaris/classes/sun/awt/X11/XKeysym.java
jdk/src/solaris/classes/sun/awt/X11/XToolkit.java
jdk/src/solaris/classes/sun/awt/X11/XWindow.java
jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java
jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java
jdk/src/solaris/classes/sun/awt/X11/generator/xlibtypes.txt
jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h
jdk/src/solaris/native/sun/xawt/XlibWrapper.c
jdk/src/windows/native/sun/windows/awt_Component.cpp
jdk/src/windows/native/sun/windows/awt_Component.h
jdk/src/windows/native/sun/windows/awt_InputMethod.cpp
jdk/src/windows/native/sun/windows/awt_KeyEvent.cpp
jdk/src/windows/native/sun/windows/awt_KeyEvent.h
jdk/test/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html
jdk/test/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java
--- a/jdk/make/sun/awt/FILES_export_unix.gmk	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/make/sun/awt/FILES_export_unix.gmk	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 #
-# Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -107,7 +107,8 @@
 	sun/java2d/x11/X11Renderer.java \
 	sun/java2d/x11/X11SurfaceData.java \
         com/sun/java/swing/plaf/gtk/GTKEngine.java \
-        com/sun/java/swing/plaf/gtk/GTKStyle.java
+        com/sun/java/swing/plaf/gtk/GTKStyle.java \
+        sun/awt/ExtendedKeyCodes.java
 
 
 FILES_export2 = \
--- a/jdk/make/sun/awt/FILES_export_windows.gmk	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/make/sun/awt/FILES_export_windows.gmk	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 #
-# Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -154,7 +154,7 @@
         sun/awt/datatransfer/DataTransferer.java \
 	sun/awt/datatransfer/SunClipboard.java \
 	sun/awt/dnd/SunDragSourceContextPeer.java \
-        sun/awt/windows/WToolkitThreadBlockedHandler.java 
+        sun/awt/windows/WToolkitThreadBlockedHandler.java
 
 FILES_export3 = \
         java/awt/CheckboxMenuItem.java \
@@ -214,6 +214,7 @@
 	sun/awt/windows/WBufferStrategy.java \
 	sun/awt/windows/WTrayIconPeer.java \
 	sun/awt/image/ImagingLib.java \
+	sun/awt/ExtendedKeyCodes.java \
         sun/java2d/pipe/hw/AccelSurface.java \
         sun/java2d/pipe/hw/AccelDeviceEventNotifier.java \
         sun/java2d/pipe/hw/ContextCapabilities.java \
--- a/jdk/make/sun/xawt/mapfile-vers	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/make/sun/xawt/mapfile-vers	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 #
-# Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -293,16 +293,26 @@
         Java_sun_awt_X11_XlibWrapper_XGetIconSizes;
         Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym;
         Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode;
-        Java_sun_awt_X11_XlibWrapper_XQueryKeymap;
+	Java_sun_awt_X11_XlibWrapper_XQueryKeymap;
+        Java_sun_awt_X11_XlibWrapper_XkbGetEffectiveGroup;
+        Java_sun_awt_X11_XlibWrapper_XkbSelectEvents;
+        Java_sun_awt_X11_XlibWrapper_XkbSelectEventDetails;
+        Java_sun_awt_X11_XlibWrapper_XkbKeycodeToKeysym;
+        Java_sun_awt_X11_XlibWrapper_XkbLibraryVersion;
+        Java_sun_awt_X11_XlibWrapper_XkbQueryExtension;
+        Java_sun_awt_X11_XlibWrapper_XkbGetMap;
+        Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap;
+        Java_sun_awt_X11_XlibWrapper_XkbFreeKeyboard;
+        Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode;
         Java_sun_awt_X11_XlibWrapper_XGetModifierMapping;
-        Java_sun_awt_X11_XlibWrapper_XFreeModifiermap;        
+        Java_sun_awt_X11_XlibWrapper_XFreeModifiermap;
         Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab;
         Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent;
         Java_sun_awt_X11_XlibWrapper_ExitSecondaryLoop;
         Java_sun_awt_X11_XlibWrapper_XTextPropertyToStringList;
         Java_sun_awt_X11_XlibWrapper_XGrabServer;
         Java_sun_awt_X11_XlibWrapper_XUngrabServer;
-        Java_sun_awt_X11_XlibWrapper_XPutBackEvent;        
+        Java_sun_awt_X11_XlibWrapper_XPutBackEvent;
         Java_sun_awt_X11_XlibWrapper_XConvertCase;
         Java_sun_awt_X11_XlibWrapper_XSynchronize;
         Java_java_awt_FileDialog_initIDs;
--- a/jdk/src/share/classes/java/awt/AWTKeyStroke.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/java/awt/AWTKeyStroke.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -329,6 +329,9 @@
      * <li><code>java.awt.event.KeyEvent.VK_TAB</code>
      * <li><code>java.awt.event.KeyEvent.VK_SPACE</code>
      * </ul>
+     * Alternatively, the key code may be obtained by calling
+     * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
+     *
      * The modifiers consist of any combination of:<ul>
      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
--- a/jdk/src/share/classes/java/awt/MenuItem.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/java/awt/MenuItem.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -398,9 +398,11 @@
     boolean handleShortcut(KeyEvent e) {
         MenuShortcut s = new MenuShortcut(e.getKeyCode(),
                              (e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
+        MenuShortcut sE = new MenuShortcut(e.getExtendedKeyCode(),
+                             (e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
         // Fix For 6185151: Menu shortcuts of all menuitems within a menu
         // should be disabled when the menu itself is disabled
-        if (s.equals(shortcut) && isItemEnabled()) {
+        if ((s.equals(shortcut) || sE.equals(shortcut)) && isItemEnabled()) {
             // MenuShortcut match -- issue an event on keydown.
             if (e.getID() == KeyEvent.KEY_PRESSED) {
                 doMenuEvent(e.getWhen(), e.getModifiers());
--- a/jdk/src/share/classes/java/awt/MenuShortcut.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/java/awt/MenuShortcut.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,21 @@
  * For example, a menu shortcut for Ctrl-a (assuming that Control is
  * the accelerator key) would be created with code like the following:
  * <p>
- * MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false);
+ * <code>MenuShortcut ms = new MenuShortcut(KeyEvent.VK_A, false);</code>
+ * <p> or alternatively
+ * <p>
+ * <code>MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('A'), false);</code>
+ * <p>
+ * Menu shortcuts may also be constructed for a wider set of keycodes
+ * using the <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code> call.
+ * For example, a menu shortcut for "Ctrl+cyrillic ef" is created by
+ * <p>
+ * <code>MenuShortcut ms = new MenuShortcut(KeyEvent.getExtendedKeyCodeForChar('\u0444'), false);</code>
+ * <p>
+ * Note that shortcuts created with a keycode or an extended keycode defined as a constant in <code>KeyEvent</code>
+ * work regardless of the current keyboard layout. However, a shortcut made of
+ * an extended keycode not listed in <code>KeyEvent</code>
+ * only work if the current keyboard layout produces a corresponding letter.
  * <p>
  * The accelerator key is platform-dependent and may be obtained
  * via {@link Toolkit#getMenuShortcutKeyMask}.
--- a/jdk/src/share/classes/java/awt/event/KeyEvent.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/java/awt/event/KeyEvent.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,15 +65,16 @@
  * <p>
  * For key pressed and key released events, the getKeyCode method returns
  * the event's keyCode.  For key typed events, the getKeyCode method
- * always returns VK_UNDEFINED.
+ * always returns {@code VK_UNDEFINED}. The {@code getExtendedKeyCode} method
+ * may also be used with many international keyboard layouts.
  *
  * <p>
  * <em>"Key pressed" and "key released" events</em> are lower-level and depend
  * on the platform and keyboard layout. They are generated whenever a key is
  * pressed or released, and are the only way to find out about keys that don't
  * generate character input (e.g., action keys, modifier keys, etc.). The key
- * being pressed or released is indicated by the getKeyCode method, which returns
- * a virtual key code.
+ * being pressed or released is indicated by the {@code getKeyCode} and {@code getExtendedKeyCode}
+ * methods, which return a virtual key code.
  *
  * <p>
  * <em>Virtual key codes</em> are used to report which keyboard key has
@@ -111,6 +112,11 @@
  * platform and keyboard layout. For example, the key that generates VK_Q
  * when using a U.S. keyboard layout will generate VK_A when using a French
  * keyboard layout.
+ * <li>The key that generates {@code VK_Q} when using a U.S. keyboard layout also
+ * generates a unique code for Russian or Hebrew layout. There is no a
+ * {@code VK_} constant for these and many other codes in various layouts. These codes
+ * may be obtained by using {@code getExtendedKeyCode} and are used whenever
+ * a {@code VK_} constant is used.
  * <li>Not all characters have a keycode associated with them.  For example,
  * there is no keycode for the question mark because there is no keyboard
  * for which it appears on the primary layer.
@@ -891,6 +897,12 @@
      */
     int keyLocation;
 
+    //set from native code.
+    private transient long rawCode = 0;
+    private transient long primaryLevelUnicode = 0;
+    private transient long scancode = 0; // for MS Windows only
+    private transient long extendedKeyCode = 0;
+
     /*
      * JDK 1.1 serialVersionUID
      */
@@ -1315,6 +1327,9 @@
             return numpad + "-" + c;
         }
 
+        if ((keyCode & 0x01000000) != 0) {
+            return String.valueOf((char)(keyCode ^ 0x01000000 ));
+        }
         String unknown = Toolkit.getProperty("AWT.unknown", "Unknown");
         return unknown + " keyCode: 0x" + Integer.toString(keyCode, 16);
     }
@@ -1551,9 +1566,44 @@
             str.append("KEY_LOCATION_UNKNOWN");
             break;
         }
+        str.append(",rawCode=").append(rawCode);
+        str.append(",primaryLevelUnicode=").append(primaryLevelUnicode);
+        str.append(",scancode=").append(scancode);
+        str.append(",extendedKeyCode=0x").append(Long.toHexString(extendedKeyCode));
 
         return str.toString();
     }
+    /**
+     * Returns an extended key code for the event.
+     * The extended key code is a unique id assigned to  a key on the keyboard
+     * just like {@code keyCode}. However, unlike {@code keyCode}, this value depends on the
+     * current keyboard layout. For instance, pressing the left topmost letter key
+     * in a common English layout produces the same value as {@code keyCode}, {@code VK_Q}.
+     * Pressing the same key in a regular Russian layout gives another code, unique for the
+     * letter "Cyrillic I short".
+     *
+     * @since 1.7
+     *
+     */
+    public  int getExtendedKeyCode() {
+        return (int)extendedKeyCode;
+    }
+    /**
+     * Returns an extended key code for a unicode character.
+     *
+     * @return for a unicode character with a corresponding {@code VK_} constant -- this
+     *   {@code VK_} constant; for a character appearing on the primary
+     *   level of a known keyboard layout -- a unique integer.
+     *   If a character does not appear on the primary level of a known keyboard,
+     *   {@code VK_UNDEFINED} is returned.
+     *
+     * @since 1.7
+     *
+     */
+    public static int getExtendedKeyCodeForChar(int c) {
+        // Return a keycode (if any) associated with a character.
+        return sun.awt.ExtendedKeyCodes.getExtendedKeyCodeForChar(c);
+    }
 
     /**
      * Sets new modifiers by the old ones. The key modifiers
--- a/jdk/src/share/classes/javax/swing/AbstractButton.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/AbstractButton.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1545,6 +1545,9 @@
      * A mnemonic must correspond to a single key on the keyboard
      * and should be specified using one of the <code>VK_XXX</code>
      * keycodes defined in <code>java.awt.event.KeyEvent</code>.
+     * These codes and the wider array of codes for international
+     * keyboards may be obtained through
+     * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
      * Mnemonics are case-insensitive, therefore a key event
      * with the corresponding keycode would cause the button to be
      * activated whether or not the Shift modifier was pressed.
--- a/jdk/src/share/classes/javax/swing/Action.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/Action.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -272,7 +272,9 @@
      * one of the <code>KeyEvent</code> key codes.  The value is
      * commonly used to specify a mnemonic.  For example:
      * <code>myAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A)</code>
-     * sets the mnemonic of <code>myAction</code> to 'a'.
+     * sets the mnemonic of <code>myAction</code> to 'a', while
+     * <code>myAction.putValue(Action.MNEMONIC_KEY, KeyEvent.getExtendedKeyCodeForChar('\u0444'))</code>
+     * sets the mnemonic of <code>myAction</code> to Cyrillic letter "Ef".
      *
      * @since 1.3
      */
--- a/jdk/src/share/classes/javax/swing/JComponent.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/JComponent.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2888,7 +2888,10 @@
           return false;
       }
       // Get the KeyStroke
+      // There may be two keystrokes associated with a low-level key event;
+      // in this case a keystroke made of an extended key code has a priority.
       KeyStroke ks;
+      KeyStroke ksE = null;
 
       if (e.getID() == KeyEvent.KEY_TYPED) {
           ks = KeyStroke.getKeyStroke(e.getKeyChar());
@@ -2896,9 +2899,18 @@
       else {
           ks = KeyStroke.getKeyStroke(e.getKeyCode(),e.getModifiers(),
                                     (pressed ? false:true));
+          if (e.getKeyCode() != e.getExtendedKeyCode()) {
+              ksE = KeyStroke.getKeyStroke(e.getExtendedKeyCode(),e.getModifiers(),
+                                    (pressed ? false:true));
+          }
       }
 
-      /* Do we have a key binding for e? */
+      // Do we have a key binding for e?
+      // If we have a binding by an extended code, use it.
+      // If not, check for regular code binding.
+      if(ksE != null && processKeyBinding(ksE, e, WHEN_FOCUSED, pressed)) {
+          return true;
+      }
       if(processKeyBinding(ks, e, WHEN_FOCUSED, pressed))
           return true;
 
@@ -2910,6 +2922,9 @@
       while (parent != null && !(parent instanceof Window) &&
              !(parent instanceof Applet)) {
           if(parent instanceof JComponent) {
+              if(ksE != null && ((JComponent)parent).processKeyBinding(ksE, e,
+                               WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
+                  return true;
               if(((JComponent)parent).processKeyBinding(ks, e,
                                WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
                   return true;
--- a/jdk/src/share/classes/javax/swing/JLabel.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/JLabel.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -503,10 +503,10 @@
      * @see #setDisplayedMnemonic(int)
      */
     public void setDisplayedMnemonic(char aChar) {
-        int vk = (int) aChar;
-        if(vk >= 'a' && vk <='z')
-            vk -= ('a' - 'A');
-        setDisplayedMnemonic(vk);
+        int vk = java.awt.event.KeyEvent.getExtendedKeyCodeForChar(aChar);
+        if (vk != java.awt.event.KeyEvent.VK_UNDEFINED) {
+            setDisplayedMnemonic(vk);
+        }
     }
 
 
--- a/jdk/src/share/classes/javax/swing/JTabbedPane.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/JTabbedPane.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1628,7 +1628,9 @@
      * <p>
      * A mnemonic must correspond to a single key on the keyboard
      * and should be specified using one of the <code>VK_XXX</code>
-     * keycodes defined in <code>java.awt.event.KeyEvent</code>.
+     * keycodes defined in <code>java.awt.event.KeyEvent</code>
+     * or one of the extended keycodes obtained through
+     * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
      * Mnemonics are case-insensitive, therefore a key event
      * with the corresponding keycode would cause the button to be
      * activated whether or not the Shift modifier was pressed.
--- a/jdk/src/share/classes/javax/swing/KeyStroke.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/KeyStroke.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -162,6 +162,9 @@
      * <li>java.awt.event.KeyEvent.VK_TAB
      * <li>java.awt.event.KeyEvent.VK_SPACE
      * </ul>
+     * Alternatively, the key code may be obtained by calling
+     * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
+     *
      * The modifiers consist of any combination of:<ul>
      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
@@ -210,6 +213,9 @@
      * <li>java.awt.event.KeyEvent.VK_TAB
      * <li>java.awt.event.KeyEvent.VK_SPACE
      * </ul>
+     * Alternatively, the key code may be obtained by calling
+     * <code>java.awt.event.KeyEvent.getExtendedKeyCodeForChar</code>.
+     *
      * The modifiers consist of any combination of:<ul>
      * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
      * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
--- a/jdk/src/share/classes/javax/swing/KeyboardManager.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/KeyboardManager.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -212,19 +212,35 @@
               Thread.dumpStack();
          }
 
+         // There may be two keystrokes associated with a low-level key event;
+         // in this case a keystroke made of an extended key code has a priority.
          KeyStroke ks;
+         KeyStroke ksE = null;
 
 
          if(e.getID() == KeyEvent.KEY_TYPED) {
                ks=KeyStroke.getKeyStroke(e.getKeyChar());
          } else {
+               if(e.getKeyCode() != e.getExtendedKeyCode()) {
+                   ksE=KeyStroke.getKeyStroke(e.getExtendedKeyCode(), e.getModifiers(), !pressed);
+               }
                ks=KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiers(), !pressed);
          }
 
          Hashtable keyMap = containerMap.get(topAncestor);
          if (keyMap != null) { // this container isn't registered, so bail
 
-             Object tmp = keyMap.get(ks);
+             Object tmp = null;
+             // extended code has priority
+             if( ksE != null ) {
+                 tmp = keyMap.get(ksE);
+                 if( tmp != null ) {
+                     ks = ksE;
+                 }
+             }
+             if( tmp == null ) {
+                 tmp = keyMap.get(ks);
+             }
 
              if (tmp == null) {
                // don't do anything
@@ -269,7 +285,12 @@
                  while (iter.hasMoreElements()) {
                      JMenuBar mb = (JMenuBar)iter.nextElement();
                      if ( mb.isShowing() && mb.isEnabled() ) { // don't want to give these out
-                         fireBinding(mb, ks, e, pressed);
+                         if( !(ks.equals(ksE)) ) {
+                             fireBinding(mb, ksE, e, pressed);
+                         }
+                         if(ks.equals(ksE) || !e.isConsumed()) {
+                             fireBinding(mb, ks, e, pressed);
+                         }
                          if (e.isConsumed()) {
                              return true;
                          }
--- a/jdk/src/share/classes/javax/swing/SwingUtilities.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/SwingUtilities.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1589,15 +1589,6 @@
      * processing the key bindings associated with JComponents.
      */
     static boolean isValidKeyEventForKeyBindings(KeyEvent e) {
-        if (e.getID() == KeyEvent.KEY_TYPED) {
-            int mod = e.getModifiers();
-            if (((mod & ActionEvent.ALT_MASK) != 0) &&
-                ((mod & ActionEvent.CTRL_MASK) == 0)) {
-                // filter out typed "alt-?" keys, but not those created
-                // with AltGr, and not control characters
-                return false;
-            }
-        }
         return true;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/awt/ExtendedKeyCodes.java	Fri Mar 27 12:01:24 2009 +0300
@@ -0,0 +1,670 @@
+package sun.awt;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.awt.event.KeyEvent;
+
+public class ExtendedKeyCodes {
+    /**
+     * ATTN: These are the readonly hashes with load factor == 1;
+     * adding a value, please set the inital capacity to exact number of items
+     * or higher.
+     */
+     // Keycodes declared in KeyEvent.java with corresponding Unicode values.
+     private final static HashMap<Integer, Integer>  regularKeyCodesMap =
+                                          new HashMap<Integer,Integer>(122, 1.0f);
+
+     // Keycodes derived from Unicode values. Here should be collected codes
+     // for characters appearing on the primary layer of at least one
+     // known keyboard layout. For instance, sterling sign is on the primary layer
+     // of the Mac Italian layout.
+     private final static HashSet<Integer> extendedKeyCodesSet =
+                                                  new HashSet<Integer>(501, 1.0f);
+     final public static int getExtendedKeyCodeForChar( int c ) {
+         int rc = KeyEvent.VK_UNDEFINED;
+         int uc = Character.toUpperCase( c );
+         int lc = Character.toLowerCase( c );
+         if (regularKeyCodesMap.containsKey( c )) {
+             if(regularKeyCodesMap.containsKey(uc)) {
+                 return regularKeyCodesMap.get( uc );
+             }
+             return regularKeyCodesMap.get( c );
+         }
+         uc += 0x01000000;
+         lc += 0x01000000;
+         if (extendedKeyCodesSet.contains( uc )) {
+             return uc;
+         }else if (extendedKeyCodesSet.contains( lc )) {
+             return lc;
+         }
+         return rc;
+     }
+     static {
+         regularKeyCodesMap.put(0x0a, KeyEvent.VK_ENTER);
+         regularKeyCodesMap.put(0x08, KeyEvent.VK_BACK_SPACE);
+         regularKeyCodesMap.put(0x09, KeyEvent.VK_TAB);
+         regularKeyCodesMap.put(0x1B, KeyEvent.VK_ESCAPE);
+         regularKeyCodesMap.put(0x20, KeyEvent.VK_SPACE);
+         regularKeyCodesMap.put(0x21, KeyEvent.VK_PAGE_UP);
+         regularKeyCodesMap.put(0x22, KeyEvent.VK_PAGE_DOWN);
+         regularKeyCodesMap.put(0x23, KeyEvent.VK_END);
+         regularKeyCodesMap.put(0x24, KeyEvent.VK_HOME);
+         regularKeyCodesMap.put(0x25, KeyEvent.VK_LEFT);
+         regularKeyCodesMap.put(0x26, KeyEvent.VK_UP);
+         regularKeyCodesMap.put(0x27, KeyEvent.VK_RIGHT);
+         regularKeyCodesMap.put(0x28, KeyEvent.VK_DOWN);
+         regularKeyCodesMap.put(0x2C, KeyEvent.VK_COMMA);
+         regularKeyCodesMap.put(0x2D, KeyEvent.VK_MINUS);
+         regularKeyCodesMap.put(0x2E, KeyEvent.VK_PERIOD);
+         regularKeyCodesMap.put(0x2F, KeyEvent.VK_SLASH);
+         regularKeyCodesMap.put(0x30, KeyEvent.VK_0);
+         regularKeyCodesMap.put(0x31, KeyEvent.VK_1);
+         regularKeyCodesMap.put(0x32, KeyEvent.VK_2);
+         regularKeyCodesMap.put(0x33, KeyEvent.VK_3);
+         regularKeyCodesMap.put(0x34, KeyEvent.VK_4);
+         regularKeyCodesMap.put(0x35, KeyEvent.VK_5);
+         regularKeyCodesMap.put(0x36, KeyEvent.VK_6);
+         regularKeyCodesMap.put(0x37, KeyEvent.VK_7);
+         regularKeyCodesMap.put(0x38, KeyEvent.VK_8);
+         regularKeyCodesMap.put(0x39, KeyEvent.VK_9);
+         regularKeyCodesMap.put(0x3B, KeyEvent.VK_SEMICOLON);
+         regularKeyCodesMap.put(0x3D, KeyEvent.VK_EQUALS);
+         regularKeyCodesMap.put(0x41, KeyEvent.VK_A);
+         regularKeyCodesMap.put(0x61, KeyEvent.VK_A);
+         regularKeyCodesMap.put(0x42, KeyEvent.VK_B);
+         regularKeyCodesMap.put(0x62, KeyEvent.VK_B);
+         regularKeyCodesMap.put(0x43, KeyEvent.VK_C);
+         regularKeyCodesMap.put(0x63, KeyEvent.VK_C);
+         regularKeyCodesMap.put(0x44, KeyEvent.VK_D);
+         regularKeyCodesMap.put(0x64, KeyEvent.VK_D);
+         regularKeyCodesMap.put(0x45, KeyEvent.VK_E);
+         regularKeyCodesMap.put(0x65, KeyEvent.VK_E);
+         regularKeyCodesMap.put(0x46, KeyEvent.VK_F);
+         regularKeyCodesMap.put(0x66, KeyEvent.VK_F);
+         regularKeyCodesMap.put(0x47, KeyEvent.VK_G);
+         regularKeyCodesMap.put(0x67, KeyEvent.VK_G);
+         regularKeyCodesMap.put(0x48, KeyEvent.VK_H);
+         regularKeyCodesMap.put(0x68, KeyEvent.VK_H);
+         regularKeyCodesMap.put(0x49, KeyEvent.VK_I);
+         regularKeyCodesMap.put(0x69, KeyEvent.VK_I);
+         regularKeyCodesMap.put(0x4A, KeyEvent.VK_J);
+         regularKeyCodesMap.put(0x6A, KeyEvent.VK_J);
+         regularKeyCodesMap.put(0x4B, KeyEvent.VK_K);
+         regularKeyCodesMap.put(0x6B, KeyEvent.VK_K);
+         regularKeyCodesMap.put(0x4C, KeyEvent.VK_L);
+         regularKeyCodesMap.put(0x6C, KeyEvent.VK_L);
+         regularKeyCodesMap.put(0x4D, KeyEvent.VK_M);
+         regularKeyCodesMap.put(0x6D, KeyEvent.VK_M);
+         regularKeyCodesMap.put(0x4E, KeyEvent.VK_N);
+         regularKeyCodesMap.put(0x6E, KeyEvent.VK_N);
+         regularKeyCodesMap.put(0x4F, KeyEvent.VK_O);
+         regularKeyCodesMap.put(0x6F, KeyEvent.VK_O);
+         regularKeyCodesMap.put(0x50, KeyEvent.VK_P);
+         regularKeyCodesMap.put(0x70, KeyEvent.VK_P);
+         regularKeyCodesMap.put(0x51, KeyEvent.VK_Q);
+         regularKeyCodesMap.put(0x71, KeyEvent.VK_Q);
+         regularKeyCodesMap.put(0x52, KeyEvent.VK_R);
+         regularKeyCodesMap.put(0x72, KeyEvent.VK_R);
+         regularKeyCodesMap.put(0x53, KeyEvent.VK_S);
+         regularKeyCodesMap.put(0x73, KeyEvent.VK_S);
+         regularKeyCodesMap.put(0x54, KeyEvent.VK_T);
+         regularKeyCodesMap.put(0x74, KeyEvent.VK_T);
+         regularKeyCodesMap.put(0x55, KeyEvent.VK_U);
+         regularKeyCodesMap.put(0x75, KeyEvent.VK_U);
+         regularKeyCodesMap.put(0x56, KeyEvent.VK_V);
+         regularKeyCodesMap.put(0x76, KeyEvent.VK_V);
+         regularKeyCodesMap.put(0x57, KeyEvent.VK_W);
+         regularKeyCodesMap.put(0x77, KeyEvent.VK_W);
+         regularKeyCodesMap.put(0x58, KeyEvent.VK_X);
+         regularKeyCodesMap.put(0x78, KeyEvent.VK_X);
+         regularKeyCodesMap.put(0x59, KeyEvent.VK_Y);
+         regularKeyCodesMap.put(0x79, KeyEvent.VK_Y);
+         regularKeyCodesMap.put(0x5A, KeyEvent.VK_Z);
+         regularKeyCodesMap.put(0x7A, KeyEvent.VK_Z);
+         regularKeyCodesMap.put(0x5B, KeyEvent.VK_OPEN_BRACKET);
+         regularKeyCodesMap.put(0x5C, KeyEvent.VK_BACK_SLASH);
+         regularKeyCodesMap.put(0x5D, KeyEvent.VK_CLOSE_BRACKET);
+//         regularKeyCodesMap.put(0x60, KeyEvent.VK_NUMPAD0);
+//         regularKeyCodesMap.put(0x61, KeyEvent.VK_NUMPAD1);
+//         regularKeyCodesMap.put(0x62, KeyEvent.VK_NUMPAD2);
+//         regularKeyCodesMap.put(0x63, KeyEvent.VK_NUMPAD3);
+//         regularKeyCodesMap.put(0x64, KeyEvent.VK_NUMPAD4);
+//         regularKeyCodesMap.put(0x65, KeyEvent.VK_NUMPAD5);
+//         regularKeyCodesMap.put(0x66, KeyEvent.VK_NUMPAD6);
+//         regularKeyCodesMap.put(0x67, KeyEvent.VK_NUMPAD7);
+//         regularKeyCodesMap.put(0x68, KeyEvent.VK_NUMPAD8);
+//         regularKeyCodesMap.put(0x69, KeyEvent.VK_NUMPAD9);
+         regularKeyCodesMap.put(0x6A, KeyEvent.VK_MULTIPLY);
+         regularKeyCodesMap.put(0x6B, KeyEvent.VK_ADD);
+         regularKeyCodesMap.put(0x6C, KeyEvent.VK_SEPARATER);
+         regularKeyCodesMap.put(0x6D, KeyEvent.VK_SUBTRACT);
+         regularKeyCodesMap.put(0x6E, KeyEvent.VK_DECIMAL);
+         regularKeyCodesMap.put(0x6F, KeyEvent.VK_DIVIDE);
+         regularKeyCodesMap.put(0x7F, KeyEvent.VK_DELETE);
+         regularKeyCodesMap.put(0xC0, KeyEvent.VK_BACK_QUOTE);
+         regularKeyCodesMap.put(0xDE, KeyEvent.VK_QUOTE);
+         regularKeyCodesMap.put(0x26, KeyEvent.VK_AMPERSAND);
+         regularKeyCodesMap.put(0x2A, KeyEvent.VK_ASTERISK);
+         regularKeyCodesMap.put(0x22, KeyEvent.VK_QUOTEDBL);
+         regularKeyCodesMap.put(0x3C, KeyEvent.VK_LESS);
+         regularKeyCodesMap.put(0x3E, KeyEvent.VK_GREATER);
+         regularKeyCodesMap.put(0x7B, KeyEvent.VK_BRACELEFT);
+         regularKeyCodesMap.put(0x7D, KeyEvent.VK_BRACERIGHT);
+         regularKeyCodesMap.put(0x40, KeyEvent.VK_AT);
+         regularKeyCodesMap.put(0x3A, KeyEvent.VK_COLON);
+         regularKeyCodesMap.put(0x5E, KeyEvent.VK_CIRCUMFLEX);
+         regularKeyCodesMap.put(0x24, KeyEvent.VK_DOLLAR);
+         regularKeyCodesMap.put(0x20AC, KeyEvent.VK_EURO_SIGN);
+         regularKeyCodesMap.put(0x21, KeyEvent.VK_EXCLAMATION_MARK);
+         regularKeyCodesMap.put(0xA1, KeyEvent.VK_INVERTED_EXCLAMATION_MARK);
+         regularKeyCodesMap.put(0x28, KeyEvent.VK_LEFT_PARENTHESIS);
+         regularKeyCodesMap.put(0x23, KeyEvent.VK_NUMBER_SIGN);
+         regularKeyCodesMap.put(0x2B, KeyEvent.VK_PLUS);
+         regularKeyCodesMap.put(0x29, KeyEvent.VK_RIGHT_PARENTHESIS);
+         regularKeyCodesMap.put(0x5F, KeyEvent.VK_UNDERSCORE);
+
+
+         extendedKeyCodesSet.add(0x01000000+0x0060);
+         extendedKeyCodesSet.add(0x01000000+0x007C);
+         extendedKeyCodesSet.add(0x01000000+0x007E);
+         extendedKeyCodesSet.add(0x01000000+0x00A2);
+         extendedKeyCodesSet.add(0x01000000+0x00A3);
+         extendedKeyCodesSet.add(0x01000000+0x00A5);
+         extendedKeyCodesSet.add(0x01000000+0x00A7);
+         extendedKeyCodesSet.add(0x01000000+0x00A8);
+         extendedKeyCodesSet.add(0x01000000+0x00AB);
+         extendedKeyCodesSet.add(0x01000000+0x00B0);
+         extendedKeyCodesSet.add(0x01000000+0x00B1);
+         extendedKeyCodesSet.add(0x01000000+0x00B2);
+         extendedKeyCodesSet.add(0x01000000+0x00B3);
+         extendedKeyCodesSet.add(0x01000000+0x00B4);
+         extendedKeyCodesSet.add(0x01000000+0x00B5);
+         extendedKeyCodesSet.add(0x01000000+0x00B6);
+         extendedKeyCodesSet.add(0x01000000+0x00B7);
+         extendedKeyCodesSet.add(0x01000000+0x00B9);
+         extendedKeyCodesSet.add(0x01000000+0x00BA);
+         extendedKeyCodesSet.add(0x01000000+0x00BB);
+         extendedKeyCodesSet.add(0x01000000+0x00BC);
+         extendedKeyCodesSet.add(0x01000000+0x00BD);
+         extendedKeyCodesSet.add(0x01000000+0x00BE);
+         extendedKeyCodesSet.add(0x01000000+0x00BF);
+         extendedKeyCodesSet.add(0x01000000+0x00C4);
+         extendedKeyCodesSet.add(0x01000000+0x00C5);
+         extendedKeyCodesSet.add(0x01000000+0x00C6);
+         extendedKeyCodesSet.add(0x01000000+0x00C7);
+         extendedKeyCodesSet.add(0x01000000+0x00D1);
+         extendedKeyCodesSet.add(0x01000000+0x00D6);
+         extendedKeyCodesSet.add(0x01000000+0x00D7);
+         extendedKeyCodesSet.add(0x01000000+0x00D8);
+         extendedKeyCodesSet.add(0x01000000+0x00DF);
+         extendedKeyCodesSet.add(0x01000000+0x00E0);
+         extendedKeyCodesSet.add(0x01000000+0x00E1);
+         extendedKeyCodesSet.add(0x01000000+0x00E2);
+         extendedKeyCodesSet.add(0x01000000+0x00E4);
+         extendedKeyCodesSet.add(0x01000000+0x00E5);
+         extendedKeyCodesSet.add(0x01000000+0x00E6);
+         extendedKeyCodesSet.add(0x01000000+0x00E7);
+         extendedKeyCodesSet.add(0x01000000+0x00E8);
+         extendedKeyCodesSet.add(0x01000000+0x00E9);
+         extendedKeyCodesSet.add(0x01000000+0x00EA);
+         extendedKeyCodesSet.add(0x01000000+0x00EB);
+         extendedKeyCodesSet.add(0x01000000+0x00EC);
+         extendedKeyCodesSet.add(0x01000000+0x00ED);
+         extendedKeyCodesSet.add(0x01000000+0x00EE);
+         extendedKeyCodesSet.add(0x01000000+0x00F0);
+         extendedKeyCodesSet.add(0x01000000+0x00F1);
+         extendedKeyCodesSet.add(0x01000000+0x00F2);
+         extendedKeyCodesSet.add(0x01000000+0x00F3);
+         extendedKeyCodesSet.add(0x01000000+0x00F4);
+         extendedKeyCodesSet.add(0x01000000+0x00F5);
+         extendedKeyCodesSet.add(0x01000000+0x00F6);
+         extendedKeyCodesSet.add(0x01000000+0x00F7);
+         extendedKeyCodesSet.add(0x01000000+0x00F8);
+         extendedKeyCodesSet.add(0x01000000+0x00F9);
+         extendedKeyCodesSet.add(0x01000000+0x00FA);
+         extendedKeyCodesSet.add(0x01000000+0x00FB);
+         extendedKeyCodesSet.add(0x01000000+0x00FC);
+         extendedKeyCodesSet.add(0x01000000+0x00FD);
+         extendedKeyCodesSet.add(0x01000000+0x00FE);
+         extendedKeyCodesSet.add(0x01000000+0x0105);
+         extendedKeyCodesSet.add(0x01000000+0x02DB);
+         extendedKeyCodesSet.add(0x01000000+0x0142);
+         extendedKeyCodesSet.add(0x01000000+0x013E);
+         extendedKeyCodesSet.add(0x01000000+0x015B);
+         extendedKeyCodesSet.add(0x01000000+0x0161);
+         extendedKeyCodesSet.add(0x01000000+0x015F);
+         extendedKeyCodesSet.add(0x01000000+0x0165);
+         extendedKeyCodesSet.add(0x01000000+0x017E);
+         extendedKeyCodesSet.add(0x01000000+0x017C);
+         extendedKeyCodesSet.add(0x01000000+0x0103);
+         extendedKeyCodesSet.add(0x01000000+0x0107);
+         extendedKeyCodesSet.add(0x01000000+0x010D);
+         extendedKeyCodesSet.add(0x01000000+0x0119);
+         extendedKeyCodesSet.add(0x01000000+0x011B);
+         extendedKeyCodesSet.add(0x01000000+0x0111);
+         extendedKeyCodesSet.add(0x01000000+0x0148);
+         extendedKeyCodesSet.add(0x01000000+0x0151);
+         extendedKeyCodesSet.add(0x01000000+0x0171);
+         extendedKeyCodesSet.add(0x01000000+0x0159);
+         extendedKeyCodesSet.add(0x01000000+0x016F);
+         extendedKeyCodesSet.add(0x01000000+0x0163);
+         extendedKeyCodesSet.add(0x01000000+0x02D9);
+         extendedKeyCodesSet.add(0x01000000+0x0130);
+         extendedKeyCodesSet.add(0x01000000+0x0127);
+         extendedKeyCodesSet.add(0x01000000+0x0125);
+         extendedKeyCodesSet.add(0x01000000+0x0131);
+         extendedKeyCodesSet.add(0x01000000+0x011F);
+         extendedKeyCodesSet.add(0x01000000+0x0135);
+         extendedKeyCodesSet.add(0x01000000+0x010B);
+         extendedKeyCodesSet.add(0x01000000+0x0109);
+         extendedKeyCodesSet.add(0x01000000+0x0121);
+         extendedKeyCodesSet.add(0x01000000+0x011D);
+         extendedKeyCodesSet.add(0x01000000+0x016D);
+         extendedKeyCodesSet.add(0x01000000+0x015D);
+         extendedKeyCodesSet.add(0x01000000+0x0138);
+         extendedKeyCodesSet.add(0x01000000+0x0157);
+         extendedKeyCodesSet.add(0x01000000+0x013C);
+         extendedKeyCodesSet.add(0x01000000+0x0113);
+         extendedKeyCodesSet.add(0x01000000+0x0123);
+         extendedKeyCodesSet.add(0x01000000+0x0167);
+         extendedKeyCodesSet.add(0x01000000+0x014B);
+         extendedKeyCodesSet.add(0x01000000+0x0101);
+         extendedKeyCodesSet.add(0x01000000+0x012F);
+         extendedKeyCodesSet.add(0x01000000+0x0117);
+         extendedKeyCodesSet.add(0x01000000+0x012B);
+         extendedKeyCodesSet.add(0x01000000+0x0146);
+         extendedKeyCodesSet.add(0x01000000+0x014D);
+         extendedKeyCodesSet.add(0x01000000+0x0137);
+         extendedKeyCodesSet.add(0x01000000+0x0173);
+         extendedKeyCodesSet.add(0x01000000+0x016B);
+         extendedKeyCodesSet.add(0x01000000+0x0153);
+         extendedKeyCodesSet.add(0x01000000+0x30FC);
+         extendedKeyCodesSet.add(0x01000000+0x30A2);
+         extendedKeyCodesSet.add(0x01000000+0x30A4);
+         extendedKeyCodesSet.add(0x01000000+0x30A6);
+         extendedKeyCodesSet.add(0x01000000+0x30A8);
+         extendedKeyCodesSet.add(0x01000000+0x30AA);
+         extendedKeyCodesSet.add(0x01000000+0x30AB);
+         extendedKeyCodesSet.add(0x01000000+0x30AD);
+         extendedKeyCodesSet.add(0x01000000+0x30AF);
+         extendedKeyCodesSet.add(0x01000000+0x30B1);
+         extendedKeyCodesSet.add(0x01000000+0x30B3);
+         extendedKeyCodesSet.add(0x01000000+0x30B5);
+         extendedKeyCodesSet.add(0x01000000+0x30B7);
+         extendedKeyCodesSet.add(0x01000000+0x30B9);
+         extendedKeyCodesSet.add(0x01000000+0x30BB);
+         extendedKeyCodesSet.add(0x01000000+0x30BD);
+         extendedKeyCodesSet.add(0x01000000+0x30BF);
+         extendedKeyCodesSet.add(0x01000000+0x30C1);
+         extendedKeyCodesSet.add(0x01000000+0x30C4);
+         extendedKeyCodesSet.add(0x01000000+0x30C6);
+         extendedKeyCodesSet.add(0x01000000+0x30C8);
+         extendedKeyCodesSet.add(0x01000000+0x30CA);
+         extendedKeyCodesSet.add(0x01000000+0x30CB);
+         extendedKeyCodesSet.add(0x01000000+0x30CC);
+         extendedKeyCodesSet.add(0x01000000+0x30CD);
+         extendedKeyCodesSet.add(0x01000000+0x30CE);
+         extendedKeyCodesSet.add(0x01000000+0x30CF);
+         extendedKeyCodesSet.add(0x01000000+0x30D2);
+         extendedKeyCodesSet.add(0x01000000+0x30D5);
+         extendedKeyCodesSet.add(0x01000000+0x30D8);
+         extendedKeyCodesSet.add(0x01000000+0x30DB);
+         extendedKeyCodesSet.add(0x01000000+0x30DE);
+         extendedKeyCodesSet.add(0x01000000+0x30DF);
+         extendedKeyCodesSet.add(0x01000000+0x30E0);
+         extendedKeyCodesSet.add(0x01000000+0x30E1);
+         extendedKeyCodesSet.add(0x01000000+0x30E2);
+         extendedKeyCodesSet.add(0x01000000+0x30E4);
+         extendedKeyCodesSet.add(0x01000000+0x30E6);
+         extendedKeyCodesSet.add(0x01000000+0x30E8);
+         extendedKeyCodesSet.add(0x01000000+0x30E9);
+         extendedKeyCodesSet.add(0x01000000+0x30EA);
+         extendedKeyCodesSet.add(0x01000000+0x30EB);
+         extendedKeyCodesSet.add(0x01000000+0x30EC);
+         extendedKeyCodesSet.add(0x01000000+0x30ED);
+         extendedKeyCodesSet.add(0x01000000+0x30EF);
+         extendedKeyCodesSet.add(0x01000000+0x30F3);
+         extendedKeyCodesSet.add(0x01000000+0x309B);
+         extendedKeyCodesSet.add(0x01000000+0x309C);
+         extendedKeyCodesSet.add(0x01000000+0x06F0);
+         extendedKeyCodesSet.add(0x01000000+0x06F1);
+         extendedKeyCodesSet.add(0x01000000+0x06F2);
+         extendedKeyCodesSet.add(0x01000000+0x06F3);
+         extendedKeyCodesSet.add(0x01000000+0x06F4);
+         extendedKeyCodesSet.add(0x01000000+0x06F5);
+         extendedKeyCodesSet.add(0x01000000+0x06F6);
+         extendedKeyCodesSet.add(0x01000000+0x06F7);
+         extendedKeyCodesSet.add(0x01000000+0x06F8);
+         extendedKeyCodesSet.add(0x01000000+0x06F9);
+         extendedKeyCodesSet.add(0x01000000+0x0670);
+         extendedKeyCodesSet.add(0x01000000+0x067E);
+         extendedKeyCodesSet.add(0x01000000+0x0686);
+         extendedKeyCodesSet.add(0x01000000+0x060C);
+         extendedKeyCodesSet.add(0x01000000+0x06D4);
+         extendedKeyCodesSet.add(0x01000000+0x0660);
+         extendedKeyCodesSet.add(0x01000000+0x0661);
+         extendedKeyCodesSet.add(0x01000000+0x0662);
+         extendedKeyCodesSet.add(0x01000000+0x0663);
+         extendedKeyCodesSet.add(0x01000000+0x0664);
+         extendedKeyCodesSet.add(0x01000000+0x0665);
+         extendedKeyCodesSet.add(0x01000000+0x0666);
+         extendedKeyCodesSet.add(0x01000000+0x0667);
+         extendedKeyCodesSet.add(0x01000000+0x0668);
+         extendedKeyCodesSet.add(0x01000000+0x0669);
+         extendedKeyCodesSet.add(0x01000000+0x061B);
+         extendedKeyCodesSet.add(0x01000000+0x0621);
+         extendedKeyCodesSet.add(0x01000000+0x0624);
+         extendedKeyCodesSet.add(0x01000000+0x0626);
+         extendedKeyCodesSet.add(0x01000000+0x0627);
+         extendedKeyCodesSet.add(0x01000000+0x0628);
+         extendedKeyCodesSet.add(0x01000000+0x0629);
+         extendedKeyCodesSet.add(0x01000000+0x062A);
+         extendedKeyCodesSet.add(0x01000000+0x062B);
+         extendedKeyCodesSet.add(0x01000000+0x062C);
+         extendedKeyCodesSet.add(0x01000000+0x062D);
+         extendedKeyCodesSet.add(0x01000000+0x062E);
+         extendedKeyCodesSet.add(0x01000000+0x062F);
+         extendedKeyCodesSet.add(0x01000000+0x0630);
+         extendedKeyCodesSet.add(0x01000000+0x0631);
+         extendedKeyCodesSet.add(0x01000000+0x0632);
+         extendedKeyCodesSet.add(0x01000000+0x0633);
+         extendedKeyCodesSet.add(0x01000000+0x0634);
+         extendedKeyCodesSet.add(0x01000000+0x0635);
+         extendedKeyCodesSet.add(0x01000000+0x0636);
+         extendedKeyCodesSet.add(0x01000000+0x0637);
+         extendedKeyCodesSet.add(0x01000000+0x0638);
+         extendedKeyCodesSet.add(0x01000000+0x0639);
+         extendedKeyCodesSet.add(0x01000000+0x063A);
+         extendedKeyCodesSet.add(0x01000000+0x0641);
+         extendedKeyCodesSet.add(0x01000000+0x0642);
+         extendedKeyCodesSet.add(0x01000000+0x0643);
+         extendedKeyCodesSet.add(0x01000000+0x0644);
+         extendedKeyCodesSet.add(0x01000000+0x0645);
+         extendedKeyCodesSet.add(0x01000000+0x0646);
+         extendedKeyCodesSet.add(0x01000000+0x0647);
+         extendedKeyCodesSet.add(0x01000000+0x0648);
+         extendedKeyCodesSet.add(0x01000000+0x0649);
+         extendedKeyCodesSet.add(0x01000000+0x064A);
+         extendedKeyCodesSet.add(0x01000000+0x064E);
+         extendedKeyCodesSet.add(0x01000000+0x064F);
+         extendedKeyCodesSet.add(0x01000000+0x0650);
+         extendedKeyCodesSet.add(0x01000000+0x0652);
+         extendedKeyCodesSet.add(0x01000000+0x0698);
+         extendedKeyCodesSet.add(0x01000000+0x06A4);
+         extendedKeyCodesSet.add(0x01000000+0x06A9);
+         extendedKeyCodesSet.add(0x01000000+0x06AF);
+         extendedKeyCodesSet.add(0x01000000+0x06BE);
+         extendedKeyCodesSet.add(0x01000000+0x06CC);
+         extendedKeyCodesSet.add(0x01000000+0x06CC);
+         extendedKeyCodesSet.add(0x01000000+0x06D2);
+         extendedKeyCodesSet.add(0x01000000+0x0493);
+         extendedKeyCodesSet.add(0x01000000+0x0497);
+         extendedKeyCodesSet.add(0x01000000+0x049B);
+         extendedKeyCodesSet.add(0x01000000+0x049D);
+         extendedKeyCodesSet.add(0x01000000+0x04A3);
+         extendedKeyCodesSet.add(0x01000000+0x04AF);
+         extendedKeyCodesSet.add(0x01000000+0x04B1);
+         extendedKeyCodesSet.add(0x01000000+0x04B3);
+         extendedKeyCodesSet.add(0x01000000+0x04B9);
+         extendedKeyCodesSet.add(0x01000000+0x04BB);
+         extendedKeyCodesSet.add(0x01000000+0x04D9);
+         extendedKeyCodesSet.add(0x01000000+0x04E9);
+         extendedKeyCodesSet.add(0x01000000+0x0452);
+         extendedKeyCodesSet.add(0x01000000+0x0453);
+         extendedKeyCodesSet.add(0x01000000+0x0451);
+         extendedKeyCodesSet.add(0x01000000+0x0454);
+         extendedKeyCodesSet.add(0x01000000+0x0455);
+         extendedKeyCodesSet.add(0x01000000+0x0456);
+         extendedKeyCodesSet.add(0x01000000+0x0457);
+         extendedKeyCodesSet.add(0x01000000+0x0458);
+         extendedKeyCodesSet.add(0x01000000+0x0459);
+         extendedKeyCodesSet.add(0x01000000+0x045A);
+         extendedKeyCodesSet.add(0x01000000+0x045B);
+         extendedKeyCodesSet.add(0x01000000+0x045C);
+         extendedKeyCodesSet.add(0x01000000+0x0491);
+         extendedKeyCodesSet.add(0x01000000+0x045E);
+         extendedKeyCodesSet.add(0x01000000+0x045F);
+         extendedKeyCodesSet.add(0x01000000+0x2116);
+         extendedKeyCodesSet.add(0x01000000+0x044E);
+         extendedKeyCodesSet.add(0x01000000+0x0430);
+         extendedKeyCodesSet.add(0x01000000+0x0431);
+         extendedKeyCodesSet.add(0x01000000+0x0446);
+         extendedKeyCodesSet.add(0x01000000+0x0434);
+         extendedKeyCodesSet.add(0x01000000+0x0435);
+         extendedKeyCodesSet.add(0x01000000+0x0444);
+         extendedKeyCodesSet.add(0x01000000+0x0433);
+         extendedKeyCodesSet.add(0x01000000+0x0445);
+         extendedKeyCodesSet.add(0x01000000+0x0438);
+         extendedKeyCodesSet.add(0x01000000+0x0439);
+         extendedKeyCodesSet.add(0x01000000+0x043A);
+         extendedKeyCodesSet.add(0x01000000+0x043B);
+         extendedKeyCodesSet.add(0x01000000+0x043C);
+         extendedKeyCodesSet.add(0x01000000+0x043D);
+         extendedKeyCodesSet.add(0x01000000+0x043E);
+         extendedKeyCodesSet.add(0x01000000+0x043F);
+         extendedKeyCodesSet.add(0x01000000+0x044F);
+         extendedKeyCodesSet.add(0x01000000+0x0440);
+         extendedKeyCodesSet.add(0x01000000+0x0441);
+         extendedKeyCodesSet.add(0x01000000+0x0442);
+         extendedKeyCodesSet.add(0x01000000+0x0443);
+         extendedKeyCodesSet.add(0x01000000+0x0436);
+         extendedKeyCodesSet.add(0x01000000+0x0432);
+         extendedKeyCodesSet.add(0x01000000+0x044C);
+         extendedKeyCodesSet.add(0x01000000+0x044B);
+         extendedKeyCodesSet.add(0x01000000+0x0437);
+         extendedKeyCodesSet.add(0x01000000+0x0448);
+         extendedKeyCodesSet.add(0x01000000+0x044D);
+         extendedKeyCodesSet.add(0x01000000+0x0449);
+         extendedKeyCodesSet.add(0x01000000+0x0447);
+         extendedKeyCodesSet.add(0x01000000+0x044A);
+         extendedKeyCodesSet.add(0x01000000+0x2015);
+         extendedKeyCodesSet.add(0x01000000+0x03B1);
+         extendedKeyCodesSet.add(0x01000000+0x03B2);
+         extendedKeyCodesSet.add(0x01000000+0x03B3);
+         extendedKeyCodesSet.add(0x01000000+0x03B4);
+         extendedKeyCodesSet.add(0x01000000+0x03B5);
+         extendedKeyCodesSet.add(0x01000000+0x03B6);
+         extendedKeyCodesSet.add(0x01000000+0x03B7);
+         extendedKeyCodesSet.add(0x01000000+0x03B8);
+         extendedKeyCodesSet.add(0x01000000+0x03B9);
+         extendedKeyCodesSet.add(0x01000000+0x03BA);
+         extendedKeyCodesSet.add(0x01000000+0x03BB);
+         extendedKeyCodesSet.add(0x01000000+0x03BC);
+         extendedKeyCodesSet.add(0x01000000+0x03BD);
+         extendedKeyCodesSet.add(0x01000000+0x03BE);
+         extendedKeyCodesSet.add(0x01000000+0x03BF);
+         extendedKeyCodesSet.add(0x01000000+0x03C0);
+         extendedKeyCodesSet.add(0x01000000+0x03C1);
+         extendedKeyCodesSet.add(0x01000000+0x03C3);
+         extendedKeyCodesSet.add(0x01000000+0x03C2);
+         extendedKeyCodesSet.add(0x01000000+0x03C4);
+         extendedKeyCodesSet.add(0x01000000+0x03C5);
+         extendedKeyCodesSet.add(0x01000000+0x03C6);
+         extendedKeyCodesSet.add(0x01000000+0x03C7);
+         extendedKeyCodesSet.add(0x01000000+0x03C8);
+         extendedKeyCodesSet.add(0x01000000+0x03C9);
+         extendedKeyCodesSet.add(0x01000000+0x2190);
+         extendedKeyCodesSet.add(0x01000000+0x2192);
+         extendedKeyCodesSet.add(0x01000000+0x2193);
+         extendedKeyCodesSet.add(0x01000000+0x2013);
+         extendedKeyCodesSet.add(0x01000000+0x201C);
+         extendedKeyCodesSet.add(0x01000000+0x201D);
+         extendedKeyCodesSet.add(0x01000000+0x201E);
+         extendedKeyCodesSet.add(0x01000000+0x05D0);
+         extendedKeyCodesSet.add(0x01000000+0x05D1);
+         extendedKeyCodesSet.add(0x01000000+0x05D2);
+         extendedKeyCodesSet.add(0x01000000+0x05D3);
+         extendedKeyCodesSet.add(0x01000000+0x05D4);
+         extendedKeyCodesSet.add(0x01000000+0x05D5);
+         extendedKeyCodesSet.add(0x01000000+0x05D6);
+         extendedKeyCodesSet.add(0x01000000+0x05D7);
+         extendedKeyCodesSet.add(0x01000000+0x05D8);
+         extendedKeyCodesSet.add(0x01000000+0x05D9);
+         extendedKeyCodesSet.add(0x01000000+0x05DA);
+         extendedKeyCodesSet.add(0x01000000+0x05DB);
+         extendedKeyCodesSet.add(0x01000000+0x05DC);
+         extendedKeyCodesSet.add(0x01000000+0x05DD);
+         extendedKeyCodesSet.add(0x01000000+0x05DE);
+         extendedKeyCodesSet.add(0x01000000+0x05DF);
+         extendedKeyCodesSet.add(0x01000000+0x05E0);
+         extendedKeyCodesSet.add(0x01000000+0x05E1);
+         extendedKeyCodesSet.add(0x01000000+0x05E2);
+         extendedKeyCodesSet.add(0x01000000+0x05E3);
+         extendedKeyCodesSet.add(0x01000000+0x05E4);
+         extendedKeyCodesSet.add(0x01000000+0x05E5);
+         extendedKeyCodesSet.add(0x01000000+0x05E6);
+         extendedKeyCodesSet.add(0x01000000+0x05E7);
+         extendedKeyCodesSet.add(0x01000000+0x05E8);
+         extendedKeyCodesSet.add(0x01000000+0x05E9);
+         extendedKeyCodesSet.add(0x01000000+0x05EA);
+         extendedKeyCodesSet.add(0x01000000+0x0E01);
+         extendedKeyCodesSet.add(0x01000000+0x0E02);
+         extendedKeyCodesSet.add(0x01000000+0x0E03);
+         extendedKeyCodesSet.add(0x01000000+0x0E04);
+         extendedKeyCodesSet.add(0x01000000+0x0E05);
+         extendedKeyCodesSet.add(0x01000000+0x0E07);
+         extendedKeyCodesSet.add(0x01000000+0x0E08);
+         extendedKeyCodesSet.add(0x01000000+0x0E0A);
+         extendedKeyCodesSet.add(0x01000000+0x0E0C);
+         extendedKeyCodesSet.add(0x01000000+0x0E14);
+         extendedKeyCodesSet.add(0x01000000+0x0E15);
+         extendedKeyCodesSet.add(0x01000000+0x0E16);
+         extendedKeyCodesSet.add(0x01000000+0x0E17);
+         extendedKeyCodesSet.add(0x01000000+0x0E19);
+         extendedKeyCodesSet.add(0x01000000+0x0E1A);
+         extendedKeyCodesSet.add(0x01000000+0x0E1B);
+         extendedKeyCodesSet.add(0x01000000+0x0E1C);
+         extendedKeyCodesSet.add(0x01000000+0x0E1D);
+         extendedKeyCodesSet.add(0x01000000+0x0E1E);
+         extendedKeyCodesSet.add(0x01000000+0x0E1F);
+         extendedKeyCodesSet.add(0x01000000+0x0E20);
+         extendedKeyCodesSet.add(0x01000000+0x0E21);
+         extendedKeyCodesSet.add(0x01000000+0x0E22);
+         extendedKeyCodesSet.add(0x01000000+0x0E23);
+         extendedKeyCodesSet.add(0x01000000+0x0E25);
+         extendedKeyCodesSet.add(0x01000000+0x0E27);
+         extendedKeyCodesSet.add(0x01000000+0x0E2A);
+         extendedKeyCodesSet.add(0x01000000+0x0E2B);
+         extendedKeyCodesSet.add(0x01000000+0x0E2D);
+         extendedKeyCodesSet.add(0x01000000+0x0E30);
+         extendedKeyCodesSet.add(0x01000000+0x0E31);
+         extendedKeyCodesSet.add(0x01000000+0x0E32);
+         extendedKeyCodesSet.add(0x01000000+0x0E33);
+         extendedKeyCodesSet.add(0x01000000+0x0E34);
+         extendedKeyCodesSet.add(0x01000000+0x0E35);
+         extendedKeyCodesSet.add(0x01000000+0x0E36);
+         extendedKeyCodesSet.add(0x01000000+0x0E37);
+         extendedKeyCodesSet.add(0x01000000+0x0E38);
+         extendedKeyCodesSet.add(0x01000000+0x0E39);
+         extendedKeyCodesSet.add(0x01000000+0x0E3F);
+         extendedKeyCodesSet.add(0x01000000+0x0E40);
+         extendedKeyCodesSet.add(0x01000000+0x0E41);
+         extendedKeyCodesSet.add(0x01000000+0x0E43);
+         extendedKeyCodesSet.add(0x01000000+0x0E44);
+         extendedKeyCodesSet.add(0x01000000+0x0E45);
+         extendedKeyCodesSet.add(0x01000000+0x0E46);
+         extendedKeyCodesSet.add(0x01000000+0x0E47);
+         extendedKeyCodesSet.add(0x01000000+0x0E48);
+         extendedKeyCodesSet.add(0x01000000+0x0E49);
+         extendedKeyCodesSet.add(0x01000000+0x0E50);
+         extendedKeyCodesSet.add(0x01000000+0x0E51);
+         extendedKeyCodesSet.add(0x01000000+0x0E52);
+         extendedKeyCodesSet.add(0x01000000+0x0E53);
+         extendedKeyCodesSet.add(0x01000000+0x0E54);
+         extendedKeyCodesSet.add(0x01000000+0x0E55);
+         extendedKeyCodesSet.add(0x01000000+0x0E56);
+         extendedKeyCodesSet.add(0x01000000+0x0E57);
+         extendedKeyCodesSet.add(0x01000000+0x0E58);
+         extendedKeyCodesSet.add(0x01000000+0x0E59);
+         extendedKeyCodesSet.add(0x01000000+0x0587);
+         extendedKeyCodesSet.add(0x01000000+0x0589);
+         extendedKeyCodesSet.add(0x01000000+0x0589);
+         extendedKeyCodesSet.add(0x01000000+0x055D);
+         extendedKeyCodesSet.add(0x01000000+0x055D);
+         extendedKeyCodesSet.add(0x01000000+0x055B);
+         extendedKeyCodesSet.add(0x01000000+0x055B);
+         extendedKeyCodesSet.add(0x01000000+0x055E);
+         extendedKeyCodesSet.add(0x01000000+0x055E);
+         extendedKeyCodesSet.add(0x01000000+0x0561);
+         extendedKeyCodesSet.add(0x01000000+0x0562);
+         extendedKeyCodesSet.add(0x01000000+0x0563);
+         extendedKeyCodesSet.add(0x01000000+0x0564);
+         extendedKeyCodesSet.add(0x01000000+0x0565);
+         extendedKeyCodesSet.add(0x01000000+0x0566);
+         extendedKeyCodesSet.add(0x01000000+0x0567);
+         extendedKeyCodesSet.add(0x01000000+0x0568);
+         extendedKeyCodesSet.add(0x01000000+0x0569);
+         extendedKeyCodesSet.add(0x01000000+0x056A);
+         extendedKeyCodesSet.add(0x01000000+0x056B);
+         extendedKeyCodesSet.add(0x01000000+0x056C);
+         extendedKeyCodesSet.add(0x01000000+0x056D);
+         extendedKeyCodesSet.add(0x01000000+0x056E);
+         extendedKeyCodesSet.add(0x01000000+0x056F);
+         extendedKeyCodesSet.add(0x01000000+0x0570);
+         extendedKeyCodesSet.add(0x01000000+0x0571);
+         extendedKeyCodesSet.add(0x01000000+0x0572);
+         extendedKeyCodesSet.add(0x01000000+0x0573);
+         extendedKeyCodesSet.add(0x01000000+0x0574);
+         extendedKeyCodesSet.add(0x01000000+0x0575);
+         extendedKeyCodesSet.add(0x01000000+0x0576);
+         extendedKeyCodesSet.add(0x01000000+0x0577);
+         extendedKeyCodesSet.add(0x01000000+0x0578);
+         extendedKeyCodesSet.add(0x01000000+0x0579);
+         extendedKeyCodesSet.add(0x01000000+0x057A);
+         extendedKeyCodesSet.add(0x01000000+0x057B);
+         extendedKeyCodesSet.add(0x01000000+0x057C);
+         extendedKeyCodesSet.add(0x01000000+0x057D);
+         extendedKeyCodesSet.add(0x01000000+0x057E);
+         extendedKeyCodesSet.add(0x01000000+0x057F);
+         extendedKeyCodesSet.add(0x01000000+0x0580);
+         extendedKeyCodesSet.add(0x01000000+0x0581);
+         extendedKeyCodesSet.add(0x01000000+0x0582);
+         extendedKeyCodesSet.add(0x01000000+0x0583);
+         extendedKeyCodesSet.add(0x01000000+0x0584);
+         extendedKeyCodesSet.add(0x01000000+0x0585);
+         extendedKeyCodesSet.add(0x01000000+0x0586);
+         extendedKeyCodesSet.add(0x01000000+0x10D0);
+         extendedKeyCodesSet.add(0x01000000+0x10D1);
+         extendedKeyCodesSet.add(0x01000000+0x10D2);
+         extendedKeyCodesSet.add(0x01000000+0x10D3);
+         extendedKeyCodesSet.add(0x01000000+0x10D4);
+         extendedKeyCodesSet.add(0x01000000+0x10D5);
+         extendedKeyCodesSet.add(0x01000000+0x10D6);
+         extendedKeyCodesSet.add(0x01000000+0x10D7);
+         extendedKeyCodesSet.add(0x01000000+0x10D8);
+         extendedKeyCodesSet.add(0x01000000+0x10D9);
+         extendedKeyCodesSet.add(0x01000000+0x10DA);
+         extendedKeyCodesSet.add(0x01000000+0x10DB);
+         extendedKeyCodesSet.add(0x01000000+0x10DC);
+         extendedKeyCodesSet.add(0x01000000+0x10DD);
+         extendedKeyCodesSet.add(0x01000000+0x10DE);
+         extendedKeyCodesSet.add(0x01000000+0x10DF);
+         extendedKeyCodesSet.add(0x01000000+0x10E0);
+         extendedKeyCodesSet.add(0x01000000+0x10E1);
+         extendedKeyCodesSet.add(0x01000000+0x10E2);
+         extendedKeyCodesSet.add(0x01000000+0x10E3);
+         extendedKeyCodesSet.add(0x01000000+0x10E4);
+         extendedKeyCodesSet.add(0x01000000+0x10E5);
+         extendedKeyCodesSet.add(0x01000000+0x10E6);
+         extendedKeyCodesSet.add(0x01000000+0x10E7);
+         extendedKeyCodesSet.add(0x01000000+0x10E8);
+         extendedKeyCodesSet.add(0x01000000+0x10E9);
+         extendedKeyCodesSet.add(0x01000000+0x10EA);
+         extendedKeyCodesSet.add(0x01000000+0x10EB);
+         extendedKeyCodesSet.add(0x01000000+0x10EC);
+         extendedKeyCodesSet.add(0x01000000+0x10ED);
+         extendedKeyCodesSet.add(0x01000000+0x10EE);
+         extendedKeyCodesSet.add(0x01000000+0x10EF);
+         extendedKeyCodesSet.add(0x01000000+0x10F0);
+         extendedKeyCodesSet.add(0x01000000+0x01E7);
+         extendedKeyCodesSet.add(0x01000000+0x0259);
+         extendedKeyCodesSet.add(0x01000000+0x1EB9);
+         extendedKeyCodesSet.add(0x01000000+0x1ECB);
+         extendedKeyCodesSet.add(0x01000000+0x1ECD);
+         extendedKeyCodesSet.add(0x01000000+0x1EE5);
+         extendedKeyCodesSet.add(0x01000000+0x01A1);
+         extendedKeyCodesSet.add(0x01000000+0x01B0);
+         extendedKeyCodesSet.add(0x01000000+0x20AB);
+     }
+}
--- a/jdk/src/solaris/classes/sun/awt/X11/XConstants.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XConstants.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -684,4 +684,19 @@
 
     public static final int LSBFirst = 0 ;
     public static final int MSBFirst = 1 ;
+
+    /* XKB support */
+    public static final int  XkbUseCoreKbd = 0x0100 ;
+    public static final int  XkbNewKeyboardNotify = 0;
+    public static final int  XkbMapNotify = 1;
+    public static final int  XkbStateNotify = 2;
+    public static final long XkbNewKeyboardNotifyMask = (1L << 0);
+    public static final long XkbMapNotifyMask = (1L << 1);
+    public static final long XkbStateNotifyMask = (1L << 2);
+    public static final long XkbGroupStateMask  = (1L << 4);
+    public static final long XkbKeyTypesMask = (1L<<0);
+    public static final long XkbKeySymsMask = (1L<<1);
+    public static final long XkbModifierMapMask = (1L<<2);
+    public static final long XkbVirtualModsMask = (1L<<6); //server map
+
 }
--- a/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XKeysym.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,7 +1,7 @@
 // This is a generated file: do not edit! Edit keysym2ucs.h if necessary.
 
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,14 +89,47 @@
         Character ch = keysym2UCSHash.get(ks);
         return ch == null ? (char)0 : ch.charValue();
     }
+    static long xkeycode2keysym_noxkb(XKeyEvent ev, int ndx) {
+        XToolkit.awtLock();
+        try {
+            return XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx);
+        } finally {
+            XToolkit.awtUnlock();
+        }
+    }
+    static long xkeycode2keysym_xkb(XKeyEvent ev, int ndx) {
+        XToolkit.awtLock();
+        try {
+            int mods = ev.get_state();
+            if ((ndx == 0) && ((mods & XConstants.ShiftMask) != 0)) {
+                // I don't know all possible meanings of 'ndx' in case of XKB
+                // and don't want to speculate. But this particular case
+                // clearly means that caller needs a so called primary keysym.
+                mods ^= XConstants.ShiftMask;
+            }
+            XlibWrapper.XkbTranslateKeyCode(XToolkit.getXKBKbdDesc(), ev.get_keycode(),
+                       mods, XlibWrapper.iarg1, XlibWrapper.larg3);
+            //XXX unconsumed modifiers?
+            return Native.getLong(XlibWrapper.larg3);
+        } finally {
+            XToolkit.awtUnlock();
+        }
+    }
     static long xkeycode2keysym(XKeyEvent ev, int ndx) {
         XToolkit.awtLock();
         try {
-            return XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx );
+            if (XToolkit.canUseXKBCalls()) {
+                return xkeycode2keysym_xkb(ev, ndx);
+            }else{
+                return xkeycode2keysym_noxkb(ev, ndx);
+            }
         } finally {
             XToolkit.awtUnlock();
         }
     }
+    static long xkeycode2primary_keysym(XKeyEvent ev) {
+        return xkeycode2keysym(ev, 0);
+    }
     public static boolean isKPEvent( XKeyEvent ev )
     {
         // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
@@ -198,6 +231,27 @@
         Keysym2JavaKeycode jkc = getJavaKeycode( ev );
         return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
     }
+    /**
+     * Return an integer java keycode apprx as it was before extending keycodes range.
+     * This call would ignore for instance XKB and process whatever is on the bottom
+     * of keysym stack. Result will not depend on actual locale, will differ between
+     * dual/multiple keyboard setup systems (e.g. English+Russian vs French+Russian)
+     * but will be someway compatible with old releases.
+     */
+    static int getLegacyJavaKeycodeOnly( XKeyEvent ev ) {
+        long keysym = XConstants.NoSymbol;
+        int ndx = 0;
+        if( (ev.get_state() & XToolkit.numLockMask) != 0 &&
+             isKPEvent(ev)) {
+            keysym = getKeypadKeysym( ev );
+        } else {
+            // we only need primary-layer keysym to derive a java keycode.
+            ndx = 0;
+            keysym = xkeycode2keysym_noxkb(ev, ndx);
+        }
+        Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym );
+        return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
+    }
     static long javaKeycode2Keysym( int jkey ) {
         Long ks = javaKeycode2KeysymHash.get( jkey );
         return  (ks == null ? 0 : ks.longValue());
--- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java	Fri Mar 27 12:01:24 2009 +0300
@@ -292,6 +292,7 @@
             if (XlibWrapper.XSetLocaleModifiers("") == null) {
                 log.finer("X locale modifiers are not supported, using default");
             }
+            tryXKB();
 
             AwtScreenData defaultScreen = new AwtScreenData(XToolkit.getDefaultScreenData());
             awt_defaultFg = defaultScreen.get_blackpixel();
@@ -314,6 +315,7 @@
                     if (xs != null) {
                         ((XAWTXSettings)xs).dispose();
                     }
+                    freeXKB();
                     if (log.isLoggable(Level.FINE)) {
                         dumpPeers();
                     }
@@ -592,6 +594,9 @@
                 if (ev.get_type() != XConstants.NoExpose) {
                     eventNumber++;
                 }
+                if (awt_UseXKB_Calls && ev.get_type() ==  awt_XKBBaseEventCode) {
+                    processXkbChanges(ev);
+                }
 
                 if (XDropTargetEventProcessor.processEvent(ev) ||
                     XDragSourceContextPeer.processEvent(ev)) {
@@ -2094,8 +2099,12 @@
 
     static boolean awt_ServerInquired = false;
     static boolean awt_IsXsunServer    = false;
-    static boolean awt_XKBInquired    = false;
     static boolean awt_UseXKB         = false;
+    static boolean awt_UseXKB_Calls   = false;
+    static int     awt_XKBBaseEventCode = 0;
+    static int     awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations
+                                              // to XkbTranslateKeyCode
+    static long    awt_XKBDescPtr     = 0;
     /**
        Try to understand if it is Xsun server.
        By now (2005) Sun is vendor of Xsun and Xorg servers; we only return true if Xsun is running.
@@ -2125,23 +2134,143 @@
             awtUnlock();
         }
     }
-    /**
-      Query XKEYBOARD extension.
-    */
     static boolean isXKBenabled() {
         awtLock();
         try {
-            if( awt_XKBInquired ) {
-                return awt_UseXKB;
+            return awt_UseXKB;
+        } finally {
+            awtUnlock();
+        }
+    }
+
+    /**
+      Query XKEYBOARD extension.
+      If possible, initialize xkb library.
+    */
+    static boolean tryXKB() {
+        awtLock();
+        try {
+            String name = "XKEYBOARD";
+            // First, if there is extension at all.
+            awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3);
+            if( awt_UseXKB ) {
+                // There is a keyboard extension. Check if a client library is compatible.
+                // If not, don't use xkb calls.
+                // In this case we still may be Xkb-capable application.
+                awt_UseXKB_Calls = XlibWrapper.XkbLibraryVersion( XlibWrapper.larg1, XlibWrapper.larg2);
+                if( awt_UseXKB_Calls ) {
+                    awt_UseXKB_Calls = XlibWrapper.XkbQueryExtension( getDisplay(),  XlibWrapper.larg1, XlibWrapper.larg2,
+                                     XlibWrapper.larg3, XlibWrapper.larg4, XlibWrapper.larg5);
+                    if( awt_UseXKB_Calls ) {
+                        awt_XKBBaseEventCode = Native.getInt(XlibWrapper.larg2);
+                        XlibWrapper.XkbSelectEvents (getDisplay(),
+                                         XConstants.XkbUseCoreKbd,
+                                         XConstants.XkbNewKeyboardNotifyMask |
+                                                 XConstants.XkbMapNotifyMask ,//|
+                                                 //XConstants.XkbStateNotifyMask,
+                                         XConstants.XkbNewKeyboardNotifyMask |
+                                                 XConstants.XkbMapNotifyMask );//|
+                                                 //XConstants.XkbStateNotifyMask);
+
+                        XlibWrapper.XkbSelectEventDetails(getDisplay(), XConstants.XkbUseCoreKbd,
+                                                     XConstants.XkbStateNotify,
+                                                     XConstants.XkbGroupStateMask,
+                                                     XConstants.XkbGroupStateMask);
+                                                     //XXX ? XkbGroupLockMask last, XkbAllStateComponentsMask before last?
+                        awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
+                                                     XConstants.XkbKeyTypesMask    |
+                                                     XConstants.XkbKeySymsMask     |
+                                                     XConstants.XkbModifierMapMask |
+                                                     XConstants.XkbVirtualModsMask,
+                                                     XConstants.XkbUseCoreKbd);
+                    }
+                }
             }
-            awt_XKBInquired = true;
-            String name = "XKEYBOARD";
-            awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3);
             return awt_UseXKB;
         } finally {
             awtUnlock();
         }
     }
+    static boolean canUseXKBCalls() {
+        awtLock();
+        try {
+            return awt_UseXKB_Calls;
+        } finally {
+            awtUnlock();
+        }
+    }
+    static int getXKBEffectiveGroup() {
+        awtLock();
+        try {
+            return awt_XKBEffectiveGroup;
+        } finally {
+            awtUnlock();
+        }
+    }
+    static int getXKBBaseEventCode() {
+        awtLock();
+        try {
+            return awt_XKBBaseEventCode;
+        } finally {
+            awtUnlock();
+        }
+    }
+    static long getXKBKbdDesc() {
+        awtLock();
+        try {
+            return awt_XKBDescPtr;
+        } finally {
+            awtUnlock();
+        }
+    }
+    void freeXKB() {
+        awtLock();
+        try {
+            if (awt_UseXKB_Calls && awt_XKBDescPtr != 0) {
+                XlibWrapper.XkbFreeKeyboard(awt_XKBDescPtr, 0xFF, true);
+            }
+        } finally {
+            awtUnlock();
+        }
+    }
+    private void processXkbChanges(XEvent ev) {
+        // mapping change --> refresh kbd map
+        // state change --> get a new effective group; do I really need it
+        //  or that should be left for XkbTranslateKeyCode?
+        XkbEvent xke = new XkbEvent( ev.getPData() );
+        int xkb_type = xke.get_any().get_xkb_type();
+        switch( xkb_type ) {
+            case XConstants.XkbNewKeyboardNotify :
+                 if( awt_XKBDescPtr != 0 ) {
+                     freeXKB();
+                 }
+                 awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
+                                              XConstants.XkbKeyTypesMask    |
+                                              XConstants.XkbKeySymsMask     |
+                                              XConstants.XkbModifierMapMask |
+                                              XConstants.XkbVirtualModsMask,
+                                              XConstants.XkbUseCoreKbd);
+                 //System.out.println("XkbNewKeyboard:"+(xke.get_new_kbd()));
+                 break;
+            case XConstants.XkbMapNotify :
+                 //TODO: provide a simple unit test.
+                 XlibWrapper.XkbGetUpdatedMap(getDisplay(),
+                                              XConstants.XkbKeyTypesMask    |
+                                              XConstants.XkbKeySymsMask     |
+                                              XConstants.XkbModifierMapMask |
+                                              XConstants.XkbVirtualModsMask,
+                                              awt_XKBDescPtr);
+                 //System.out.println("XkbMap:"+(xke.get_map()));
+                 break;
+            case XConstants.XkbStateNotify :
+                 // May use it later e.g. to obtain an effective group etc.
+                 //System.out.println("XkbState:"+(xke.get_state()));
+                 break;
+            default:
+                 //System.out.println("XkbEvent of xkb_type "+xkb_type);
+                 break;
+        }
+    }
 
     private static long eventNumber;
     public static long getEventNumber() {
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindow.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -128,6 +128,9 @@
     private native static void initIDs();
 
     private static Field isPostedField;
+    private static Field rawCodeField;
+    private static Field primaryLevelUnicodeField;
+    private static Field extendedKeyCodeField;
     static {
         initIDs();
     }
@@ -1037,7 +1040,7 @@
        Parameter is a keysym basically from keysymdef.h
        XXX: how about vendor keys? Is there some with Unicode value and not in the list?
     */
-    char keysymToUnicode( long keysym, int state ) {
+    int keysymToUnicode( long keysym, int state ) {
         return XKeysym.convertKeysym( keysym, state );
     }
     int keyEventType2Id( int xEventType ) {
@@ -1047,6 +1050,13 @@
     static private long xkeycodeToKeysym(XKeyEvent ev) {
         return XKeysym.getKeysym( ev );
     }
+    private long xkeycodeToPrimaryKeysym(XKeyEvent ev) {
+        return XKeysym.xkeycode2primary_keysym( ev );
+    }
+    static private int primaryUnicode2JavaKeycode(int uni) {
+        return (uni > 0? sun.awt.ExtendedKeyCodes.getExtendedKeyCodeForChar(uni) : 0);
+        //return (uni > 0? uni + 0x01000000 : 0);
+    }
     void logIncomingKeyEvent(XKeyEvent ev) {
         keyEventLog.fine("--XWindow.java:handleKeyEvent:"+ev);
         dumpKeysymArray(ev);
@@ -1065,7 +1075,7 @@
     // un-final it if you need to override it in a subclass.
     final void handleKeyPress(XKeyEvent ev) {
         long keysym[] = new long[2];
-        char unicodeKey = 0;
+        int unicodeKey = 0;
         keysym[0] = XConstants.NoSymbol;
 
         if (keyEventLog.isLoggable(Level.FINE)) {
@@ -1110,19 +1120,36 @@
         if( jkc == null ) {
             jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN);
         }
+
+        // Take the first keysym from a keysym array associated with the XKeyevent
+        // and convert it to Unicode. Then, even if a Java keycode for the keystroke
+        // is undefined, we still have a guess of what has been engraved on a keytop.
+        int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0);
+
         if (keyEventLog.isLoggable(Level.FINE)) {
             keyEventLog.fine(">>>Fire Event:"+
                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
                "jkeycode:decimal="+jkc.getJavaKeycode()+
-               ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "
+               ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+
+               " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+
+               ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; "
             );
         }
+
+        int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible
+        int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ?
+                           primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) :
+                             jkc.getJavaKeycode();
         postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED,
                           ev.get_time(),
-                          jkc.getJavaKeycode(),
+                          jkeyToReturn,
                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
                           jkc.getKeyLocation(),
-                          ev.get_state(),ev.getPData(), XKeyEvent.getSize());
+                          ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()),
+                          unicodeFromPrimaryKeysym,
+                          jkeyExtended);
+
+
         if( unicodeKey > 0 ) {
                 keyEventLog.fine("fire _TYPED on "+unicodeKey);
                 postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED,
@@ -1130,7 +1157,10 @@
                               java.awt.event.KeyEvent.VK_UNDEFINED,
                               unicodeKey,
                               java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN,
-                              ev.get_state(),ev.getPData(), XKeyEvent.getSize());
+                              ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)0,
+                              unicodeFromPrimaryKeysym,
+                              java.awt.event.KeyEvent.VK_UNDEFINED);
+
         }
 
 
@@ -1148,7 +1178,7 @@
     // un-private it if you need to call it from elsewhere
     private void handleKeyRelease(XKeyEvent ev) {
         long keysym[] = new long[2];
-        char unicodeKey = 0;
+        int unicodeKey = 0;
         keysym[0] = XConstants.NoSymbol;
 
         if (keyEventLog.isLoggable(Level.FINE)) {
@@ -1166,7 +1196,9 @@
             keyEventLog.fine(">>>Fire Event:"+
                (ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+
                "jkeycode:decimal="+jkc.getJavaKeycode()+
-               ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "
+               ", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; "+
+               " legacy jkeycode: decimal="+XKeysym.getLegacyJavaKeycodeOnly(ev)+
+               ", hex=0x"+Integer.toHexString(XKeysym.getLegacyJavaKeycodeOnly(ev))+"; "
             );
         }
         // We obtain keysym from IM and derive unicodeKey from it for KeyPress only.
@@ -1177,12 +1209,24 @@
         // That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode.
         unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() );
 
+        // Take a first keysym from a keysym array associated with the XKeyevent
+        // and convert it to Unicode. Then, even if Java keycode for the keystroke
+        // is undefined, we still will have a guess of what was engraved on a keytop.
+        int unicodeFromPrimaryKeysym = keysymToUnicode( xkeycodeToPrimaryKeysym(ev) ,0);
+
+        int jkeyToReturn = XKeysym.getLegacyJavaKeycodeOnly(ev); // someway backward compatible
+        int jkeyExtended = jkc.getJavaKeycode() == java.awt.event.KeyEvent.VK_UNDEFINED ?
+                           primaryUnicode2JavaKeycode( unicodeFromPrimaryKeysym ) :
+                             jkc.getJavaKeycode();
         postKeyEvent(  java.awt.event.KeyEvent.KEY_RELEASED,
                           ev.get_time(),
-                          jkc.getJavaKeycode(),
+                          jkeyToReturn,
                           (unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey),
                           jkc.getKeyLocation(),
-                          ev.get_state(),ev.getPData(), XKeyEvent.getSize());
+                          ev.get_state(),ev.getPData(), XKeyEvent.getSize(), (long)(ev.get_keycode()),
+                          unicodeFromPrimaryKeysym,
+                          jkeyExtended);
+
 
     }
 
@@ -1379,17 +1423,38 @@
         }
     }
 
-    public void postKeyEvent(int id, long when, int keyCode, char keyChar,
-        int keyLocation, int state, long event, int eventSize)
+    public void postKeyEvent(int id, long when, int keyCode, int keyChar,
+        int keyLocation, int state, long event, int eventSize, long rawCode,
+        int unicodeFromPrimaryKeysym, int extendedKeyCode)
+
     {
         long jWhen = XToolkit.nowMillisUTC_offset(when);
         int modifiers = getModifiers(state, 0, keyCode);
+        if (rawCodeField == null) {
+            rawCodeField = XToolkit.getField(KeyEvent.class, "rawCode");
+        }
+        if (primaryLevelUnicodeField == null) {
+            primaryLevelUnicodeField = XToolkit.getField(KeyEvent.class, "primaryLevelUnicode");
+        }
+        if (extendedKeyCodeField == null) {
+            extendedKeyCodeField = XToolkit.getField(KeyEvent.class, "extendedKeyCode");
+        }
+
         KeyEvent ke = new KeyEvent((Component)getEventSource(), id, jWhen,
-                                   modifiers, keyCode, keyChar, keyLocation);
+                                   modifiers, keyCode, (char)keyChar, keyLocation);
         if (event != 0) {
             byte[] data = Native.toBytes(event, eventSize);
             setBData(ke, data);
         }
+        try {
+            rawCodeField.set(ke, rawCode);
+            primaryLevelUnicodeField.set(ke, (long)unicodeFromPrimaryKeysym);
+            extendedKeyCodeField.set(ke, (long)extendedKeyCode);
+        } catch (IllegalArgumentException e) {
+            assert(false);
+        } catch (IllegalAccessException e) {
+            assert(false);
+        }
         postEventToEventQueue(ke);
     }
 
--- a/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/XlibWrapper.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -492,6 +492,21 @@
 
     static native int XKeysymToKeycode(long display, long keysym);
 
+    // xkb-related
+    static native int XkbGetEffectiveGroup(long display);
+    static native long XkbKeycodeToKeysym(long display, int keycode, int group, int level);
+    static native void XkbSelectEvents(long display, long device, long bits_to_change, long values_for_bits);
+    static native void XkbSelectEventDetails(long display, long device, long event_type,
+                                              long bits_to_change, long values_for_bits);
+    static native boolean XkbQueryExtension(long display, long opcode_rtrn, long event_rtrn,
+              long error_rtrn, long major_in_out, long minor_in_out);
+    static native boolean XkbLibraryVersion(long lib_major_in_out, long lib_minor_in_out);
+    static native long XkbGetMap(long display, long which, long device_spec);
+    static native long XkbGetUpdatedMap(long display, long which, long xkb);
+    static native void XkbFreeKeyboard(long xkb, long which, boolean free_all);
+    static native boolean XkbTranslateKeyCode(long xkb, int keycode, long mods, long mods_rtrn, long keysym_rtrn);
+
+
     static native void XConvertCase(long keysym,
                                     long keysym_lowercase,
                                     long keysym_uppercase);
@@ -617,6 +632,15 @@
         }
         return buf.toString();
     }
+    static String getEventToString( int type ) {
+        if( (type >= 0) && (type < eventToString.length)) {
+            return eventToString[type];
+        }else if( type == XToolkit.getXKBBaseEventCode() ) {
+            //XXX TODO various xkb types
+            return "XkbEvent";
+        }
+        return eventToString[0];
+    }
 
     private static boolean getBuildInternal() {
         String javaVersion = XToolkit.getSystemProperty("java.version");
--- a/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java	Fri Mar 27 12:01:24 2009 +0300
@@ -1138,6 +1138,7 @@
             pw.println("/* This file is an automatically generated file, please do not edit this file, modify the XlibParser.java file instead !*/\n" );
             pw.println("#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xos.h>\n#include <X11/Xatom.h>\n#include <stdio.h>\n");
             pw.println("#include <X11/extensions/Xdbe.h>");
+            pw.println("#include <X11/XKBlib.h>");
             pw.println("#include \"awt_p.h\"");
             pw.println("#include \"color.h\"");
             pw.println("#include \"colordata.h\"");
--- a/jdk/src/solaris/classes/sun/awt/X11/generator/xlibtypes.txt	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/generator/xlibtypes.txt	Fri Mar 27 12:01:24 2009 +0300
@@ -119,7 +119,7 @@
     length	short
     feedback	pointer
     encoding_is_wchar	Bool
-    string      pointer 
+    string      pointer
 XKeymapEvent
     type	int
     serial	long
@@ -574,7 +574,7 @@
     f.get_pixel pointer
     f.put_pixel pointer
     f.sub_image pointer
-    f.add_pixel pointer    
+    f.add_pixel pointer
 XIMValuesList
     count_values	short
     supported_values	pointer
@@ -728,7 +728,7 @@
     awt_icmLUT pointer int
     awt_icmLUT2Colors pointer byte
     img_grays pointer byte
-    img_clr_tbl pointer byte 
+    img_clr_tbl pointer byte
     img_oda_red pointer byte
     img_oda_green pointer byte
     img_oda_blue pointer byte
@@ -798,3 +798,227 @@
    xerror struct XErrorEvent
    xkeymap struct XKeymapEvent
    pad array long 24
+
+XkbAnyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+
+XkbNewKeyboardNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    old_device  int
+    min_key_code  int
+    max_key_code  int
+    old_min_key_code  int
+    old_max_key_code  int
+    changed  int
+    req_major  byte
+    req_minor  byte
+
+XkbMapNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed  int
+    flags  int
+    first_type  int
+    num_types  int
+    min_key_code  int
+    max_key_code  int
+    first_key_sym  int
+    first_key_act  int
+    first_key_behavior  int
+    first_key_explicit  int
+    first_modmap_key  int
+    first_vmodmap_key  int
+    num_key_syms  int
+    num_key_acts  int
+    num_key_behaviors  int
+    num_key_explicit  int
+    num_modmap_keys  int
+    num_vmodmap_keys  int
+    vmods  int
+
+XkbStateNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed  int
+    group  int
+    base_group  int
+    latched_group  int
+    locked_group  int
+    mods  int
+    base_mods  int
+    latched_mods  int
+    locked_mods  int
+    compat_state  int
+    grab_mods  byte
+    compat_grab_mods  byte
+    lookup_mods  byte
+    compat_lookup_mods  byte
+    ptr_buttons  int
+    keycode  int
+    event_type  byte
+    req_major  byte
+    req_minor  byte
+
+XkbControlsNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed_ctrls  int
+    enabled_ctrls  int
+    enabled_ctrl_changes  int
+    num_groups  int
+    keycode  int
+    event_type  byte
+    req_major  byte
+    req_minor  byte
+
+XkbIndicatorNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed  int
+    state  int
+
+XkbNamesNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed  int
+    first_type  int
+    num_types  int
+    first_lvl  int
+    num_lvls  int
+    num_aliases  int
+    num_radio_groups  int
+    changed_vmods  int
+    changed_groups  int
+    changed_indicators  int
+    first_key  int
+    num_keys  int
+
+
+XkbCompatMapNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    changed_groups  int
+    first_si  int
+    num_si  int
+    num_total_si  int
+
+XkbBellNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    percent  int
+    pitch  int
+    duration  int
+    bell_class  int
+    bell_id  int
+    name  Atom
+    window  long
+    event_only  Bool
+
+XkbActionMessageEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    keycode  int
+    press  Bool
+    key_event_follows  Bool
+    group  int
+    mods  int
+    message array byte 7 //XkbActionMessageLength+1
+
+XkbAccessXNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    detail  int
+    keycode  int
+    sk_delay  int
+    debounce_delay  int
+
+XkbExtensionDeviceNotifyEvent
+    type  int
+    serial  ulong
+    send_event  Bool
+    display  long
+    time  ulong
+    xkb_type  int
+    device  int
+    reason  int
+    supported  int
+    unsupported  int
+    first_btn  int
+    num_btns  int
+    leds_defined  int
+    led_state  int
+    led_class  int
+    led_id  int
+
+XkbEvent
+    type  int
+    any  struct XkbAnyEvent
+    new_kbd  struct XkbNewKeyboardNotifyEvent
+    map  struct XkbMapNotifyEvent
+    state  struct XkbStateNotifyEvent
+    ctrls  struct XkbControlsNotifyEvent
+    indicators  struct XkbIndicatorNotifyEvent
+    names  struct XkbNamesNotifyEvent
+    compat  struct XkbCompatMapNotifyEvent
+    bell  struct XkbBellNotifyEvent
+    message  struct XkbActionMessageEvent
+    accessx  struct XkbAccessXNotifyEvent
+    device  struct XkbExtensionDeviceNotifyEvent
+    core  struct XEvent
--- a/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/classes/sun/awt/X11/keysym2ucs.h	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
  */
 
 tojava /*
-tojava  * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+tojava  * Copyright 2005-2009 Sun Microsystems, Inc.  All Rights Reserved.
 tojava  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 tojava  *
 tojava  * This code is free software; you can redistribute it and/or modify it
@@ -127,14 +127,47 @@
 tojava         Character ch = keysym2UCSHash.get(ks);
 tojava         return ch == null ? (char)0 : ch.charValue();
 tojava     }
+tojava     static long xkeycode2keysym_noxkb(XKeyEvent ev, int ndx) {
+tojava         XToolkit.awtLock();
+tojava         try {
+tojava             return XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx);
+tojava         } finally {
+tojava             XToolkit.awtUnlock();
+tojava         }
+tojava     }
+tojava     static long xkeycode2keysym_xkb(XKeyEvent ev, int ndx) {
+tojava         XToolkit.awtLock();
+tojava         try {
+tojava             int mods = ev.get_state();
+tojava             if ((ndx == 0) && ((mods & XConstants.ShiftMask) != 0)) {
+tojava                 // I don't know all possible meanings of 'ndx' in case of XKB
+tojava                 // and don't want to speculate. But this particular case
+tojava                 // clearly means that caller needs a so called primary keysym.
+tojava                 mods ^= XConstants.ShiftMask;
+tojava             }
+tojava             XlibWrapper.XkbTranslateKeyCode(XToolkit.getXKBKbdDesc(), ev.get_keycode(),
+tojava                        mods, XlibWrapper.iarg1, XlibWrapper.larg3);
+tojava             //XXX unconsumed modifiers?
+tojava             return Native.getLong(XlibWrapper.larg3);
+tojava         } finally {
+tojava             XToolkit.awtUnlock();
+tojava         }
+tojava     }
 tojava     static long xkeycode2keysym(XKeyEvent ev, int ndx) {
 tojava         XToolkit.awtLock();
 tojava         try {
-tojava             return XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx );
+tojava             if (XToolkit.canUseXKBCalls()) {
+tojava                 return xkeycode2keysym_xkb(ev, ndx);
+tojava             }else{
+tojava                 return xkeycode2keysym_noxkb(ev, ndx);
+tojava             }
 tojava         } finally {
 tojava             XToolkit.awtUnlock();
 tojava         }
 tojava     }
+tojava     static long xkeycode2primary_keysym(XKeyEvent ev) {
+tojava         return xkeycode2keysym(ev, 0);
+tojava     }
 tojava     public static boolean isKPEvent( XKeyEvent ev )
 tojava     {
 tojava         // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
@@ -236,6 +269,27 @@
 tojava         Keysym2JavaKeycode jkc = getJavaKeycode( ev );
 tojava         return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
 tojava     }
+tojava     /**
+tojava      * Return an integer java keycode apprx as it was before extending keycodes range.
+tojava      * This call would ignore for instance XKB and process whatever is on the bottom
+tojava      * of keysym stack. Result will not depend on actual locale, will differ between
+tojava      * dual/multiple keyboard setup systems (e.g. English+Russian vs French+Russian)
+tojava      * but will be someway compatible with old releases.
+tojava      */
+tojava     static int getLegacyJavaKeycodeOnly( XKeyEvent ev ) {
+tojava         long keysym = XConstants.NoSymbol;
+tojava         int ndx = 0;
+tojava         if( (ev.get_state() & XToolkit.numLockMask) != 0 &&
+tojava              isKPEvent(ev)) {
+tojava             keysym = getKeypadKeysym( ev );
+tojava         } else {
+tojava             // we only need primary-layer keysym to derive a java keycode.
+tojava             ndx = 0;
+tojava             keysym = xkeycode2keysym_noxkb(ev, ndx);
+tojava         }
+tojava         Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym );
+tojava         return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
+tojava     }
 tojava     static long javaKeycode2Keysym( int jkey ) {
 tojava         Long ks = javaKeycode2KeysymHash.get( jkey );
 tojava         return  (ks == null ? 0 : ks.longValue());
--- a/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/solaris/native/sun/xawt/XlibWrapper.c	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
 #include <Region.h>
 #include "utility/rect.h"
 
+#include <X11/XKBlib.h>
 #if defined(DEBUG) || defined(INTERNAL_BUILD)
 static jmethodID lockIsHeldMID = NULL;
 
@@ -449,6 +450,79 @@
     XSelectInput((Display *) jlong_to_ptr(display), (Window) window, mask);
 }
 
+JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbSelectEvents
+(JNIEnv *env, jclass clazz, jlong display, jlong device, jlong bits_to_change, jlong values_for_bits)
+{
+    AWT_CHECK_HAVE_LOCK();
+    XkbSelectEvents((Display *) jlong_to_ptr(display), (unsigned int)device,
+                   (unsigned long)bits_to_change,
+                   (unsigned long)values_for_bits);
+}
+JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbSelectEventDetails
+(JNIEnv *env, jclass clazz, jlong display, jlong device, jlong event_type, jlong bits_to_change, jlong values_for_bits)
+{
+    AWT_CHECK_HAVE_LOCK();
+    XkbSelectEventDetails((Display *) jlong_to_ptr(display), (unsigned int)device,
+                   (unsigned int) event_type,
+                   (unsigned long)bits_to_change,
+                   (unsigned long)values_for_bits);
+}
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbQueryExtension
+(JNIEnv *env, jclass clazz, jlong display, jlong opcode_rtrn, jlong event_rtrn,
+              jlong error_rtrn, jlong major_in_out, jlong minor_in_out)
+{
+    AWT_CHECK_HAVE_LOCK();
+    return XkbQueryExtension( (Display *) jlong_to_ptr(display),
+                       (int *) jlong_to_ptr(opcode_rtrn),
+                       (int *) jlong_to_ptr(event_rtrn),
+                       (int *) jlong_to_ptr(error_rtrn),
+                       (int *) jlong_to_ptr(major_in_out),
+                       (int *) jlong_to_ptr(minor_in_out));
+}
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbLibraryVersion
+(JNIEnv *env, jclass clazz, jlong lib_major_in_out, jlong lib_minor_in_out)
+{
+    AWT_CHECK_HAVE_LOCK();
+    *((int *)lib_major_in_out) =  XkbMajorVersion;
+    *((int *)lib_minor_in_out) =  XkbMinorVersion;
+    return  XkbLibraryVersion((int *)jlong_to_ptr(lib_major_in_out), (int *)jlong_to_ptr(lib_minor_in_out));
+}
+
+JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetMap
+(JNIEnv *env, jclass clazz, jlong display, jlong which, jlong device_spec)
+{
+    AWT_CHECK_HAVE_LOCK();
+    return (jlong) XkbGetMap( (Display *) jlong_to_ptr(display),
+                              (unsigned int) which,
+                              (unsigned int) device_spec);
+}
+JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap
+(JNIEnv *env, jclass clazz, jlong display, jlong which, jlong xkb)
+{
+    AWT_CHECK_HAVE_LOCK();
+    return (jlong) XkbGetUpdatedMap( (Display *) jlong_to_ptr(display),
+                              (unsigned int) which,
+                              (XkbDescPtr) jlong_to_ptr(xkb));
+}
+JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbFreeKeyboard
+(JNIEnv *env, jclass clazz, jlong xkb, jlong which, jboolean free_all)
+{
+    AWT_CHECK_HAVE_LOCK();
+    XkbFreeKeyboard(jlong_to_ptr(xkb), (unsigned int)which, free_all);
+}
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode
+(JNIEnv *env, jclass clazz, jlong xkb, jint keycode, jlong mods, jlong mods_rtrn, jlong keysym_rtrn)
+{
+    Bool b;
+    b = XkbTranslateKeyCode((XkbDescPtr)xkb, (unsigned int)keycode, (unsigned int)mods,
+                              (unsigned int *)jlong_to_ptr(mods_rtrn),
+                               (KeySym *)jlong_to_ptr(keysym_rtrn));
+    //printf("native,  input: keycode:0x%0X; mods:0x%0X\n", keycode, mods);
+    //printf("native, output:  keysym:0x%0X; mods:0x%0X\n", *(unsigned int *)jlong_to_ptr(keysym_rtrn), *(unsigned int *)jlong_to_ptr(mods_rtrn));
+    return b;
+}
+
+
 /*
  * Class:     sun_awt_X11_XlibWrapper
  * Method:    XNextEvent
@@ -1673,6 +1747,39 @@
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_awt_X11_XlibWrapper_XkbGetEffectiveGroup(JNIEnv *env, jclass clazz,
+                                              jlong display) {
+    XkbStateRec sr;
+    AWT_CHECK_HAVE_LOCK();
+    memset(&sr, 0, sizeof(XkbStateRec));
+    XkbGetState((Display*) jlong_to_ptr(display), XkbUseCoreKbd, &sr);
+//    printf("-------------------------------------VVVV\n");
+//    printf("                 group:0x%0X\n",sr.group);
+//    printf("            base_group:0x%0X\n",sr.base_group);
+//    printf("         latched_group:0x%0X\n",sr.latched_group);
+//    printf("          locked_group:0x%0X\n",sr.locked_group);
+//    printf("                  mods:0x%0X\n",sr.mods);
+//    printf("             base_mods:0x%0X\n",sr.base_mods);
+//    printf("          latched_mods:0x%0X\n",sr.latched_mods);
+//    printf("           locked_mods:0x%0X\n",sr.locked_mods);
+//    printf("          compat_state:0x%0X\n",sr.compat_state);
+//    printf("             grab_mods:0x%0X\n",sr.grab_mods);
+//    printf("      compat_grab_mods:0x%0X\n",sr.compat_grab_mods);
+//    printf("           lookup_mods:0x%0X\n",sr.lookup_mods);
+//    printf("    compat_lookup_mods:0x%0X\n",sr.compat_lookup_mods);
+//    printf("           ptr_buttons:0x%0X\n",sr.ptr_buttons);
+//    printf("-------------------------------------^^^^\n");
+    return (jint)(sr.group);
+}
+JNIEXPORT jlong JNICALL
+Java_sun_awt_X11_XlibWrapper_XkbKeycodeToKeysym(JNIEnv *env, jclass clazz,
+                                              jlong display, jint keycode,
+                                              jint group, jint level) {
+    AWT_CHECK_HAVE_LOCK();
+    return XkbKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (unsigned int)group, (unsigned int)level);
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode(JNIEnv *env, jclass clazz,
                                               jlong display, jlong keysym) {
     AWT_CHECK_HAVE_LOCK();
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Fri Mar 27 12:01:24 2009 +0300
@@ -199,6 +199,8 @@
 BOOL AwtComponent::sm_rtlReadingOrder =
     PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC;
 
+BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE;
+
 HWND AwtComponent::sm_cursorOn;
 BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE;
 
@@ -245,6 +247,11 @@
 
     m_MessagesProcessing = 0;
     m_wheelRotationAmount = 0;
+    if (!sm_PrimaryDynamicTableBuilt) {
+        // do it once.
+        AwtComponent::BuildPrimaryDynamicTable();
+        sm_PrimaryDynamicTableBuilt = TRUE;
+    }
 }
 
 AwtComponent::~AwtComponent()
@@ -2892,6 +2899,19 @@
     {0,0}
 };
 
+// The full map of the current keyboard state including
+// windows virtual key, scancode, java virtual key, and unicode
+// for this key sans modifiers.
+// All but first element may be 0.
+// XXX in the update releases this is an addition to the unchanged existing code
+struct DynPrimaryKeymapEntry {
+    UINT wkey;
+    UINT scancode;
+    UINT jkey;
+    WCHAR unicode;
+};
+
+static DynPrimaryKeymapEntry dynPrimaryKeymap[256];
 
 void
 AwtComponent::InitDynamicKeyMapTable()
@@ -2900,6 +2920,8 @@
 
     if (!kbdinited) {
         AwtComponent::BuildDynamicKeyMapTable();
+        // We cannot build it here since JNI is not available yet:
+        //AwtComponent::BuildPrimaryDynamicTable();
         kbdinited = TRUE;
     }
 }
@@ -3125,7 +3147,11 @@
 
     for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) {
         if (dynamicKeyMapTable[j].windowsKey == windowsKey) {
-            return dynamicKeyMapTable[j].javaKey;
+            if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) {
+                return dynamicKeyMapTable[j].javaKey;
+            }else{
+                break;
+            }
         }
     }
 
@@ -3202,6 +3228,122 @@
 
     return FALSE;
 }
+static void
+resetKbdState( BYTE kstate[256]) {
+    BYTE tmpState[256];
+    WCHAR wc[2];
+    memmove(tmpState, kstate, sizeof(kstate));
+    tmpState[VK_SHIFT] = 0;
+    tmpState[VK_CONTROL] = 0;
+    tmpState[VK_MENU] = 0;
+
+    ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0,  GetKeyboardLayout(0));
+}
+
+// XXX in the update releases this is an addition to the unchanged existing code
+// After the call, a table will have a unicode associated with a windows virtual keycode
+// sans modifiers. With some further simplification, one can
+// derive java keycode from it, and anyway we will pass this unicode value
+// all the way up in a comment to a KeyEvent.
+void
+AwtComponent::BuildPrimaryDynamicTable() {
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+    // XXX: how about that?
+    //CriticalSection::Lock l(GetLock());
+    //if (GetPeer(env) == NULL) {
+    //    /* event received during termination. */
+    //    return;
+    //}
+
+    HKL hkl = GetKeyboardLayout();
+    UINT sc = 0;
+    BYTE kbdState[AwtToolkit::KB_STATE_SIZE];
+    memset(kbdState, 0, sizeof (kbdState));
+
+    // Use JNI call to obtain java key code. We should keep a list
+    // of currently available keycodes in a single place.
+    static jclass extKeyCodesCls;
+    if( extKeyCodesCls == NULL) {
+        jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes");
+        DASSERT(extKeyCodesClsLocal);
+        if (extKeyCodesClsLocal == NULL) {
+            /* exception already thrown */
+            return;
+        }
+        extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal);
+        env->DeleteLocalRef(extKeyCodesClsLocal);
+    }
+    static jmethodID getExtendedKeyCodeForChar;
+    if (getExtendedKeyCodeForChar == NULL) {
+        getExtendedKeyCodeForChar =
+                  env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I");
+        DASSERT(getExtendedKeyCodeForChar);
+    }
+    jint extJKC; //extended Java key code
+
+    for (UINT i = 0; i < 256; i++) {
+        dynPrimaryKeymap[i].wkey = i;
+        dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED;
+        dynPrimaryKeymap[i].unicode = 0;
+
+        if ((sc = MapVirtualKey (i, 0)) == 0) {
+            dynPrimaryKeymap[i].scancode = 0;
+            continue;
+        }
+        dynPrimaryKeymap[i].scancode = sc;
+
+        // XXX process cases like VK_SHIFT etc.
+        kbdState[i] = 0x80; // "key pressed".
+        WCHAR wc[16];
+        int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl);
+        if (k == 1) {
+            // unicode
+            dynPrimaryKeymap[i].unicode = wc[0];
+            if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) {
+            // Convert unicode to java keycode.
+                //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000);
+                //
+                //XXX If this key in on the keypad, we should force a special value equal to
+                //XXX an old java keycode: but how to say if it is a keypad key?
+                //XXX We'll do it in WmKeyUp/Down.
+                extJKC = env->CallStaticIntMethod(extKeyCodesCls,
+                                                  getExtendedKeyCodeForChar, (jint)(wc[0]));
+                dynPrimaryKeymap[i].jkey = extJKC;
+            }
+        }else if (k == -1) {
+            // dead key: use charToDeadVKTable
+            dynPrimaryKeymap[i].unicode = wc[0];
+            resetKbdState( kbdState );
+            for (const CharToVKEntry *map = charToDeadVKTable;  map->c != 0;  ++map) {
+                if (wc[0] == map->c) {
+                    dynPrimaryKeymap[i].jkey = map->javaKey;
+                    break;
+                }
+            }
+        } else if (k == 0) {
+            // reset
+            resetKbdState( kbdState );
+        }else {
+            printf ("++++Whats that? wkey 0x%x (%d)\n", i,i);
+        }
+        kbdState[i] = 0; // "key unpressed"
+    }
+}
+void
+AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers)
+{
+    if( wkey && wkey < 256 ) {
+        if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) {
+            // At the creation time,
+            // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /"
+            dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
+        }
+        if(dynPrimaryKeymap[wkey].jkey ==  java_awt_event_KeyEvent_VK_UNDEFINED) {
+            // E.g. it is non-unicode key
+            dynPrimaryKeymap[wkey].jkey = jkeyLegacy;
+        }
+    }
+}
 
 UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops)
 {
@@ -3358,10 +3500,12 @@
     jint keyLocation = GetKeyLocation(wkey, flags);
     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers);
     UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE);
+    UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
+
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
                              TimeHelper::windowsToUTC(msg.time), jkey, character,
-                             modifiers, keyLocation, &msg);
+                             modifiers, keyLocation, (jlong)wkey, &msg);
 
     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
     // for some reason, so we need to create the KEY_TYPED event on the
@@ -3373,7 +3517,7 @@
                                  TimeHelper::windowsToUTC(msg.time),
                                  java_awt_event_KeyEvent_VK_UNDEFINED,
                                  character, modifiers,
-                                 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN);
+                                 java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
     }
 
     return mrConsume;
@@ -3398,10 +3542,11 @@
     jint keyLocation = GetKeyLocation(wkey, flags);
     UINT jkey = WindowsKeyToJavaKey(wkey, modifiers);
     UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD);
+    UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
                              TimeHelper::windowsToUTC(msg.time), jkey, character,
-                             modifiers, keyLocation, &msg);
+                             modifiers, keyLocation, (jlong)wkey, &msg);
     return mrConsume;
 }
 
@@ -3417,6 +3562,7 @@
     m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID
     m_CodePage = LangToCodePage(m_idLang);
     BuildDynamicKeyMapTable();  // compute new mappings for VK_OEM
+    BuildPrimaryDynamicTable();
     return mrConsume;           // do not propagate to children
 }
 
@@ -3447,7 +3593,7 @@
                              TimeHelper::windowsToUTC(msg.time),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
-                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
+                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
                              &msg);
     return mrConsume;
 }
@@ -3516,7 +3662,7 @@
                              TimeHelper::windowsToUTC(msg.time),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
-                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
+                             java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
                              &msg);
     return mrConsume;
 }
@@ -4525,7 +4671,7 @@
 }
 
 void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
-                                jint modifiers, jint keyLocation, MSG *pMsg)
+                                jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg)
 {
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
     CriticalSection::Lock l(GetLock());
@@ -4562,6 +4708,18 @@
     if (safe_ExceptionOccurred(env)) env->ExceptionDescribe();
     DASSERT(!safe_ExceptionOccurred(env));
     DASSERT(keyEvent != NULL);
+    env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode);
+    if( nativeCode && nativeCode < 256 ) {
+        env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode));
+        env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey));
+        if( nativeCode < 255 ) {
+            env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode));
+        }else if( pMsg != NULL ) {
+            // unknown key with virtual keycode 0xFF.
+            // Its scancode is not in the table, pickup it from the message.
+            env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF));
+        }
+    }
     if (pMsg != NULL) {
         AwtAWTEvent::saveMSG(env, pMsg, keyEvent);
     }
@@ -4575,6 +4733,7 @@
 AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
                                        jint raw, jint cooked,
                                        jint modifiers, jint keyLocation,
+                                       jlong nativeCode,
                                        MSG *msg)
 {
     /*
@@ -4584,7 +4743,7 @@
     HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow());
 
     if (hwndTarget == GetHWnd()) {
-        SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, msg);
+        SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg);
     } else {
         AwtComponent *target = NULL;
         if (hwndTarget != NULL) {
@@ -4595,7 +4754,7 @@
         }
         if (target != NULL) {
             target->SendKeyEvent(id, when, raw, cooked, modifiers,
-              keyLocation, msg);
+              keyLocation, nativeCode, msg);
         }
     }
 }
--- a/jdk/src/windows/native/sun/windows/awt_Component.h	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h	Fri Mar 27 12:01:24 2009 +0300
@@ -365,7 +365,7 @@
     }
 
     void SendKeyEventToFocusOwner(jint id, jlong when, jint raw, jint cooked,
-                                  jint modifiers, jint keyLocation,
+                                  jint modifiers, jint keyLocation, jlong nativeCode,
                                   MSG *msg = NULL);
     /*
      * Allocate and initialize a new java.awt.event.KeyEvent, and
@@ -373,7 +373,7 @@
      * from the target.
      */
     void SendKeyEvent(jint id, jlong when, jint raw, jint cooked,
-                      jint modifiers, jint keyLocation,
+                      jint modifiers, jint keyLocation, jlong nativeCode,
                       MSG *msg = NULL);
 
     /*
@@ -423,10 +423,6 @@
      */
     virtual BOOL InheritsNativeMouseWheelBehavior();
 
-    /* Functions for MouseWheel support on Windows95
-     * These should only be called if running on 95
-     */
-
     /* Determines whether the component is obscured by another window */
     // Called on Toolkit thread
     static jboolean _IsObscured(void *param);
@@ -446,6 +442,7 @@
     static UINT GetButtonMK(int mouseButton);
     static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers);
     static void JavaKeyToWindowsKey(UINT javaKey, UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey);
+    static void UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers);
 
     INLINE static void AwtComponent::JavaKeyToWindowsKey(UINT javaKey,
                                        UINT *windowsKey, UINT *modifiers)
@@ -787,6 +784,8 @@
     static BOOL sm_rtl;
     static BOOL sm_rtlReadingOrder;
 
+    static BOOL sm_PrimaryDynamicTableBuilt;
+
     jobject m_InputMethod;
     BOOL    m_useNativeCompWindow;
     LPARAM  m_bitsCandType;
@@ -850,6 +849,7 @@
     AwtComponent* SearchChild(UINT id);
     void RemoveChild(UINT id) ;
     static BOOL IsNavigationKey(UINT wkey);
+    static void BuildPrimaryDynamicTable();
 
     ChildListItem* m_childList;
 
--- a/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_InputMethod.cpp	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -176,7 +176,7 @@
                             java_awt_event_KeyEvent_CHAR_UNDEFINED,
                             unicodeChar,
                             modifiers,
-                            java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN,
+                            java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
                             &msg);
         } else {
             MSG* pCopiedMsg = new MSG;
--- a/jdk/src/windows/native/sun/windows/awt_KeyEvent.cpp	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_KeyEvent.cpp	Fri Mar 27 12:01:24 2009 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-1999 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,10 @@
 
 jfieldID AwtKeyEvent::keyCodeID;
 jfieldID AwtKeyEvent::keyCharID;
+jfieldID AwtKeyEvent::rawCodeID;
+jfieldID AwtKeyEvent::primaryLevelUnicodeID;
+jfieldID AwtKeyEvent::scancodeID;
+jfieldID AwtKeyEvent::extendedKeyCodeID;
 
 /************************************************************************
  * AwtKeyEvent native methods
@@ -45,9 +49,18 @@
 
     AwtKeyEvent::keyCodeID = env->GetFieldID(cls, "keyCode", "I");
     AwtKeyEvent::keyCharID = env->GetFieldID(cls, "keyChar", "C");
+    AwtKeyEvent::rawCodeID = env->GetFieldID(cls, "rawCode", "J");
+    AwtKeyEvent::primaryLevelUnicodeID = env->GetFieldID(cls, "primaryLevelUnicode", "J");
+    AwtKeyEvent::scancodeID = env->GetFieldID(cls, "scancode", "J");
+    AwtKeyEvent::extendedKeyCodeID = env->GetFieldID(cls, "extendedKeyCode", "J");
+
 
     DASSERT(AwtKeyEvent::keyCodeID != NULL);
     DASSERT(AwtKeyEvent::keyCharID != NULL);
+    DASSERT(AwtKeyEvent::rawCodeID != NULL);
+    DASSERT(AwtKeyEvent::primaryLevelUnicodeID != NULL);
+    DASSERT(AwtKeyEvent::scancodeID != NULL);
+    DASSERT(AwtKeyEvent::extendedKeyCodeID != NULL);
 
     CATCH_BAD_ALLOC;
 }
--- a/jdk/src/windows/native/sun/windows/awt_KeyEvent.h	Thu Mar 26 14:38:46 2009 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_KeyEvent.h	Fri Mar 27 12:01:24 2009 +0300
@@ -39,7 +39,10 @@
     /* java.awt.KeyEvent field ids */
     static jfieldID keyCodeID;
     static jfieldID keyCharID;
-
+    static jfieldID rawCodeID;
+    static jfieldID primaryLevelUnicodeID;
+    static jfieldID scancodeID;
+    static jfieldID extendedKeyCodeID;
 };
 
 #endif // AWT_KEYEVENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html	Fri Mar 27 12:01:24 2009 +0300
@@ -0,0 +1,20 @@
+<html>
+<!--
+  @test
+  @bug 6680988
+  @summary verify that various shortcuts and accelerators work
+  @author yuri.nesterenko : area=awt.keyboard
+  @run applet/manual=yesno AcceleratorTest.html
+  -->
+<head>
+<title> AcceleratorTest </title>
+</head>
+<body>
+
+<h1>AcceleratorTest<br>Bug ID: </h1>
+
+<p> See the dialog box (usually in upper left corner) for instructions</p>
+
+<APPLET CODE="AcceleratorTest.class" WIDTH=200 HEIGHT=200></APPLET>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.java	Fri Mar 27 12:01:24 2009 +0300
@@ -0,0 +1,305 @@
+/*
+  test
+  @bug 6680988
+  @summary verify that various shortcuts and accelerators work
+  @author yuri.nesterenko : area=awt.keyboard
+  @run applet/manual=yesno AcceleratorTest.html
+*/
+
+/**
+ * AcceleratorTest.java
+ *
+ * summary:
+ */
+
+//import java.applet.Applet;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Hashtable;
+
+
+public class AcceleratorTest extends JApplet
+{
+    //Declare things used in the test, like buttons and labels here
+    static int pressed = 0;
+    Hashtable<String, Integer> cmdHash = new Hashtable<String, Integer>();
+    String[] CMD = {
+        "\u042E, keep me in focus",
+        "Item Cyrl Be",
+        "Item English Period",
+        "Item English N",
+        "\u0436"
+    };
+
+    JFrame jfr;
+
+    public void init()
+    {
+        //Create instructions for the user here, as well as set up
+        // the environment -- set the layout manager, add buttons,
+        // etc.
+        this.setLayout (new BorderLayout ());
+
+        String[] instructions =
+        {
+            " Ensure you have Russian keyboard layout as a currently active.",
+            "(1) Press Ctrl+\u0411 (a key with \",<\" on it) ",
+            "(2) Find a . (period) in this layout (perhaps \"/?\" or \"7&\" key).",
+            "Press Ctrl+.",
+            "(3) Press Crtl+ regular English . (period) key (on \".>\" )",
+            "(4) Press Ctrl+ key with English N.",
+            "(5) Press Alt+\u042E (key with \".>\")",
+            "(6) Press Alt+\u0436 (key with \";:\")",
+            "If all expected commands will be fired, look for message",
+            "\"All tests passed\""
+        };
+        Sysout.createDialogWithInstructions( instructions );
+        for(int i = 0; i < CMD.length; i++) {
+            cmdHash.put(CMD[i], 0);
+        }
+
+        jfr = new JFrame();
+        JButton jbu;
+        jfr.add((jbu = new JButton(CMD[0])));
+        jbu.setMnemonic(java.awt.event.KeyEvent.getExtendedKeyCodeForChar('\u042E'));
+        jbu.addActionListener( new ALi(CMD[0]));
+
+
+        JMenuBar menuBar = new JMenuBar();
+        jfr.setJMenuBar(menuBar);
+        JMenu menu = new JMenu("Menu");
+        menuBar.add(menu);
+
+        JMenuItem menuItem = new JMenuItem(CMD[1]);
+        menuItem.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.getExtendedKeyCodeForChar('\u0431'),
+                        InputEvent.CTRL_DOWN_MASK));
+
+        JMenuItem menuItemEnglish = new JMenuItem(CMD[2]);
+        menuItemEnglish.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD,
+                        InputEvent.CTRL_DOWN_MASK));
+        JMenuItem menuItemE1 = new JMenuItem(CMD[3]);
+        menuItemE1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
+                        InputEvent.CTRL_DOWN_MASK));
+        menuItem.addActionListener( new ALi(CMD[1]));
+        menuItemEnglish.addActionListener( new ALi(CMD[2]));
+        menuItemE1.addActionListener( new ALi(CMD[3]));
+        menu.add(menuItem);
+        menu.add(menuItemEnglish);
+        menu.add(menuItemE1);
+
+        KeyStroke ks;
+        InputMap im = new InputMap();
+        ks = KeyStroke.getKeyStroke(KeyEvent.getExtendedKeyCodeForChar('\u0436'), java.awt.event.InputEvent.ALT_DOWN_MASK);
+        im.put(ks, "pushAction");
+        im.setParent(jbu.getInputMap(JComponent.WHEN_FOCUSED));
+        jbu.setInputMap(JComponent.WHEN_FOCUSED, im);
+
+        jbu.getActionMap().put("pushAction",
+            new AbstractAction("pushAction") {
+                  public void actionPerformed(ActionEvent evt) {
+                      if( evt.getActionCommand().equals(CMD[4])) {
+                          cmdHash.put(CMD[4], 1);
+                      }
+                      boolean notYet = false;
+                      for(int i = 0; i < CMD.length; i++) {
+                          if(cmdHash.get(CMD[i]) == 0 ) notYet = true;
+                      }
+                      Sysout.println("Fired");
+                      if( !notYet ) {
+                          Sysout.println("All tests passed.");
+                      }
+                  }
+            }
+        );
+
+
+        jfr.setBounds(650,0,200,200);
+        jfr.setVisible(true);
+
+    }//End  init()
+
+    public void start ()
+    {
+        //Get things going.  Request focus, set size, et cetera
+        setSize (200,200);
+        setVisible(true);
+        validate();
+
+    }// start()
+    public class ALi implements ActionListener {
+        String expectedCmd;
+        public ALi( String eCmd ) {
+            expectedCmd = eCmd;
+        }
+        public void actionPerformed(ActionEvent ae) {
+            if( cmdHash.containsKey(ae.getActionCommand()) ) {
+                cmdHash.put(expectedCmd, 1);
+            }
+            boolean notYet = false;
+            for(int i = 0; i < CMD.length; i++) {
+                if(cmdHash.get(CMD[i]) == 0 ) notYet = true;
+                //Sysout.println(CMD[i]+":"+cmdHash.get(CMD[i]));
+            }
+            Sysout.println("FIRED");
+            if( !notYet ) {
+                Sysout.println("All tests passed.");
+            }
+        }
+    }
+
+
+}// class AcceleratorTest
+
+/* Place other classes related to the test after this line */
+
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+{
+    private static TestDialog dialog;
+    private static boolean numbering = false;
+    private static int messageNumber = 0;
+
+    public static void createDialogWithInstructions( String[] instructions )
+    {
+        dialog = new TestDialog( new Frame(), "Instructions" );
+        dialog.printInstructions( instructions );
+        dialog.setVisible(true);
+        println( "Any messages for the tester will display here." );
+    }
+
+    public static void createDialog( )
+    {
+        dialog = new TestDialog( new Frame(), "Instructions" );
+        String[] defInstr = { "Instructions will appear here. ", "" } ;
+        dialog.printInstructions( defInstr );
+        dialog.setVisible(true);
+        println( "Any messages for the tester will display here." );
+    }
+
+    /* Enables message counting for the tester. */
+    public static void enableNumbering(boolean enable){
+        numbering = enable;
+    }
+
+    public static void printInstructions( String[] instructions )
+    {
+        dialog.printInstructions( instructions );
+    }
+
+
+    public static void println( String messageIn )
+    {
+        if (numbering) {
+            messageIn = "" + messageNumber + " " + messageIn;
+            messageNumber++;
+        }
+        dialog.displayMessage( messageIn );
+    }
+
+}// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog
+{
+
+    TextArea instructionsText;
+    TextArea messageText;
+    int maxStringLength = 80;
+
+    //DO NOT call this directly, go through Sysout
+    public TestDialog( Frame frame, String name )
+    {
+        super( frame, name );
+        int scrollBoth = TextArea.SCROLLBARS_BOTH;
+        instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+        add( "North", instructionsText );
+
+        messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+        add("Center", messageText);
+
+        pack();
+
+        setVisible(true);
+    }// TestDialog()
+
+    //DO NOT call this directly, go through Sysout
+    public void printInstructions( String[] instructions )
+    {
+        //Clear out any current instructions
+        instructionsText.setText( "" );
+
+        //Go down array of instruction strings
+
+        String printStr, remainingStr;
+        for( int i=0; i < instructions.length; i++ )
+        {
+            //chop up each into pieces maxSringLength long
+            remainingStr = instructions[ i ];
+            while( remainingStr.length() > 0 )
+            {
+                //if longer than max then chop off first max chars to print
+                if( remainingStr.length() >= maxStringLength )
+                {
+                    //Try to chop on a word boundary
+                    int posOfSpace = remainingStr.
+                        lastIndexOf( ' ', maxStringLength - 1 );
+
+                    if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+                    printStr = remainingStr.substring( 0, posOfSpace + 1 );
+                    remainingStr = remainingStr.substring( posOfSpace + 1 );
+                }
+                //else just print
+                else
+                {
+                    printStr = remainingStr;
+                    remainingStr = "";
+                }
+
+                instructionsText.append( printStr + "\n" );
+
+            }// while
+
+        }// for
+
+    }//printInstructions()
+
+    //DO NOT call this directly, go through Sysout
+    public void displayMessage( String messageIn )
+    {
+        messageText.append( messageIn + "\n" );
+        System.out.println(messageIn);
+    }
+
+}// TestDialog  class