< prev index next >

src/solaris/classes/sun/awt/X11/XKeysym.java

Print this page
rev 1565 : 5100701: Toolkit.getLockingKeyState() does not work on XToolkit, but works on Motif
Summary: Does not work on Motif but works on XToolkit now; implemented using XQueryPointer.
Reviewed-by: anthony
rev 1566 : 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
rev 1567 : 6871299: Shift+Tab no longer generates a KEY_TYPED event; used to with JRE 1.5
Summary: Add XK_ISO_Left_Tab -> VK_TAB rule
Reviewed-by: dcherepanov
rev 1568 : 6711676: Numpad keys trigger more than one KeyEvent.
Summary: Introduce a new sniffer based on server keymap.
Reviewed-by: art
rev 1569 : 5099725: AWT doesn't seem to handle MappingNotify events under X11.
5036807: Pressing action keys "STOP/AGAIN/COMPOSE" generates keycode of F11/F12 keys.
4787377: VK_STOP key on Solaris generates wrong Key Code
Summary: Added an event processing lumped with similar native code for similar bugs.
Reviewed-by: art
rev 1570 : 8000626: Implement dead key detection for KeyEvent on Linux
Reviewed-by: kizune

@@ -1,9 +1,9 @@
 // This is a generated file: do not edit! Edit keysym2ucs.h if necessary.
 
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2009, Oracle and/or its affiliates. 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
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -61,12 +61,16 @@
     static Hashtable<Long, Character> keysym2UCSHash = new Hashtable<Long, Character>();
     static Hashtable<Long, Long> uppercaseHash = new Hashtable<Long, Long>();
     // TODO: or not to do: add reverse lookup javakeycode2keysym,
     // for robot only it seems to me. After that, we can remove lookup table
     // from XWindow.c altogether.
+    // Another use for reverse lookup: query keyboard state, for some keys.
+    static Hashtable<Integer, Long> javaKeycode2KeysymHash = new Hashtable<Integer, Long>();
     static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize());
     static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize());
