Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/java/src/org/openqa/selenium/Keys.java
3991 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
package org.openqa.selenium;
19
20
import java.util.List;
21
import org.jspecify.annotations.Nullable;
22
23
/**
24
* Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private
25
* Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate
26
* keyboard input where standard Unicode characters are insufficient, such as modifier and control
27
* keys.
28
*
29
* <p>The codes follow conventions partially established by the W3C WebDriver specification and the
30
* Selenium project. Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are
31
* not currently part of the W3C spec. Others (e.g., OPTION, FN) are symbolic and reserved for
32
* possible future mapping.
33
*
34
* <p>For consistency across platforms and drivers, values should be verified before assuming native
35
* support.
36
*
37
* @see <a href="https://www.w3.org/TR/webdriver/#keyboard-actions">W3C WebDriver Keyboard
38
* Actions</a>
39
* @see <a href="http://www.google.com.au/search?&q=unicode+pua&btnK=Search">Unicode PUA
40
* Overview</a>
41
*/
42
public enum Keys implements CharSequence {
43
// Basic control characters
44
NULL('\uE000'),
45
CANCEL('\uE001'), // ^break
46
HELP('\uE002'),
47
BACK_SPACE('\uE003'),
48
TAB('\uE004'),
49
CLEAR('\uE005'),
50
RETURN('\uE006'),
51
ENTER('\uE007'),
52
SHIFT('\uE008'),
53
LEFT_SHIFT(Keys.SHIFT),
54
CONTROL('\uE009'),
55
LEFT_CONTROL(Keys.CONTROL),
56
ALT('\uE00A'),
57
LEFT_ALT(Keys.ALT),
58
PAUSE('\uE00B'),
59
ESCAPE('\uE00C'),
60
SPACE('\uE00D'),
61
PAGE_UP('\uE00E'),
62
PAGE_DOWN('\uE00F'),
63
END('\uE010'),
64
HOME('\uE011'),
65
LEFT('\uE012'),
66
ARROW_LEFT(Keys.LEFT),
67
UP('\uE013'),
68
ARROW_UP(Keys.UP),
69
RIGHT('\uE014'),
70
ARROW_RIGHT(Keys.RIGHT),
71
DOWN('\uE015'),
72
ARROW_DOWN(Keys.DOWN),
73
INSERT('\uE016'),
74
DELETE('\uE017'),
75
SEMICOLON('\uE018'),
76
EQUALS('\uE019'),
77
78
// Number pad keys
79
NUMPAD0('\uE01A'),
80
NUMPAD1('\uE01B'),
81
NUMPAD2('\uE01C'),
82
NUMPAD3('\uE01D'),
83
NUMPAD4('\uE01E'),
84
NUMPAD5('\uE01F'),
85
NUMPAD6('\uE020'),
86
NUMPAD7('\uE021'),
87
NUMPAD8('\uE022'),
88
NUMPAD9('\uE023'),
89
MULTIPLY('\uE024'),
90
ADD('\uE025'),
91
SEPARATOR('\uE026'),
92
SUBTRACT('\uE027'),
93
DECIMAL('\uE028'),
94
DIVIDE('\uE029'),
95
96
// Function keys
97
F1('\uE031'),
98
F2('\uE032'),
99
F3('\uE033'),
100
F4('\uE034'),
101
F5('\uE035'),
102
F6('\uE036'),
103
F7('\uE037'),
104
F8('\uE038'),
105
F9('\uE039'),
106
F10('\uE03A'),
107
F11('\uE03B'),
108
F12('\uE03C'),
109
110
META('\uE03D'),
111
COMMAND(Keys.META),
112
113
// Extended macOS/ChromeDriver keys (based on observed Chrome usage)
114
RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver usage
115
RIGHT_CONTROL('\uE051'),
116
RIGHT_ALT('\uE052'),
117
RIGHT_COMMAND('\uE053'),
118
119
// Symbolic macOS keys not yet standardized
120
OPTION('\uE052'),
121
FN('\uE051'), // TODO: symbolic only; confirm or remove in future
122
123
ZENKAKU_HANKAKU('\uE040');
124
125
private final char keyCode;
126
private final int codePoint;
127
128
Keys(Keys key) {
129
this(key.charAt(0));
130
}
131
132
Keys(char keyCode) {
133
this.keyCode = keyCode;
134
this.codePoint = String.valueOf(keyCode).codePoints().findFirst().getAsInt();
135
}
136
137
public int getCodePoint() {
138
return codePoint;
139
}
140
141
@Override
142
public char charAt(int index) {
143
if (index == 0) {
144
return keyCode;
145
}
146
return 0;
147
}
148
149
@Override
150
public int length() {
151
return 1;
152
}
153
154
@Override
155
public CharSequence subSequence(int start, int end) {
156
if (start == 0 && end == 1) {
157
return String.valueOf(keyCode);
158
}
159
throw new IndexOutOfBoundsException();
160
}
161
162
@Override
163
public String toString() {
164
return String.valueOf(keyCode);
165
}
166
167
/**
168
* Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings;
169
* appends each to a string, adds the chord termination key (Keys.NULL), and returns it.
170
*
171
* <p>Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events.
172
*
173
* @param value characters to send
174
* @return String representation of the char sequence
175
*/
176
public static String chord(CharSequence... value) {
177
return chord(List.of(value));
178
}
179
180
/**
181
* Overload of {@link #chord(CharSequence...)} that accepts an iterable.
182
*
183
* @param value characters to send
184
* @return String representation of the char sequence
185
*/
186
public static String chord(Iterable<CharSequence> value) {
187
StringBuilder builder = new StringBuilder();
188
for (CharSequence seq : value) {
189
builder.append(seq);
190
}
191
builder.append(Keys.NULL);
192
return builder.toString();
193
}
194
195
/**
196
* Retrieves the {@link Keys} enum constant corresponding to the given Unicode character.
197
*
198
* @param key unicode character code
199
* @return special key linked to the character code, or null if not found
200
*/
201
public static @Nullable Keys getKeyFromUnicode(char key) {
202
for (Keys unicodeKey : values()) {
203
if (unicodeKey.charAt(0) == key) {
204
return unicodeKey;
205
}
206
}
207
return null;
208
}
209
}
210
211