source: trunk/gcc/libjava/java/awt/AWTKeyStroke.java

Last change on this file was 1389, checked in by bird, 21 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 22.4 KB
Line 
1/* AWTKeyStroke.java -- an immutable key stroke
2 Copyright (C) 2002 Free Software Foundation
3
4This file is part of GNU Classpath.
5
6GNU Classpath is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Classpath is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Classpath; see the file COPYING. If not, write to the
18Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1902111-1307 USA.
20
21Linking this library statically or dynamically with other modules is
22making a combined work based on this library. Thus, the terms and
23conditions of the GNU General Public License cover the whole
24combination.
25
26As a special exception, the copyright holders of this library give you
27permission to link this library with independent modules to produce an
28executable, regardless of the license terms of these independent
29modules, and to copy and distribute the resulting executable under
30terms of your choice, provided that you also meet, for each linked
31independent module, the terms and conditions of the license of that
32module. An independent module is a module which is not derived from
33or based on this library. If you modify this library, you may extend
34this exception to your version of the library, but you are not
35obligated to do so. If you do not wish to do so, delete this
36exception statement from your version. */
37
38
39package java.awt;
40
41import java.awt.event.KeyEvent;
42import java.io.ObjectStreamException;
43import java.io.Serializable;
44import java.lang.reflect.Constructor;
45import java.lang.reflect.Field;
46import java.lang.reflect.InvocationTargetException;
47import java.security.AccessController;
48import java.security.PrivilegedAction;
49import java.security.PrivilegedActionException;
50import java.security.PrivilegedExceptionAction;
51import java.util.Map;
52import java.util.HashMap;
53import java.util.LinkedHashMap;
54import java.util.StringTokenizer;
55
56/**
57 * This class mirrors KeyEvents, representing both low-level key presses and
58 * key releases, and high level key typed inputs. However, this class forms
59 * immutable strokes, and can be efficiently reused via the factory methods
60 * for creating them.
61 *
62 * <p>For backwards compatibility with Swing, this supports a way to build
63 * instances of a subclass, using reflection, provided the subclass has a
64 * no-arg constructor (of any accessibility).
65 *
66 * @author Eric Blake <ebb9@email.byu.edu>
67 * @see #getAWTKeyStroke(char)
68 * @since 1.4
69 * @status updated to 1.4
70 */
71public class AWTKeyStroke implements Serializable
72{
73 /**
74 * Compatible with JDK 1.4+.
75 */
76 private static final long serialVersionUID = -6430539691155161871L;
77
78 /** The mask for modifiers. */
79 private static final int MODIFIERS_MASK = 0x3fef;
80
81 /**
82 * The cache of recently created keystrokes. This maps KeyStrokes to
83 * KeyStrokes in a cache which removes the least recently accessed entry,
84 * under the assumption that garbage collection of a new keystroke is
85 * easy when we find the old one that it matches in the cache.
86 */
87 private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
88 {
89 /** The largest the keystroke cache can grow. */
90 private static final int MAX_CACHE_SIZE = 2048;
91
92 /** Prune stale entries. */
93 protected boolean removeEldestEntry(Map.Entry eldest)
94 { // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround.
95 return size() > MAX_CACHE_SIZE;
96 }
97 };
98
99 /** The most recently generated keystroke, or null. */
100 private static AWTKeyStroke recent;
101
102 /**
103 * The no-arg constructor of a subclass, or null to use AWTKeyStroke. Note
104 * that this will be left accessible, to get around private access; but
105 * it should not be a security risk as it is highly unlikely that creating
106 * protected instances of the subclass via reflection will do much damage.
107 */
108 private static Constructor ctor;
109
110 /**
111 * A table of keyCode names to values.
112 *
113 * @see #getAWTKeyStroke(String)
114 */
115 private static final HashMap vktable = new HashMap();
116 static
117 {
118 // Using reflection saves the hassle of keeping this in sync with KeyEvent,
119 // at the price of an expensive initialization.
120 AccessController.doPrivileged(new PrivilegedAction()
121 {
122 public Object run()
123 {
124 Field[] fields = KeyEvent.class.getFields();
125 int i = fields.length;
126 try
127 {
128 while (--i >= 0)
129 {
130 Field f = fields[i];
131 String name = f.getName();
132 if (name.startsWith("VK_"))
133 vktable.put(name.substring(3), f.get(null));
134 }
135 }
136 catch (Exception e)
137 {
138 throw (Error) new InternalError().initCause(e);
139 }
140 return null;
141 }
142 });
143 }
144
145 /**
146 * The typed character, or CHAR_UNDEFINED for key presses and releases.
147 *
148 * @serial the keyChar
149 */
150 private char keyChar;
151
152 /**
153 * The virtual key code, or VK_UNDEFINED for key typed. Package visible for
154 * use by Component.
155 *
156 * @serial the keyCode
157 */
158 int keyCode;
159
160 /**
161 * The modifiers in effect. To match Sun, this stores the old style masks
162 * for shift, control, alt, meta, and alt-graph (but not button1); as well
163 * as the new style of extended modifiers for all modifiers.
164 *
165 * @serial bitwise or of the *_DOWN_MASK modifiers
166 */
167 private int modifiers;
168
169 /**
170 * True if this is a key release; should only be true if keyChar is
171 * CHAR_UNDEFINED.
172 *
173 * @serial true to distinguish key pressed from key released
174 */
175 private boolean onKeyRelease;
176
177 /**
178 * Construct a keystroke with default values: it will be interpreted as a
179 * key typed event with an invalid character and no modifiers. Client code
180 * should use the factory methods instead.
181 *
182 * @see #getAWTKeyStroke(char)
183 * @see #getAWTKeyStroke(Character, int)
184 * @see #getAWTKeyStroke(int, int, boolean)
185 * @see #getAWTKeyStroke(int, int)
186 * @see #getAWTKeyStrokeForEvent(KeyEvent)
187 * @see #getAWTKeyStroke(String)
188 */
189 protected AWTKeyStroke()
190 {
191 keyChar = KeyEvent.CHAR_UNDEFINED;
192 }
193
194 /**
195 * Construct a keystroke with the given values. Client code should use the
196 * factory methods instead.
197 *
198 * @param keyChar the character entered, if this is a key typed
199 * @param keyCode the key pressed or released, or VK_UNDEFINED for key typed
200 * @param modifiers the modifier keys for the keystroke, in old or new style
201 * @param onKeyRelease true if this is a key release instead of a press
202 * @see #getAWTKeyStroke(char)
203 * @see #getAWTKeyStroke(Character, int)
204 * @see #getAWTKeyStroke(int, int, boolean)
205 * @see #getAWTKeyStroke(int, int)
206 * @see #getAWTKeyStrokeForEvent(KeyEvent)
207 * @see #getAWTKeyStroke(String)
208 */
209 protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
210 boolean onKeyRelease)
211 {
212 this.keyChar = keyChar;
213 this.keyCode = keyCode;
214 // No need to call extend(), as only trusted code calls this constructor.
215 this.modifiers = modifiers;
216 this.onKeyRelease = onKeyRelease;
217 }
218
219 /**
220 * Registers a new subclass as being the type of keystrokes to generate in
221 * the factory methods. This operation flushes the cache of stored keystrokes
222 * if the class differs from the current one. The new class must be
223 * AWTKeyStroke or a subclass, and must have a no-arg constructor (which may
224 * be private).
225 *
226 * @param subclass the new runtime type of generated keystrokes
227 * @throws IllegalArgumentException subclass doesn't have no-arg constructor
228 * @throws ClassCastException subclass doesn't extend AWTKeyStroke
229 */
230 protected static void registerSubclass(final Class subclass)
231 {
232 if (subclass == null)
233 throw new IllegalArgumentException();
234 if (subclass.equals(ctor == null ? AWTKeyStroke.class
235 : ctor.getDeclaringClass()))
236 return;
237 if (subclass.equals(AWTKeyStroke.class))
238 {
239 cache.clear();
240 recent = null;
241 ctor = null;
242 return;
243 }
244 try
245 {
246 ctor = (Constructor) AccessController.doPrivileged
247 (new PrivilegedExceptionAction()
248 {
249 public Object run()
250 throws NoSuchMethodException, InstantiationException,
251 IllegalAccessException, InvocationTargetException
252 {
253 Constructor c = subclass.getDeclaredConstructor(null);
254 c.setAccessible(true);
255 // Create a new instance, to make sure that we can, and
256 // to cause any ClassCastException.
257 AWTKeyStroke dummy = (AWTKeyStroke) c.newInstance(null);
258 return c;
259 }
260 });
261 }
262 catch (PrivilegedActionException e)
263 {
264 // e.getCause() will not ever be ClassCastException; that should
265 // escape on its own.
266 throw (RuntimeException)
267 new IllegalArgumentException().initCause(e.getCause());
268 }
269 cache.clear();
270 recent = null;
271 }
272
273 /**
274 * Returns a keystroke representing a typed character.
275 *
276 * @param keyChar the typed character
277 * @return the specified keystroke
278 */
279 public static AWTKeyStroke getAWTKeyStroke(char keyChar)
280 {
281 return getAWTKeyStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
282 }
283
284 /**
285 * Returns a keystroke representing a typed character with the given
286 * modifiers. Note that keyChar is a <code>Character</code> instead of a
287 * <code>char</code> to avoid accidental ambiguity with
288 * <code>getAWTKeyStroke(int, int)</code>. The modifiers are the bitwise
289 * or of the masks found in {@link InputEvent}; the new style (*_DOWN_MASK)
290 * is preferred, but the old style will work.
291 *
292 * @param keyChar the typed character
293 * @param modifiers the modifiers, or 0
294 * @return the specified keystroke
295 * @throws IllegalArgumentException if keyChar is null
296 */
297 public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
298 {
299 if (keyChar == null)
300 throw new IllegalArgumentException();
301 return getAWTKeyStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
302 extend(modifiers), false);
303 }
304
305 /**
306 * Returns a keystroke representing a pressed or released key event, with
307 * the given modifiers. The "virtual key" should be one of the VK_*
308 * constants in {@link KeyEvent}. The modifiers are the bitwise or of the
309 * masks found in {@link InputEvent}; the new style (*_DOWN_MASK) is
310 * preferred, but the old style will work.
311 *
312 * @param keyCode the virtual key
313 * @param modifiers the modifiers, or 0
314 * @param release true if this is a key release instead of a key press
315 * @return the specified keystroke
316 */
317 public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
318 boolean release)
319 {
320 return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
321 extend(modifiers), release);
322 }
323
324 /**
325 * Returns a keystroke representing a pressed key event, with the given
326 * modifiers. The "virtual key" should be one of the VK_* constants in
327 * {@link KeyEvent}. The modifiers are the bitwise or of the masks found
328 * in {@link InputEvent}; the new style (*_DOWN_MASK) is preferred, but the
329 * old style will work.
330 *
331 * @param keyCode the virtual key
332 * @param modifiers the modifiers, or 0
333 * @return the specified keystroke
334 */
335 public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers)
336 {
337 return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
338 extend(modifiers), false);
339 }
340
341 /**
342 * Returns a keystroke representing what caused the key event.
343 *
344 * @param event the key event to convert
345 * @return the specified keystroke, or null if the event is invalid
346 * @throws NullPointerException if event is null
347 */
348 public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent event)
349 {
350 switch (event.id)
351 {
352 case KeyEvent.KEY_TYPED:
353 return getAWTKeyStroke(event.getKeyChar(), KeyEvent.VK_UNDEFINED,
354 extend(event.getModifiersEx()), false);
355 case KeyEvent.KEY_PRESSED:
356 return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
357 extend(event.getModifiersEx()), false);
358 case KeyEvent.KEY_RELEASED:
359 return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, event.getKeyCode(),
360 extend(event.getModifiersEx()), true);
361 default:
362 return null;
363 }
364 }
365
366 /**
367 * Parses a string and returns the keystroke that it represents. The syntax
368 * for keystrokes is listed below, with tokens separated by an arbitrary
369 * number of spaces:
370 * <pre>
371 * keyStroke := &lt;modifiers&gt;* ( &lt;typedID&gt; | &lt;codeID&gt; )
372 * modifiers := ( shift | control | ctrl | meta | alt
373 * | button1 | button2 | button3 )
374 * typedID := typed &lt;single Unicode character&gt;
375 * codeID := ( pressed | released )? &lt;name&gt;
376 * name := &lt;the KeyEvent field name less the leading "VK_"&gt;
377 * </pre>
378 *
379 * <p>Note that the grammar is rather weak, and not all valid keystrokes
380 * can be generated in this manner (for example, a typed space, or anything
381 * with the alt-graph modifier!). The output of AWTKeyStroke.toString()
382 * will not meet the grammar. If pressed or released is not specified,
383 * pressed is assumed. Examples:<br>
384 * <code>
385 * "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);<br>
386 * "control DELETE" =&gt;
387 * getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);<br>
388 * "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
389 * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);<br>
390 * "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X,
391 * InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);<br>
392 * "typed a" =&gt; getAWTKeyStroke('a');
393 * </code>
394 *
395 * @param s the string to parse
396 * @return the specified keystroke
397 * @throws NullPointerException if s is null
398 * @throws IllegalArgumentException if s cannot be parsed
399 */
400 public static AWTKeyStroke getAWTKeyStroke(String s)
401 {
402 StringTokenizer t = new StringTokenizer(s, " ");
403 if (! t.hasMoreTokens())
404 throw new IllegalArgumentException();
405 int modifiers = 0;
406 boolean released = false;
407 String token = null;
408 do
409 {
410 token = t.nextToken();
411 if ("shift".equals(token))
412 modifiers |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
413 else if ("ctrl".equals(token) || "control".equals(token))
414 modifiers |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
415 else if ("meta".equals(token))
416 modifiers |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
417 else if ("alt".equals(token))
418 modifiers |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
419 else if ("button1".equals(token))
420 modifiers |= KeyEvent.BUTTON1_DOWN_MASK;
421 else if ("button2".equals(token))
422 modifiers |= KeyEvent.BUTTON2_DOWN_MASK;
423 else if ("button3".equals(token))
424 modifiers |= KeyEvent.BUTTON3_DOWN_MASK;
425 else if ("typed".equals(token))
426 {
427 if (t.hasMoreTokens())
428 {
429 token = t.nextToken();
430 if (! t.hasMoreTokens() && token.length() == 1)
431 return getAWTKeyStroke(token.charAt(0),
432 KeyEvent.VK_UNDEFINED, modifiers,
433 false);
434 }
435 throw new IllegalArgumentException();
436 }
437 else if ("pressed".equals(token))
438 {
439 if (t.hasMoreTokens())
440 token = t.nextToken();
441 break;
442 }
443 else if ("released".equals(token))
444 {
445 released = true;
446 if (t.hasMoreTokens())
447 token = t.nextToken();
448 break;
449 }
450 else
451 break;
452 }
453 while (t.hasMoreTokens());
454 // Now token contains the VK name we must parse.
455 Integer code = (Integer) vktable.get(token);
456 if (code == null || t.hasMoreTokens())
457 throw new IllegalArgumentException();
458 return getAWTKeyStroke(KeyEvent.CHAR_UNDEFINED, code.intValue(),
459 modifiers, released);
460 }
461
462 /**
463 * Returns the character of this keystroke, if it was typed.
464 *
465 * @return the character value, or CHAR_UNDEFINED
466 * @see #getAWTKeyStroke(char)
467 */
468 public final char getKeyChar()
469 {
470 return keyChar;
471 }
472
473 /**
474 * Returns the virtual key code of this keystroke, if it was pressed or
475 * released. This will be a VK_* constant from KeyEvent.
476 *
477 * @return the virtual key code value, or VK_UNDEFINED
478 * @see #getAWTKeyStroke(int, int)
479 */
480 public final int getKeyCode()
481 {
482 return keyCode;
483 }
484
485 /**
486 * Returns the modifiers for this keystroke. This will be a bitwise or of
487 * constants from InputEvent; it includes the old style masks for shift,
488 * control, alt, meta, and alt-graph (but not button1); as well as the new
489 * style of extended modifiers for all modifiers.
490 *
491 * @return the modifiers
492 * @see #getAWTKeyStroke(Character, int)
493 * @see #getAWTKeyStroke(int, int)
494 */
495 public final int getModifiers()
496 {
497 return modifiers;
498 }
499
500 /**
501 * Tests if this keystroke is a key release.
502 *
503 * @return true if this is a key release
504 * @see #getAWTKeyStroke(int, int, boolean)
505 */
506 public final boolean isOnKeyRelease()
507 {
508 return onKeyRelease;
509 }
510
511 /**
512 * Returns the AWT event type of this keystroke. This is one of
513 * {@link KeyEvent#KEY_TYPED}, {@link KeyEvent#KEY_PRESSED}, or
514 * {@link KeyEvent#KEY_RELEASED}.
515 *
516 * @return the key event type
517 */
518 public final int getKeyEventType()
519 {
520 return keyCode == KeyEvent.VK_UNDEFINED ? KeyEvent.KEY_TYPED
521 : onKeyRelease ? KeyEvent.KEY_RELEASED : KeyEvent.KEY_PRESSED;
522 }
523
524 /**
525 * Returns a hashcode for this key event. It is not documented, but appears
526 * to be: <code>(getKeyChar() + 1) * (getKeyCode() + 1)
527 * * (getModifiers() + 1) * 2 + (isOnKeyRelease() ? 1 : 2)</code>.
528 *
529 * @return the hashcode
530 */
531 public int hashCode()
532 {
533 return (keyChar + 1) * (keyCode + 1) * (modifiers + 1) * 2
534 + (onKeyRelease ? 1 : 2);
535 }
536
537 /**
538 * Tests two keystrokes for equality.
539 *
540 * @param o the object to test
541 * @return true if it is equal
542 */
543 public final boolean equals(Object o)
544 {
545 if (! (o instanceof AWTKeyStroke))
546 return false;
547 AWTKeyStroke s = (AWTKeyStroke) o;
548 return this == o || (keyChar == s.keyChar && keyCode == s.keyCode
549 && modifiers == s.modifiers
550 && onKeyRelease == s.onKeyRelease);
551 }
552
553 /**
554 * Returns a string representation of this keystroke. For typed keystrokes,
555 * this is <code>"keyChar " + KeyEvent.getKeyModifiersText(getModifiers())
556 + getKeyChar()</code>; for pressed and released keystrokes, this is
557 * <code>"keyCode " + KeyEvent.getKeyModifiersText(getModifiers())
558 * + KeyEvent.getKeyText(getKeyCode())
559 * + (isOnKeyRelease() ? "-R" : "-P")</code>.
560 *
561 * @return a string representation
562 */
563 public String toString()
564 {
565 if (keyCode == KeyEvent.VK_UNDEFINED)
566 return "keyChar " + KeyEvent.getKeyModifiersText(modifiers) + keyChar;
567 return "keyCode " + KeyEvent.getKeyModifiersText(modifiers)
568 + KeyEvent.getKeyText(keyCode) + (onKeyRelease ? "-R" : "-P");
569 }
570
571 /**
572 * Returns a cached version of the deserialized keystroke, if available.
573 *
574 * @return a cached replacement
575 * @throws ObjectStreamException if something goes wrong
576 */
577 protected Object readResolve() throws ObjectStreamException
578 {
579 AWTKeyStroke s = (AWTKeyStroke) cache.get(this);
580 if (s != null)
581 return s;
582 cache.put(this, this);
583 return this;
584 }
585
586 /**
587 * Gets the appropriate keystroke, creating one if necessary.
588 *
589 * @param keyChar the keyChar
590 * @param keyCode the keyCode
591 * @param modifiers the modifiers
592 * @param release true for key release
593 * @return the specified keystroke
594 */
595 private static AWTKeyStroke getAWTKeyStroke(char keyChar, int keyCode,
596 int modifiers, boolean release)
597 {
598 // Check level 0 cache.
599 AWTKeyStroke stroke = recent; // Avoid thread races.
600 if (stroke != null && stroke.keyChar == keyChar
601 && stroke.keyCode == keyCode && stroke.modifiers == modifiers
602 && stroke.onKeyRelease == release)
603 return stroke;
604 // Create a new object, on the assumption that if it has a match in the
605 // cache, the VM can easily garbage collect it as it is temporary.
606 Constructor c = ctor; // Avoid thread races.
607 if (c == null)
608 stroke = new AWTKeyStroke(keyChar, keyCode, modifiers, release);
609 else
610 try
611 {
612 stroke = (AWTKeyStroke) c.newInstance(null);
613 stroke.keyChar = keyChar;
614 stroke.keyCode = keyCode;
615 stroke.modifiers = modifiers;
616 stroke.onKeyRelease = release;
617 }
618 catch (Exception e)
619 {
620 throw (Error) new InternalError().initCause(e);
621 }
622 // Check level 1 cache.
623 AWTKeyStroke cached = (AWTKeyStroke) cache.get(stroke);
624 if (cached == null)
625 cache.put(stroke, stroke);
626 else
627 stroke = cached;
628 return recent = stroke;
629 }
630
631 /**
632 * Converts the modifiers to the appropriate format.
633 *
634 * @param mod the modifiers to convert
635 * @return the adjusted modifiers
636 */
637 private static int extend(int mod)
638 {
639 if ((mod & (KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK)) != 0)
640 mod |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
641 if ((mod & (KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK)) != 0)
642 mod |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
643 if ((mod & (KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK)) != 0)
644 mod |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
645 if ((mod & (KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK)) != 0)
646 mod |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
647 if ((mod & (KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK)) != 0)
648 mod |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK;
649 if ((mod & KeyEvent.BUTTON1_MASK) != 0)
650 mod |= KeyEvent.BUTTON1_DOWN_MASK;
651 return mod & MODIFIERS_MASK;
652 }
653} // class AWTKeyStroke
Note: See TracBrowser for help on using the repository browser.