Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/java/awt/AWTKeyStroke.java
41152 views
1
/*
2
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package java.awt;
27
28
import java.awt.event.InputEvent;
29
import java.awt.event.KeyEvent;
30
import java.io.Serial;
31
import java.io.Serializable;
32
import java.lang.reflect.Field;
33
import java.lang.reflect.Modifier;
34
import java.util.Collections;
35
import java.util.HashMap;
36
import java.util.Map;
37
import java.util.StringTokenizer;
38
39
import sun.awt.AppContext;
40
import sun.swing.SwingAccessor;
41
42
/**
43
* An {@code AWTKeyStroke} represents a key action on the
44
* keyboard, or equivalent input device. {@code AWTKeyStroke}s
45
* can correspond to only a press or release of a
46
* particular key, just as {@code KEY_PRESSED} and
47
* {@code KEY_RELEASED KeyEvent}s do;
48
* alternately, they can correspond to typing a specific Java character, just
49
* as {@code KEY_TYPED KeyEvent}s do.
50
* In all cases, {@code AWTKeyStroke}s can specify modifiers
51
* (alt, shift, control, meta, altGraph, or a combination thereof) which must be present
52
* during the action for an exact match.
53
* <p>
54
* {@code AWTKeyStrokes} are immutable, and are intended
55
* to be unique. Client code should never create an
56
* {@code AWTKeyStroke} on its own, but should instead use
57
* a variant of {@code getAWTKeyStroke}. Client use of these factory
58
* methods allows the {@code AWTKeyStroke} implementation
59
* to cache and share instances efficiently.
60
*
61
* @see #getAWTKeyStroke
62
*
63
* @author Arnaud Weber
64
* @author David Mendenhall
65
* @since 1.4
66
*/
67
public class AWTKeyStroke implements Serializable {
68
69
/**
70
* Use serialVersionUID from JDK 1.4 for interoperability.
71
*/
72
@Serial
73
private static final long serialVersionUID = -6430539691155161871L;
74
75
private static Map<String, Integer> modifierKeywords;
76
/**
77
* Associates VK_XXX (as a String) with code (as Integer). This is
78
* done to avoid the overhead of the reflective call to find the
79
* constant.
80
*/
81
private static VKCollection vks;
82
83
//A key for the collection of AWTKeyStrokes within AppContext.
84
private static Object APP_CONTEXT_CACHE_KEY = new Object();
85
//A key withing the cache
86
private static AWTKeyStroke APP_CONTEXT_KEYSTROKE_KEY = new AWTKeyStroke();
87
88
/**
89
* The character value for a keyboard key.
90
*/
91
private char keyChar = KeyEvent.CHAR_UNDEFINED;
92
93
/**
94
* The key code for this {@code AWTKeyStroke}.
95
*/
96
private int keyCode = KeyEvent.VK_UNDEFINED;
97
98
/**
99
* The bitwise-ored combination of any modifiers.
100
*/
101
private int modifiers;
102
103
/**
104
* {@code true} if this {@code AWTKeyStroke} corresponds to a key release;
105
* {@code false} otherwise.
106
*/
107
private boolean onKeyRelease;
108
109
static {
110
/* ensure that the necessary native libraries are loaded */
111
Toolkit.loadLibraries();
112
}
113
114
/**
115
* Constructs an {@code AWTKeyStroke} with default values.
116
* The default values used are:
117
*
118
* <table class="striped">
119
* <caption>AWTKeyStroke default values</caption>
120
* <thead>
121
* <tr>
122
* <th scope="col">Property
123
* <th scope="col">Default Value
124
* </thead>
125
* <tbody>
126
* <tr>
127
* <th scope="row">Key Char
128
* <td>{@code KeyEvent.CHAR_UNDEFINED}
129
* <tr>
130
* <th scope="row">Key Code
131
* <td>{@code KeyEvent.VK_UNDEFINED}
132
* <tr>
133
* <th scope="row">Modifiers
134
* <td>none
135
* <tr>
136
* <th scope="row">On key release?
137
* <td>{@code false}
138
* </tbody>
139
* </table>
140
*
141
* {@code AWTKeyStroke}s should not be constructed
142
* by client code. Use a variant of {@code getAWTKeyStroke}
143
* instead.
144
*
145
* @see #getAWTKeyStroke
146
*/
147
protected AWTKeyStroke() {
148
}
149
150
/**
151
* Constructs an {@code AWTKeyStroke} with the specified
152
* values. {@code AWTKeyStroke}s should not be constructed
153
* by client code. Use a variant of {@code getAWTKeyStroke}
154
* instead.
155
*
156
* @param keyChar the character value for a keyboard key
157
* @param keyCode the key code for this {@code AWTKeyStroke}
158
* @param modifiers a bitwise-ored combination of any modifiers
159
* @param onKeyRelease {@code true} if this
160
* {@code AWTKeyStroke} corresponds
161
* to a key release; {@code false} otherwise
162
* @see #getAWTKeyStroke
163
*/
164
protected AWTKeyStroke(char keyChar, int keyCode, int modifiers,
165
boolean onKeyRelease) {
166
this.keyChar = keyChar;
167
this.keyCode = keyCode;
168
this.modifiers = modifiers;
169
this.onKeyRelease = onKeyRelease;
170
}
171
172
/**
173
* The method has no effect and is only left present to avoid introducing
174
* a binary incompatibility.
175
*
176
* @param subclass the new Class of which the factory methods should create
177
* instances
178
* @deprecated
179
*/
180
@Deprecated
181
protected static void registerSubclass(Class<?> subclass) {
182
}
183
184
private static synchronized AWTKeyStroke getCachedStroke
185
(char keyChar, int keyCode, int modifiers, boolean onKeyRelease)
186
{
187
@SuppressWarnings("unchecked")
188
Map<AWTKeyStroke, AWTKeyStroke> cache = (Map)AppContext.getAppContext().get(APP_CONTEXT_CACHE_KEY);
189
AWTKeyStroke cacheKey = (AWTKeyStroke)AppContext.getAppContext().get(APP_CONTEXT_KEYSTROKE_KEY);
190
191
if (cache == null) {
192
cache = new HashMap<>();
193
AppContext.getAppContext().put(APP_CONTEXT_CACHE_KEY, cache);
194
}
195
196
if (cacheKey == null) {
197
cacheKey = SwingAccessor.getKeyStrokeAccessor().create();
198
AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey);
199
}
200
201
cacheKey.keyChar = keyChar;
202
cacheKey.keyCode = keyCode;
203
cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
204
cacheKey.onKeyRelease = onKeyRelease;
205
206
AWTKeyStroke stroke = cache.get(cacheKey);
207
if (stroke == null) {
208
stroke = cacheKey;
209
cache.put(stroke, stroke);
210
AppContext.getAppContext().remove(APP_CONTEXT_KEYSTROKE_KEY);
211
}
212
return stroke;
213
}
214
215
/**
216
* Returns a shared instance of an {@code AWTKeyStroke}
217
* that represents a {@code KEY_TYPED} event for the
218
* specified character.
219
*
220
* @param keyChar the character value for a keyboard key
221
* @return an {@code AWTKeyStroke} object for that key
222
*/
223
public static AWTKeyStroke getAWTKeyStroke(char keyChar) {
224
return getCachedStroke(keyChar, KeyEvent.VK_UNDEFINED, 0, false);
225
}
226
227
/**
228
* Returns a shared instance of an {@code AWTKeyStroke}
229
* that represents a {@code KEY_TYPED} event for the
230
* specified Character object and a set of modifiers. Note
231
* that the first parameter is of type Character rather than
232
* char. This is to avoid inadvertent clashes with
233
* calls to {@code getAWTKeyStroke(int keyCode, int modifiers)}.
234
*
235
* The modifiers consist of any combination of following:<ul>
236
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
237
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
238
* <li>java.awt.event.InputEvent.META_DOWN_MASK
239
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
240
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
241
* </ul>
242
* The old modifiers listed below also can be used, but they are
243
* mapped to _DOWN_ modifiers. <ul>
244
* <li>java.awt.event.InputEvent.SHIFT_MASK
245
* <li>java.awt.event.InputEvent.CTRL_MASK
246
* <li>java.awt.event.InputEvent.META_MASK
247
* <li>java.awt.event.InputEvent.ALT_MASK
248
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
249
* </ul>
250
* also can be used, but they are mapped to _DOWN_ modifiers.
251
*
252
* Since these numbers are all different powers of two, any combination of
253
* them is an integer in which each bit represents a different modifier
254
* key. Use 0 to specify no modifiers.
255
*
256
* @param keyChar the Character object for a keyboard character
257
* @param modifiers a bitwise-ored combination of any modifiers
258
* @return an {@code AWTKeyStroke} object for that key
259
* @throws IllegalArgumentException if {@code keyChar} is
260
* {@code null}
261
*
262
* @see java.awt.event.InputEvent
263
*/
264
public static AWTKeyStroke getAWTKeyStroke(Character keyChar, int modifiers)
265
{
266
if (keyChar == null) {
267
throw new IllegalArgumentException("keyChar cannot be null");
268
}
269
return getCachedStroke(keyChar.charValue(), KeyEvent.VK_UNDEFINED,
270
modifiers, false);
271
}
272
273
/**
274
* Returns a shared instance of an {@code AWTKeyStroke},
275
* given a numeric key code and a set of modifiers, specifying
276
* whether the key is activated when it is pressed or released.
277
* <p>
278
* The "virtual key" constants defined in
279
* {@code java.awt.event.KeyEvent} can be
280
* used to specify the key code. For example:<ul>
281
* <li>{@code java.awt.event.KeyEvent.VK_ENTER}
282
* <li>{@code java.awt.event.KeyEvent.VK_TAB}
283
* <li>{@code java.awt.event.KeyEvent.VK_SPACE}
284
* </ul>
285
* Alternatively, the key code may be obtained by calling
286
* {@code java.awt.event.KeyEvent.getExtendedKeyCodeForChar}.
287
*
288
* The modifiers consist of any combination of:<ul>
289
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
290
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
291
* <li>java.awt.event.InputEvent.META_DOWN_MASK
292
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
293
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
294
* </ul>
295
* The old modifiers <ul>
296
* <li>java.awt.event.InputEvent.SHIFT_MASK
297
* <li>java.awt.event.InputEvent.CTRL_MASK
298
* <li>java.awt.event.InputEvent.META_MASK
299
* <li>java.awt.event.InputEvent.ALT_MASK
300
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
301
* </ul>
302
* also can be used, but they are mapped to _DOWN_ modifiers.
303
*
304
* Since these numbers are all different powers of two, any combination of
305
* them is an integer in which each bit represents a different modifier
306
* key. Use 0 to specify no modifiers.
307
*
308
* @param keyCode an int specifying the numeric code for a keyboard key
309
* @param modifiers a bitwise-ored combination of any modifiers
310
* @param onKeyRelease {@code true} if the {@code AWTKeyStroke}
311
* should represent a key release; {@code false} otherwise
312
* @return an AWTKeyStroke object for that key
313
*
314
* @see java.awt.event.KeyEvent
315
* @see java.awt.event.InputEvent
316
*/
317
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers,
318
boolean onKeyRelease) {
319
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
320
onKeyRelease);
321
}
322
323
/**
324
* Returns a shared instance of an {@code AWTKeyStroke},
325
* given a numeric key code and a set of modifiers. The returned
326
* {@code AWTKeyStroke} will correspond to a key press.
327
* <p>
328
* The "virtual key" constants defined in
329
* {@code java.awt.event.KeyEvent} can be
330
* used to specify the key code. For example:<ul>
331
* <li>{@code java.awt.event.KeyEvent.VK_ENTER}
332
* <li>{@code java.awt.event.KeyEvent.VK_TAB}
333
* <li>{@code java.awt.event.KeyEvent.VK_SPACE}
334
* </ul>
335
* The modifiers consist of any combination of:<ul>
336
* <li>java.awt.event.InputEvent.SHIFT_DOWN_MASK
337
* <li>java.awt.event.InputEvent.CTRL_DOWN_MASK
338
* <li>java.awt.event.InputEvent.META_DOWN_MASK
339
* <li>java.awt.event.InputEvent.ALT_DOWN_MASK
340
* <li>java.awt.event.InputEvent.ALT_GRAPH_DOWN_MASK
341
* </ul>
342
* The old modifiers <ul>
343
* <li>java.awt.event.InputEvent.SHIFT_MASK
344
* <li>java.awt.event.InputEvent.CTRL_MASK
345
* <li>java.awt.event.InputEvent.META_MASK
346
* <li>java.awt.event.InputEvent.ALT_MASK
347
* <li>java.awt.event.InputEvent.ALT_GRAPH_MASK
348
* </ul>
349
* also can be used, but they are mapped to _DOWN_ modifiers.
350
*
351
* Since these numbers are all different powers of two, any combination of
352
* them is an integer in which each bit represents a different modifier
353
* key. Use 0 to specify no modifiers.
354
*
355
* @param keyCode an int specifying the numeric code for a keyboard key
356
* @param modifiers a bitwise-ored combination of any modifiers
357
* @return an {@code AWTKeyStroke} object for that key
358
*
359
* @see java.awt.event.KeyEvent
360
* @see java.awt.event.InputEvent
361
*/
362
public static AWTKeyStroke getAWTKeyStroke(int keyCode, int modifiers) {
363
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode, modifiers,
364
false);
365
}
366
367
/**
368
* Returns an {@code AWTKeyStroke} which represents the
369
* stroke which generated a given {@code KeyEvent}.
370
* <p>
371
* This method obtains the keyChar from a {@code KeyTyped}
372
* event, and the keyCode from a {@code KeyPressed} or
373
* {@code KeyReleased} event. The {@code KeyEvent} modifiers are
374
* obtained for all three types of {@code KeyEvent}.
375
*
376
* @param anEvent the {@code KeyEvent} from which to
377
* obtain the {@code AWTKeyStroke}
378
* @throws NullPointerException if {@code anEvent} is null
379
* @return the {@code AWTKeyStroke} that precipitated the event
380
*/
381
@SuppressWarnings("deprecation")
382
public static AWTKeyStroke getAWTKeyStrokeForEvent(KeyEvent anEvent) {
383
int id = anEvent.getID();
384
switch(id) {
385
case KeyEvent.KEY_PRESSED:
386
case KeyEvent.KEY_RELEASED:
387
return getCachedStroke(KeyEvent.CHAR_UNDEFINED,
388
anEvent.getKeyCode(),
389
anEvent.getModifiers(),
390
(id == KeyEvent.KEY_RELEASED));
391
case KeyEvent.KEY_TYPED:
392
return getCachedStroke(anEvent.getKeyChar(),
393
KeyEvent.VK_UNDEFINED,
394
anEvent.getModifiers(),
395
false);
396
default:
397
// Invalid ID for this KeyEvent
398
return null;
399
}
400
}
401
402
/**
403
* Parses a string and returns an {@code AWTKeyStroke}.
404
* The string must have the following syntax:
405
* <pre>
406
* &lt;modifiers&gt;* (&lt;typedID&gt; | &lt;pressedReleasedID&gt;)
407
*
408
* modifiers := shift | control | ctrl | meta | alt | altGraph
409
* typedID := typed &lt;typedKey&gt;
410
* typedKey := string of length 1 giving Unicode character.
411
* pressedReleasedID := (pressed | released) key
412
* key := KeyEvent key code name, i.e. the name following "VK_".
413
* </pre>
414
* If typed, pressed or released is not specified, pressed is assumed. Here
415
* are some examples:
416
* <pre>
417
* "INSERT" =&gt; getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
418
* "control DELETE" =&gt; getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
419
* "alt shift X" =&gt; getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
420
* "alt shift released X" =&gt; getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
421
* "typed a" =&gt; getAWTKeyStroke('a');
422
* </pre>
423
*
424
* @param s a String formatted as described above
425
* @return an {@code AWTKeyStroke} object for that String
426
* @throws IllegalArgumentException if {@code s} is {@code null},
427
* or is formatted incorrectly
428
*/
429
@SuppressWarnings("deprecation")
430
public static AWTKeyStroke getAWTKeyStroke(String s) {
431
if (s == null) {
432
throw new IllegalArgumentException("String cannot be null");
433
}
434
435
final String errmsg = "String formatted incorrectly";
436
437
StringTokenizer st = new StringTokenizer(s, " ");
438
439
int mask = 0;
440
boolean released = false;
441
boolean typed = false;
442
boolean pressed = false;
443
444
synchronized (AWTKeyStroke.class) {
445
if (modifierKeywords == null) {
446
Map<String, Integer> uninitializedMap = new HashMap<>(8, 1.0f);
447
uninitializedMap.put("shift",
448
Integer.valueOf(InputEvent.SHIFT_DOWN_MASK
449
|InputEvent.SHIFT_MASK));
450
uninitializedMap.put("control",
451
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
452
|InputEvent.CTRL_MASK));
453
uninitializedMap.put("ctrl",
454
Integer.valueOf(InputEvent.CTRL_DOWN_MASK
455
|InputEvent.CTRL_MASK));
456
uninitializedMap.put("meta",
457
Integer.valueOf(InputEvent.META_DOWN_MASK
458
|InputEvent.META_MASK));
459
uninitializedMap.put("alt",
460
Integer.valueOf(InputEvent.ALT_DOWN_MASK
461
|InputEvent.ALT_MASK));
462
uninitializedMap.put("altGraph",
463
Integer.valueOf(InputEvent.ALT_GRAPH_DOWN_MASK
464
|InputEvent.ALT_GRAPH_MASK));
465
uninitializedMap.put("button1",
466
Integer.valueOf(InputEvent.BUTTON1_DOWN_MASK));
467
uninitializedMap.put("button2",
468
Integer.valueOf(InputEvent.BUTTON2_DOWN_MASK));
469
uninitializedMap.put("button3",
470
Integer.valueOf(InputEvent.BUTTON3_DOWN_MASK));
471
modifierKeywords =
472
Collections.synchronizedMap(uninitializedMap);
473
}
474
}
475
476
int count = st.countTokens();
477
478
for (int i = 1; i <= count; i++) {
479
String token = st.nextToken();
480
481
if (typed) {
482
if (token.length() != 1 || i != count) {
483
throw new IllegalArgumentException(errmsg);
484
}
485
return getCachedStroke(token.charAt(0), KeyEvent.VK_UNDEFINED,
486
mask, false);
487
}
488
489
if (pressed || released || i == count) {
490
if (i != count) {
491
throw new IllegalArgumentException(errmsg);
492
}
493
494
String keyCodeName = "VK_" + token;
495
int keyCode = getVKValue(keyCodeName);
496
497
return getCachedStroke(KeyEvent.CHAR_UNDEFINED, keyCode,
498
mask, released);
499
}
500
501
if (token.equals("released")) {
502
released = true;
503
continue;
504
}
505
if (token.equals("pressed")) {
506
pressed = true;
507
continue;
508
}
509
if (token.equals("typed")) {
510
typed = true;
511
continue;
512
}
513
514
Integer tokenMask = modifierKeywords.get(token);
515
if (tokenMask != null) {
516
mask |= tokenMask.intValue();
517
} else {
518
throw new IllegalArgumentException(errmsg);
519
}
520
}
521
522
throw new IllegalArgumentException(errmsg);
523
}
524
525
private static VKCollection getVKCollection() {
526
if (vks == null) {
527
vks = new VKCollection();
528
}
529
return vks;
530
}
531
/**
532
* Returns the integer constant for the KeyEvent.VK field named
533
* {@code key}. This will throw an
534
* {@code IllegalArgumentException} if {@code key} is
535
* not a valid constant.
536
*/
537
private static int getVKValue(String key) {
538
VKCollection vkCollect = getVKCollection();
539
540
Integer value = vkCollect.findCode(key);
541
542
if (value == null) {
543
int keyCode = 0;
544
final String errmsg = "String formatted incorrectly";
545
546
try {
547
keyCode = KeyEvent.class.getField(key).getInt(KeyEvent.class);
548
} catch (NoSuchFieldException nsfe) {
549
throw new IllegalArgumentException(errmsg);
550
} catch (IllegalAccessException iae) {
551
throw new IllegalArgumentException(errmsg);
552
}
553
value = Integer.valueOf(keyCode);
554
vkCollect.put(key, value);
555
}
556
return value.intValue();
557
}
558
559
/**
560
* Returns the character for this {@code AWTKeyStroke}.
561
*
562
* @return a char value
563
* @see #getAWTKeyStroke(char)
564
* @see KeyEvent#getKeyChar
565
*/
566
public final char getKeyChar() {
567
return keyChar;
568
}
569
570
/**
571
* Returns the numeric key code for this {@code AWTKeyStroke}.
572
*
573
* @return an int containing the key code value
574
* @see #getAWTKeyStroke(int,int)
575
* @see KeyEvent#getKeyCode
576
*/
577
public final int getKeyCode() {
578
return keyCode;
579
}
580
581
/**
582
* Returns the modifier keys for this {@code AWTKeyStroke}.
583
*
584
* @return an int containing the modifiers
585
* @see #getAWTKeyStroke(int,int)
586
*/
587
public final int getModifiers() {
588
return modifiers;
589
}
590
591
/**
592
* Returns whether this {@code AWTKeyStroke} represents a key release.
593
*
594
* @return {@code true} if this {@code AWTKeyStroke}
595
* represents a key release; {@code false} otherwise
596
* @see #getAWTKeyStroke(int,int,boolean)
597
*/
598
public final boolean isOnKeyRelease() {
599
return onKeyRelease;
600
}
601
602
/**
603
* Returns the type of {@code KeyEvent} which corresponds to
604
* this {@code AWTKeyStroke}.
605
*
606
* @return {@code KeyEvent.KEY_PRESSED},
607
* {@code KeyEvent.KEY_TYPED},
608
* or {@code KeyEvent.KEY_RELEASED}
609
* @see java.awt.event.KeyEvent
610
*/
611
public final int getKeyEventType() {
612
if (keyCode == KeyEvent.VK_UNDEFINED) {
613
return KeyEvent.KEY_TYPED;
614
} else {
615
return (onKeyRelease)
616
? KeyEvent.KEY_RELEASED
617
: KeyEvent.KEY_PRESSED;
618
}
619
}
620
621
/**
622
* Returns a numeric value for this object that is likely to be unique,
623
* making it a good choice as the index value in a hash table.
624
*
625
* @return an int that represents this object
626
*/
627
public int hashCode() {
628
return (((int)keyChar) + 1) * (2 * (keyCode + 1)) * (modifiers + 1) +
629
(onKeyRelease ? 1 : 2);
630
}
631
632
/**
633
* Returns true if this object is identical to the specified object.
634
*
635
* @param anObject the Object to compare this object to
636
* @return true if the objects are identical
637
*/
638
public final boolean equals(Object anObject) {
639
if (anObject instanceof AWTKeyStroke) {
640
AWTKeyStroke ks = (AWTKeyStroke)anObject;
641
return (ks.keyChar == keyChar && ks.keyCode == keyCode &&
642
ks.onKeyRelease == onKeyRelease &&
643
ks.modifiers == modifiers);
644
}
645
return false;
646
}
647
648
/**
649
* Returns a string that displays and identifies this object's properties.
650
* The {@code String} returned by this method can be passed
651
* as a parameter to {@code getAWTKeyStroke(String)} to produce
652
* a key stroke equal to this key stroke.
653
*
654
* @return a String representation of this object
655
* @see #getAWTKeyStroke(String)
656
*/
657
public String toString() {
658
if (keyCode == KeyEvent.VK_UNDEFINED) {
659
return getModifiersText(modifiers) + "typed " + keyChar;
660
} else {
661
return getModifiersText(modifiers) +
662
(onKeyRelease ? "released" : "pressed") + " " +
663
getVKText(keyCode);
664
}
665
}
666
667
static String getModifiersText(int modifiers) {
668
StringBuilder buf = new StringBuilder();
669
670
if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 ) {
671
buf.append("shift ");
672
}
673
if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0 ) {
674
buf.append("ctrl ");
675
}
676
if ((modifiers & InputEvent.META_DOWN_MASK) != 0 ) {
677
buf.append("meta ");
678
}
679
if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
680
buf.append("alt ");
681
}
682
if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 ) {
683
buf.append("altGraph ");
684
}
685
if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0 ) {
686
buf.append("button1 ");
687
}
688
if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0 ) {
689
buf.append("button2 ");
690
}
691
if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0 ) {
692
buf.append("button3 ");
693
}
694
695
return buf.toString();
696
}
697
698
static String getVKText(int keyCode) {
699
VKCollection vkCollect = getVKCollection();
700
Integer key = Integer.valueOf(keyCode);
701
String name = vkCollect.findName(key);
702
if (name != null) {
703
return name.substring(3);
704
}
705
int expected_modifiers =
706
(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
707
708
Field[] fields = KeyEvent.class.getDeclaredFields();
709
for (int i = 0; i < fields.length; i++) {
710
try {
711
if (fields[i].getModifiers() == expected_modifiers
712
&& fields[i].getType() == Integer.TYPE
713
&& fields[i].getName().startsWith("VK_")
714
&& fields[i].getInt(KeyEvent.class) == keyCode)
715
{
716
name = fields[i].getName();
717
vkCollect.put(name, key);
718
return name.substring(3);
719
}
720
} catch (IllegalAccessException e) {
721
assert(false);
722
}
723
}
724
return "UNKNOWN";
725
}
726
727
/**
728
* Returns a cached instance of {@code AWTKeyStroke} (or a subclass of
729
* {@code AWTKeyStroke}) which is equal to this instance.
730
*
731
* @return a cached instance which is equal to this instance
732
* @throws java.io.ObjectStreamException if a serialization problem occurs
733
*/
734
@Serial
735
protected Object readResolve() throws java.io.ObjectStreamException {
736
synchronized (AWTKeyStroke.class) {
737
738
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
739
}
740
}
741
742
@SuppressWarnings("deprecation")
743
private static int mapOldModifiers(int modifiers) {
744
if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
745
modifiers |= InputEvent.SHIFT_DOWN_MASK;
746
}
747
if ((modifiers & InputEvent.ALT_MASK) != 0) {
748
modifiers |= InputEvent.ALT_DOWN_MASK;
749
}
750
if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
751
modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
752
}
753
if ((modifiers & InputEvent.CTRL_MASK) != 0) {
754
modifiers |= InputEvent.CTRL_DOWN_MASK;
755
}
756
if ((modifiers & InputEvent.META_MASK) != 0) {
757
modifiers |= InputEvent.META_DOWN_MASK;
758
}
759
760
modifiers &= InputEvent.SHIFT_DOWN_MASK
761
| InputEvent.ALT_DOWN_MASK
762
| InputEvent.ALT_GRAPH_DOWN_MASK
763
| InputEvent.CTRL_DOWN_MASK
764
| InputEvent.META_DOWN_MASK
765
| InputEvent.BUTTON1_DOWN_MASK
766
| InputEvent.BUTTON2_DOWN_MASK
767
| InputEvent.BUTTON3_DOWN_MASK;
768
769
return modifiers;
770
}
771
772
@SuppressWarnings("deprecation")
773
private static int mapNewModifiers(int modifiers) {
774
if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
775
modifiers |= InputEvent.SHIFT_MASK;
776
}
777
if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0) {
778
modifiers |= InputEvent.ALT_MASK;
779
}
780
if ((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
781
modifiers |= InputEvent.ALT_GRAPH_MASK;
782
}
783
if ((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
784
modifiers |= InputEvent.CTRL_MASK;
785
}
786
if ((modifiers & InputEvent.META_DOWN_MASK) != 0) {
787
modifiers |= InputEvent.META_MASK;
788
}
789
790
return modifiers;
791
}
792
793
}
794
795
class VKCollection {
796
Map<Integer, String> code2name;
797
Map<String, Integer> name2code;
798
799
public VKCollection() {
800
code2name = new HashMap<>();
801
name2code = new HashMap<>();
802
}
803
804
public synchronized void put(String name, Integer code) {
805
assert((name != null) && (code != null));
806
assert(findName(code) == null);
807
assert(findCode(name) == null);
808
code2name.put(code, name);
809
name2code.put(name, code);
810
}
811
812
public synchronized Integer findCode(String name) {
813
assert(name != null);
814
return name2code.get(name);
815
}
816
817
public synchronized String findName(Integer code) {
818
assert(code != null);
819
return code2name.get(code);
820
}
821
}
822
823