/* * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program 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. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package java.awt; import java.awt.event.KeyEvent; import java.awt.event.InputEvent; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import java.io.Serializable; import java.lang.reflect.*; /** * An <code>AWTKeyStroke</code> represents a key action on the * keyboard, or equivalent input device. <code>AWTKeyStroke</code>s * can correspond to only a press or release of a * particular key, just as <code>KEY_PRESSED</code> and * <code>KEY_RELEASED</code> <code>KeyEvent</code>s do; * alternately, they can correspond to typing a specific Java character, just * as <code>KEY_TYPED</code> <code>KeyEvent</code>s do. * In all cases, <code>AWTKeyStroke</code>s can specify modifiers * (alt, shift, control, meta, or a combination thereof) which must be present * during the action for an exact match. * <p> * <code>AWTKeyStrokes</code> are immutable, and are intended * to be unique. Client code should never create an * <code>AWTKeyStroke</code> on its own, but should instead use * a variant of <code>getAWTKeyStroke</code>. Client use of these factory * methods allows the <code>AWTKeyStroke</code> implementation * to cache and share instances efficiently. * * @see #getAWTKeyStroke * * @version 1.14, 01/23/03 * @author Arnaud Weber * @author David Mendenhall * @since 1.4 */ public class AWTKeyStroke implements Serializable { private static Map cache; private static AWTKeyStroke cacheKey; private static Class subclass = AWTKeyStroke.class; private static Map modifierKeywords; /** * Maps from VK_XXX (as a String) to an Integer. This is done to * avoid the overhead of the reflective call to find the constant. */ private static Map vkMap; // Fix 6234000. static final long serialVersionUID = -6430539691155161871L; private char keyChar = KeyEvent.CHAR_UNDEFINED; private int keyCode = KeyEvent.VK_UNDEFINED; private int modifiers; private boolean onKeyRelease; /** * Constructs an <code>AWTKeyStroke</code> with default values. * The default values used are: * <table border="1" summary="AWTKeyStroke default values"> * <tr><th>Property</th><th>Default Value</th></tr> * <tr> * <td>Key Char</td> * <td><code>KeyEvent.CHAR_UNDEFINED</code></td> * </tr> * <tr> * <td>Key Code</td> * <td><code>KeyEvent.VK_UNDEFINED</code></td> * </tr> * <tr> * <td>Modifiers</td> * <td>none</td> * </tr> * <tr> * <td>On key release?</td> * <td><code>false</code></td> * </tr> * </table> * * <code>AWTKeyStroke</code>s should not be constructed * by client code. Use a variant of <code>getAWTKeyStroke</code> * instead. * * @see #getAWTKeyStroke */ // PBP/PP 6218482 // Make package private // protected AWTKeyStroke() { } AWTKeyStroke() {} /** * Constructs an <code>AWTKeyStroke</code> with the specified * values. <code>AWTKeyStroke</code>s should not be constructed * by client code. Use a variant of <code>getAWTKeyStroke</code> * instead. * * @param keyChar the character value for a keyboard key * @param keyCode the key code for this <code>AWTKeyStroke</code> * @param modifiers a bitwise-ored combination of any modifiers * @param onKeyRelease <code>true</code> if this * <code>AWTKeyStroke</code> corresponds * to a key release; <code>false</code> otherwise * @see #getAWTKeyStroke */ // PBP/PP 6218482 // Make package private // protected AWTKeyStroke(char keyChar, int keyCode, int modifiers, // boolean onKeyRelease) { AWTKeyStroke(char keyChar, int keyCode, int modifiers, boolean onKeyRelease) { this.keyChar = keyChar; this.keyCode = keyCode; this.modifiers = modifiers; this.onKeyRelease = onKeyRelease; } private void copy(AWTKeyStroke rhs) { this.keyChar = rhs.keyChar; this.keyCode = rhs.keyCode; this.modifiers = rhs.modifiers; this.onKeyRelease = rhs.onKeyRelease; } /** * Registers a new class which the factory methods in * <code>AWTKeyStroke</code> will use when generating new * instances of <code>AWTKeyStroke</code>s. After invoking this * method, the factory methods will return instances of the specified * Class. The specified Class must be either <code>AWTKeyStroke</code> * or derived from <code>AWTKeyStroke</code>, and it must have a * no-arg constructor. The constructor can be of any accessibility, * including <code>private</code>. This operation * flushes the current <code>AWTKeyStroke</code> cache. * * @param subclass the new Class of which the factory methods should create * instances * @throws IllegalArgumentException if subclass is <code>null</code>, * or if subclass does not have a no-arg constructor * @throws ClassCastException if subclass is not * <code>AWTKeyStroke</code>, or a class derived from * <code>AWTKeyStroke</code> */ // PBP/PP 6218482 // Remove registerSubClass(). /* protected static void registerSubclass(Class subclass) { if (subclass == null) { throw new IllegalArgumentException("subclass cannot be null"); } if (AWTKeyStroke.subclass.equals(subclass)) { // Already registered return; } if (!AWTKeyStroke.class.isAssignableFrom(subclass)) { throw new ClassCastException("subclass is not derived from AWTKeyStroke"); } String couldNotInstantiate = "subclass could not be instantiated"; try { AWTKeyStroke stroke = allocateNewInstance(subclass); if (stroke == null) { throw new IllegalArgumentException(couldNotInstantiate); } } catch (NoSuchMethodError e) { throw new IllegalArgumentException(couldNotInstantiate); } catch (ExceptionInInitializerError e) { throw new IllegalArgumentException(couldNotInstantiate); } catch (InstantiationException e) { throw new IllegalArgumentException(couldNotInstantiate); } synchronized (AWTKeyStroke.class) { AWTKeyStroke.subclass = subclass; cache = null; cacheKey = null; } } */ // Reflection allows us to bypass all security and access restrictions. // This allows us to define javax.swing.KeyStroke with only a private // no-arg constructor, yet still instantiate it from AWT without // special knowledge of Swing. private static AWTKeyStroke allocateNewInstance(Class clazz) throws InstantiationException { Class[] parameterTypes = new Class[0]; AWTKeyStroke newInstance = null; try { final Constructor constructor = clazz.getDeclaredConstructor(parameterTypes); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { constructor.setAccessible(true); return null; } }); Object[] args = new Object[0]; newInstance = (AWTKeyStroke) constructor.newInstance(args); } catch (InstantiationException ie) { throw ie; } catch (Exception e) { throw new InstantiationException("Couldn't instantiate class " + clazz.getName()); } return newInstance; } private static synchronized AWTKeyStroke getCachedStroke (char keyChar, int keyCode, int modifiers, boolean onKeyRelease) { if (cache == null) { cache = new HashMap(); } if (cacheKey == null) { try { cacheKey = allocateNewInstance(subclass); } catch (InstantiationException e) {} } cacheKey.keyChar = keyChar; cacheKey.keyCode = keyCode; cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers)); cacheKey.onKeyRelease = onKeyRelease; AWTKeyStroke stroke = (AWTKeyStroke) cache.get(cacheKey); if (stroke == null) { stroke = cacheKey; cache.put(stroke, stroke); cacheKey = null; } return stroke; } /** * Returns a shared instance of an <code>AWTKeyStroke</code> * that represents a <code>KEY_TYPED</code> event for the * specified character. * * @param keyChar the character value for a keyboard key * @return an <code>AWTKeyStroke</code> object for that key */ public static AWTKeyStroke getAWTKeyStroke(char keyChar) { return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false); } /** * Returns a shared instance of an <code>AWTKeyStroke</code>, * given a Character object and a set of modifiers. Note * that the first parameter is of type Character rather than * char. This is to avoid inadvertent clashes with * calls to <code>getAWTKeyStroke(int keyCode, int modifiers)</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 * <li>java.awt.event.InputEvent.META_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON1_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON2_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON3_DOWN_MASK * </ul> * The old modifiers <ul> * <li>java.awt.event.InputEvent.SHIFT_MASK * <li>java.awt.event.InputEvent.CTRL_MASK * <li>java.awt.event.InputEvent.META_MASK * <li>java.awt.event.InputEvent.ALT_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK * </ul> * also can be used, but they are mapped to _DOWN_ modifiers. * * Since these numbers are all different powers of two, any combination of * them is an integer in which each bit represents a different modifier * key. Use 0 to specify no modifiers. * * @param keyChar the Character object for a keyboard character * @param modifiers a bitwise-ored combination of any modifiers * @return an <code>AWTKeyStroke</code> object for that key * @throws IllegalArgumentException if <code>keyChar</code> is * <code>null</code> * * @see java.awt.event.InputEvent */ public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers) { if (keyChar == null) { throw new IllegalArgumentException("keyChar cannot be null"); } return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED, modifiers, false); } /** * Returns a shared instance of an <code>AWTKeyStroke</code>, * given a numeric key code and a set of modifiers, specifying * whether the key is activated when it is pressed or released. * <p> * The "virtual key" constants defined in * <code>java.awt.event.KeyEvent</code> can be * used to specify the key code. For example:<ul> * <li><code>java.awt.event.KeyEvent.VK_ENTER</code> * <li><code>java.awt.event.KeyEvent.VK_TAB</code> * <li><code>java.awt.event.KeyEvent.VK_SPACE</code> * </ul> * The modifiers consist of any combination of:<ul> * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK * <li>java.awt.event.InputEvent.META_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON1_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON2_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON3_DOWN_MASK * </ul> * The old modifiers <ul> * <li>java.awt.event.InputEvent.SHIFT_MASK * <li>java.awt.event.InputEvent.CTRL_MASK * <li>java.awt.event.InputEvent.META_MASK * <li>java.awt.event.InputEvent.ALT_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK * </ul> * also can be used, but they are mapped to _DOWN_ modifiers. * * Since these numbers are all different powers of two, any combination of * them is an integer in which each bit represents a different modifier * key. Use 0 to specify no modifiers. * * @param keyCode an int specifying the numeric code for a keyboard key * @param modifiers a bitwise-ored combination of any modifiers * @param onKeyRelease <code>true</code> if the <code>AWTKeyStroke</code> * should represent a key release; <code>false</code> otherwise * @return an AWTKeyStroke object for that key * * @see java.awt.event.KeyEvent * @see java.awt.event.InputEvent */ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers, boolean onKeyRelease) { return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, onKeyRelease); } /** * Returns a shared instance of an <code>AWTKeyStroke</code>, * given a numeric key code and a set of modifiers. The returned * <code>AWTKeyStroke</code> will correspond to a key press. * <p> * The "virtual key" constants defined in * <code>java.awt.event.KeyEvent</code> can be * used to specify the key code. For example:<ul> * <li><code>java.awt.event.KeyEvent.VK_ENTER</code> * <li><code>java.awt.event.KeyEvent.VK_TAB</code> * <li><code>java.awt.event.KeyEvent.VK_SPACE</code> * </ul> * The modifiers consist of any combination of:<ul> * <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK * <li>java.awt.event.InputEvent.CTRL_DOWN_MASK * <li>java.awt.event.InputEvent.META_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_DOWN_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON1_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON2_DOWN_MASK * <li>java.awt.event.InputEvent.BUTTON3_DOWN_MASK * </ul> * The old modifiers <ul> * <li>java.awt.event.InputEvent.SHIFT_MASK * <li>java.awt.event.InputEvent.CTRL_MASK * <li>java.awt.event.InputEvent.META_MASK * <li>java.awt.event.InputEvent.ALT_MASK * <li>java.awt.event.InputEvent.ALT_GRAPH_MASK * </ul> * also can be used, but they are mapped to _DOWN_ modifiers. * * Since these numbers are all different powers of two, any combination of * them is an integer in which each bit represents a different modifier * key. Use 0 to specify no modifiers. * * @param keyCode an int specifying the numeric code for a keyboard key * @param modifiers a bitwise-ored combination of any modifiers * @return an <code>AWTKeyStroke</code> object for that key * * @see java.awt.event.KeyEvent * @see java.awt.event.InputEvent */ public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) { return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers, false); } /** * Returns an <code>AWTKeyStroke</code> which represents the * stroke which generated a given <code>KeyEvent</code>. * <p> * This method obtains the key char from a <code>KeyTyped</code> * event, and the key code from a <code>KeyPressed</code> or * <code>KeyReleased</code> event. The <code>KeyEvent</code> modifiers are * obtained for all three types of <code>KeyEvent</code>. * * @param anEvent the <code>KeyEvent</code> from which to * obtain the <code>AWTKeyStroke</code> * @return the <code>AWTKeyStroke</code> that precipitated the event */ public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) { int id = anEvent.getID(); switch (id) { case KeyEvent.KEY_PRESSED: case KeyEvent.KEY_RELEASED: return getCachedStroke(KeyEvent.CHAR_UNDEFINED, anEvent.getKeyCode(), anEvent.getModifiers(), (id == KeyEvent.KEY_RELEASED)); case KeyEvent.KEY_TYPED: return getCachedStroke(anEvent.getKeyChar(), KeyEvent.VK_UNDEFINED, anEvent.getModifiers(), false); default: // Invalid ID for this KeyEvent return null; } } /** * Parses a string and returns an <code>AWTKeyStroke</code>. * The string must have the following syntax: * <pre> * <modifiers>* (<typedID> | <pressedReleasedID>) * * modifiers := shift | control | ctrl | meta | alt | button1 | button2 | button3 * typedID := typed <typedKey> * typedKey := string of length 1 giving Unicode character. * pressedReleasedID := (pressed | released) key * key := KeyEvent key code name, i.e. the name following "VK_". * </pre> * If typed, pressed or released is not specified, pressed is assumed. Here * are some examples: * <pre> * "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0); * "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK); * "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK); * "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true); * "typed a" => getAWTKeyStroke('a'); * </pre> * * @param s a String formatted as described above * @return an <code>AWTKeyStroke</code> object for that String * @throws IllegalArgumentException if <code>s</code> is <code>null</code>, * or is formatted incorrectly */ public static AWTKeyStroke getAWTKeyStroke(String s) { if (s == null) { throw new IllegalArgumentException("String cannot be null"); } final String errmsg = "String formatted incorrectly"; StringTokenizer st = new StringTokenizer(s, " "); int mask = 0; boolean released = false; boolean typed = false; boolean pressed = false; if (modifierKeywords == null) { synchronized (AWTKeyStroke.class) { if (modifierKeywords == null) { Map uninitializedMap = new HashMap(8, 1.0f); uninitializedMap.put("shift", new Integer(InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)); uninitializedMap.put("control", new Integer(InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)); uninitializedMap.put("ctrl", new Integer(InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)); uninitializedMap.put("meta", new Integer(InputEvent.META_DOWN_MASK | InputEvent.META_MASK)); uninitializedMap.put("alt", new Integer(InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)); uninitializedMap.put("altGraph", new Integer(InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.ALT_GRAPH_MASK)); uninitializedMap.put("button1", new Integer(InputEvent.BUTTON1_DOWN_MASK)); uninitializedMap.put("button2", new Integer(InputEvent.BUTTON2_DOWN_MASK)); uninitializedMap.put("button3", new Integer(InputEvent.BUTTON3_DOWN_MASK)); modifierKeywords = Collections.synchronizedMap(uninitializedMap); } } } int count = st.countTokens(); for (int i = 1; i <= count; i++) { String token = st.nextToken(); if (typed) { if (token.length() != 1 || i != count) { throw new IllegalArgumentException(errmsg); } return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED, mask, false); } if (pressed || released || i == count) { if (i != count) { throw new IllegalArgumentException(errmsg); } String keyCodeName = "VK_" + token; int keyCode = getVKValue(keyCodeName); return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, mask, released); } if (token.equals("released")) { released = true; continue; } if (token.equals("pressed")) { pressed = true; continue; } if (token.equals("typed")) { typed = true; continue; } Integer tokenMask = (Integer) modifierKeywords.get(token); if (tokenMask != null) { mask |= tokenMask.intValue(); } else { throw new IllegalArgumentException(errmsg); } } throw new IllegalArgumentException(errmsg); } /** * Returns the integer constant for the KeyEvent.VK field named * <code>key</code>. This will throw an * <code>IllegalArgumentException</code> if <code>key</code> is * not a valid constant. */ private static int getVKValue(String key) { if (vkMap == null) { vkMap = Collections.synchronizedMap(new HashMap()); } Integer value = (Integer) vkMap.get(key); if (value == null) { int keyCode = 0; final String errmsg = "String formatted incorrectly"; try { keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class); } catch (NoSuchFieldException nsfe) { throw new IllegalArgumentException(errmsg); } catch (IllegalAccessException iae) { throw new IllegalArgumentException(errmsg); } value = new Integer(keyCode); vkMap.put(key, value); } return value.intValue(); } /** * Returns the character for this <code>AWTKeyStroke</code>. * * @return a char value * @see #getAWTKeyStroke(char) */ public final char getKeyChar() { return keyChar; } /** * Returns the numeric key code for this <code>AWTKeyStroke</code>. * * @return an int containing the key code value * @see #getAWTKeyStroke(int,int) */ public final int getKeyCode() { return keyCode; } /** * Returns the modifier keys for this <code>AWTKeyStroke</code>. * * @return an int containing the modifiers * @see #getAWTKeyStroke(int,int) */ public final int getModifiers() { return modifiers; } /** * Returns whether this <code>AWTKeyStroke</code> represents a key release. * * @return <code>true</code> if this <code>AWTKeyStroke</code> * represents a key release; <code>false</code> otherwise * @see #getAWTKeyStroke(int,int,boolean) */ public final boolean isOnKeyRelease() { return onKeyRelease; } /** * Returns the type of <code>KeyEvent</code> which corresponds to * this <code>AWTKeyStroke</code>. * * @return <code>KeyEvent.KEY_PRESSED</code>, * <code>KeyEvent.KEY_TYPED</code>, * or <code>KeyEvent.KEY_RELEASED</code> * @see java.awt.event.KeyEvent */ public final int getKeyEventType() { if (keyCode == KeyEvent.VK_UNDEFINED) { return KeyEvent.KEY_TYPED; } else { return (onKeyRelease) ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED; } } /** * Returns a numeric value for this object that is likely to be unique, * making it a good choice as the index value in a hash table. * * @return an int that represents this object */ public int hashCode() { return (((int) keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) + (onKeyRelease ? 1 : 2); } /** * Returns true if this object is identical to the specified object. * * @param anObject the Object to compare this object to * @return true if the objects are identical */ public final boolean equals(Object anObject) { if (anObject instanceof AWTKeyStroke) { AWTKeyStroke ks = (AWTKeyStroke) anObject; return (ks.keyChar == keyChar && ks.keyCode == keyCode && ks.onKeyRelease == onKeyRelease && ks.modifiers == modifiers); } return false; } /** * Returns a string that displays and identifies this object's properties. * * @return a String representation of this object */ public String toString() { if (keyCode == KeyEvent.VK_UNDEFINED) { return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar; } else { return "keyCode " + KeyEvent.getKeyModifiersText(modifiers) + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P"); } } /** * Returns a cached instance of <code>AWTKeyStroke</code> * which is equal to this instance. * * @return a cached instance which is equal to this instance */ // PBP/PP 6218482 // Make readResolve() private, like java.net.InetAddress. // protected Object readResolve() throws java.io.ObjectStreamException { private Object readResolve() throws java.io.ObjectStreamException { synchronized (AWTKeyStroke.class) { /* Class newClass = getClass(); if (!newClass.equals(subclass)) { registerSubclass(newClass); } */ return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease); } } private static int mapOldModifiers(int modifiers) { if ((modifiers & InputEvent.SHIFT_MASK) != 0) { modifiers |= InputEvent.SHIFT_DOWN_MASK; } if ((modifiers & InputEvent.ALT_MASK) != 0) { modifiers |= InputEvent.ALT_DOWN_MASK; } if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) { modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; } if ((modifiers & InputEvent.CTRL_MASK) != 0) { modifiers |= InputEvent.CTRL_DOWN_MASK; } if ((modifiers & InputEvent.META_MASK) != 0) { modifiers |= InputEvent.META_DOWN_MASK; } if ((modifiers & InputEvent.BUTTON1_MASK) != 0) { modifiers |= InputEvent.BUTTON1_DOWN_MASK; } modifiers &= InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.META_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON2_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK; return modifiers; } private static int mapNewModifiers(int modifiers) { if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) { modifiers |= InputEvent.SHIFT_MASK; } if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) { modifiers |= InputEvent.ALT_MASK; } if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) { modifiers |= InputEvent.ALT_GRAPH_MASK; } if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) { modifiers |= InputEvent.CTRL_MASK; } if ((modifiers & InputEvent.META_DOWN_MASK) != 0) { modifiers |= InputEvent.META_MASK; } return modifiers; } }