+    static Keysym2JavaKeycode kanaLock = new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK,
+                                                                java.awt.event.KeyEvent.KEY_LOCATION_STANDARD);
     public static char convertKeysym( long ks, int state ) {
 
         /* First check for Latin-1 characters (1:1 mapping) */
         if ((ks >= 0x0020 && ks <= 0x007e) ||
             (ks >= 0x00a0 && ks <= 0x00ff)) {

@@ -85,23 +89,56 @@
           return (char)(ks & 0x00ffffff);
 
         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.
         // Otherwise, it is [1].
-        int ndx = XToolkit.isXsunServer() &&
+        int ndx = XToolkit.isXsunKPBehavior() &&
                   ! XToolkit.isXKBenabled() ? 2 : 1;
         XToolkit.awtLock();
         try {
             return XlibWrapper.IsKeypadKey(
                 XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx ) );

@@ -140,11 +177,11 @@
         I do not check if this is a keypad event, I just presume it.
     */
     private static long getKeypadKeysym( XKeyEvent ev ) {
         int ndx = 0;
         long keysym = XConstants.NoSymbol;
-        if( XToolkit.isXsunServer() &&
+        if( XToolkit.isXsunKPBehavior() &&
             ! XToolkit.isXKBenabled() ) {
             if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on
                 ndx = 3;
                 keysym = xkeycode2keysym(ev, ndx);
             } else {

@@ -162,16 +199,39 @@
                 keysym = xkeycode2keysym(ev, ndx);
             }
         }
         return keysym;
     }
+
+    /**
+        Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X keysym.
+        Some keysyms maps to more than one keycode, these would require extra processing.
+    */
+    static Keysym2JavaKeycode getJavaKeycode( long keysym ) {
+        if(keysym == XKeySymConstants.XK_Mode_switch){
+           /* XK_Mode_switch on solaris maps either to VK_ALT_GRAPH (default) or VK_KANA_LOCK */
+           if( XToolkit.isKanaKeyboard() ) {
+               return kanaLock;
+           }
+        }else if(keysym == XKeySymConstants.XK_L1){
+           /* if it is Sun keyboard, trick hash to return VK_STOP else VK_F11 (default) */
+           if( XToolkit.isSunKeyboard() ) {
+               keysym = XKeySymConstants.SunXK_Stop;
+           }
+        }else if(keysym == XKeySymConstants.XK_L2) {
+           /* if it is Sun keyboard, trick hash to return VK_AGAIN else VK_F12 (default) */
+           if( XToolkit.isSunKeyboard() ) {
+               keysym = XKeySymConstants.SunXK_Again;
+           }
+        }
+
+        return  keysym2JavaKeycodeHash.get( keysym );
+    }
     /**
         Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X Window KeyEvent.
         Algorithm is, extract via XKeycodeToKeysym  a proper keysym according to Xlib spec rules and
         err exceptions, then search a java keycode in a table.
-        Some keysyms maps to more than one keycode, these would require extra processing. If someone
-        points me to such a keysym.
     */
     static Keysym2JavaKeycode getJavaKeycode( XKeyEvent ev ) {
         // get from keysym2JavaKeycodeHash.
         long keysym = XConstants.NoSymbol;
         int ndx = 0;

@@ -182,18 +242,43 @@
             // we only need primary-layer keysym to derive a java keycode.
             ndx = 0;
             keysym = xkeycode2keysym(ev, ndx);
         }
 
-        Keysym2JavaKeycode jkc = keysym2JavaKeycodeHash.get( keysym );
+        Keysym2JavaKeycode jkc = getJavaKeycode( keysym );
         return jkc;
     }
     static int getJavaKeycodeOnly( XKeyEvent ev ) {
         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 = getJavaKeycode( 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());
+    }
+    /**
         Return keysym derived from a keycode and modifiers.
         Usually an input method does this. However non-system input methods (e.g. Java IMs) do not.
         For rules, see "Xlib - C Language X Interface",
                         MIT X Consortium Standard
                         X Version 11, Release 6

@@ -276,10 +361,30 @@
         keysym2UCSHash.put( (long)0xFFB5, (char)0x0035); // XK_KP_5 --> DIGIT FIVE
         keysym2UCSHash.put( (long)0xFFB6, (char)0x0036); // XK_KP_6 --> DIGIT SIX
         keysym2UCSHash.put( (long)0xFFB7, (char)0x0037); // XK_KP_7 --> DIGIT SEVEN
         keysym2UCSHash.put( (long)0xFFB8, (char)0x0038); // XK_KP_8 --> DIGIT EIGHT
         keysym2UCSHash.put( (long)0xFFB9, (char)0x0039); // XK_KP_9 --> DIGIT NINE
+        keysym2UCSHash.put( (long)0xFE20, (char)0x0009); // XK_ISO_Left_Tab --> <control>
+        keysym2UCSHash.put( (long)0xFE50, (char)0x02CB); // XK_dead_grave --> MODIFIER LETTER GRAVE ACCENT
+        keysym2UCSHash.put( (long)0xFE51, (char)0x02CA); // XK_dead_acute --> MODIFIER LETTER ACUTE ACCENT
+        keysym2UCSHash.put( (long)0xFE52, (char)0x02C6); // XK_dead_circumflex --> MODIFIER LETTER CIRCUMFLEX ACCENT
+        keysym2UCSHash.put( (long)0xFE53, (char)0x02DC); // XK_dead_tilde --> SMALL TILDE
+        keysym2UCSHash.put( (long)0xFE54, (char)0x02C9); // XK_dead_macron --> MODIFIER LETTER MACRON
+        keysym2UCSHash.put( (long)0xFE55, (char)0x02D8); // XK_dead_breve --> BREVE
+        keysym2UCSHash.put( (long)0xFE56, (char)0x02D9); // XK_dead_abovedot --> DOT ABOVE
+        keysym2UCSHash.put( (long)0xFE57, (char)0x00A8); // XK_dead_diaeresis --> DIAERESIS
+        keysym2UCSHash.put( (long)0xFE58, (char)0x02DA); // XK_dead_abovering --> RING ABOVE
+        keysym2UCSHash.put( (long)0xFE59, (char)0x02DD); // XK_dead_doubleacute --> DOUBLE ACUTE ACCENT
+        keysym2UCSHash.put( (long)0xFE5A, (char)0x02C7); // XK_dead_caron --> CARON
+        keysym2UCSHash.put( (long)0xFE5B, (char)0x00B8); // XK_dead_cedilla --> CEDILLA
+        keysym2UCSHash.put( (long)0xFE5C, (char)0x02DB); // XK_dead_ogonek --> OGONEK
+        keysym2UCSHash.put( (long)0xFE5D, (char)0x0269); // XK_dead_iota --> LATIN SMALL LETTER IOTA
+        keysym2UCSHash.put( (long)0xFE5E, (char)0x3099); // XK_dead_voiced_sound --> COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+        keysym2UCSHash.put( (long)0xFE5F, (char)0x309A); // XK_dead_semivoiced_sound --> COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+        keysym2UCSHash.put( (long)0xFE60, (char)0x0323); // XK_dead_belowdot --> COMBINING DOT BELOW
+        keysym2UCSHash.put( (long)0xFE61, (char)0x0321); // XK_dead_hook --> COMBINING PALATALIZED HOOK BELOW
+        keysym2UCSHash.put( (long)0xFE62, (char)0x031B); // XK_dead_horn --> COMBINING HORN
         keysym2UCSHash.put( (long)0x1a1, (char)0x0104); // XK_Aogonek --> LATIN CAPITAL LETTER A WITH OGONEK
         keysym2UCSHash.put( (long)0x1a2, (char)0x02d8); // XK_breve --> BREVE
         keysym2UCSHash.put( (long)0x1a3, (char)0x0141); // XK_Lstroke --> LATIN CAPITAL LETTER L WITH STROKE
         keysym2UCSHash.put( (long)0x1a5, (char)0x013d); // XK_Lcaron --> LATIN CAPITAL LETTER L WITH CARON
         keysym2UCSHash.put( (long)0x1a6, (char)0x015a); // XK_Sacute --> LATIN CAPITAL LETTER S WITH ACUTE

@@ -1575,8 +1680,16 @@
         keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciicircum),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
         keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_diaeresis),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DIAERESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
         keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
 
         keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol),     new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN));
+
+        /* Reverse search of keysym by keycode. */
+
+        /* Add keyboard locking codes. */
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock);
+        javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock);
     };
 
 }
< prev index next >