Path: blob/trunk/java/src/org/openqa/selenium/Keys.java
1865 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617package org.openqa.selenium;1819import java.util.Arrays;20import org.jspecify.annotations.NullMarked;21import org.jspecify.annotations.Nullable;2223/**24* Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private25* Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate26* keyboard input where standard Unicode characters are insufficient, such as modifier and control27* keys.28*29* <p>The codes follow conventions partially established by the W3C WebDriver specification and the30* Selenium project. Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are31* not currently part of the W3C spec. Others (e.g., OPTION, FN) are symbolic and reserved for32* possible future mapping.33*34* <p>For consistency across platforms and drivers, values should be verified before assuming native35* support.36*37* @see <a href="https://www.w3.org/TR/webdriver/#keyboard-actions">W3C WebDriver Keyboard38* Actions</a>39* @see <a href="http://www.google.com.au/search?&q=unicode+pua&btnK=Search">Unicode PUA40* Overview</a>41*/42@NullMarked43public enum Keys implements CharSequence {44// Basic control characters45NULL('\uE000'),46CANCEL('\uE001'), // ^break47HELP('\uE002'),48BACK_SPACE('\uE003'),49TAB('\uE004'),50CLEAR('\uE005'),51RETURN('\uE006'),52ENTER('\uE007'),53SHIFT('\uE008'),54LEFT_SHIFT(Keys.SHIFT),55CONTROL('\uE009'),56LEFT_CONTROL(Keys.CONTROL),57ALT('\uE00A'),58LEFT_ALT(Keys.ALT),59PAUSE('\uE00B'),60ESCAPE('\uE00C'),61SPACE('\uE00D'),62PAGE_UP('\uE00E'),63PAGE_DOWN('\uE00F'),64END('\uE010'),65HOME('\uE011'),66LEFT('\uE012'),67ARROW_LEFT(Keys.LEFT),68UP('\uE013'),69ARROW_UP(Keys.UP),70RIGHT('\uE014'),71ARROW_RIGHT(Keys.RIGHT),72DOWN('\uE015'),73ARROW_DOWN(Keys.DOWN),74INSERT('\uE016'),75DELETE('\uE017'),76SEMICOLON('\uE018'),77EQUALS('\uE019'),7879// Number pad keys80NUMPAD0('\uE01A'),81NUMPAD1('\uE01B'),82NUMPAD2('\uE01C'),83NUMPAD3('\uE01D'),84NUMPAD4('\uE01E'),85NUMPAD5('\uE01F'),86NUMPAD6('\uE020'),87NUMPAD7('\uE021'),88NUMPAD8('\uE022'),89NUMPAD9('\uE023'),90MULTIPLY('\uE024'),91ADD('\uE025'),92SEPARATOR('\uE026'),93SUBTRACT('\uE027'),94DECIMAL('\uE028'),95DIVIDE('\uE029'),9697// Function keys98F1('\uE031'),99F2('\uE032'),100F3('\uE033'),101F4('\uE034'),102F5('\uE035'),103F6('\uE036'),104F7('\uE037'),105F8('\uE038'),106F9('\uE039'),107F10('\uE03A'),108F11('\uE03B'),109F12('\uE03C'),110111META('\uE03D'),112COMMAND(Keys.META),113114// Extended macOS/ChromeDriver keys (based on observed Chrome usage)115RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver usage116RIGHT_CONTROL('\uE051'),117RIGHT_ALT('\uE052'),118RIGHT_COMMAND('\uE053'),119120// Symbolic macOS keys not yet standardized121OPTION('\uE052'),122FN('\uE051'), // TODO: symbolic only; confirm or remove in future123124ZENKAKU_HANKAKU('\uE040');125126private final char keyCode;127private final int codePoint;128129Keys(Keys key) {130this(key.charAt(0));131}132133Keys(char keyCode) {134this.keyCode = keyCode;135this.codePoint = String.valueOf(keyCode).codePoints().findFirst().getAsInt();136}137138public int getCodePoint() {139return codePoint;140}141142@Override143public char charAt(int index) {144if (index == 0) {145return keyCode;146}147return 0;148}149150@Override151public int length() {152return 1;153}154155@Override156public CharSequence subSequence(int start, int end) {157if (start == 0 && end == 1) {158return String.valueOf(keyCode);159}160throw new IndexOutOfBoundsException();161}162163@Override164public String toString() {165return String.valueOf(keyCode);166}167168/**169* Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings;170* appends each to a string, adds the chord termination key (Keys.NULL), and returns it.171*172* <p>Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events.173*174* @param value characters to send175* @return String representation of the char sequence176*/177public static String chord(CharSequence... value) {178return chord(Arrays.asList(value));179}180181/**182* Overload of {@link #chord(CharSequence...)} that accepts an iterable.183*184* @param value characters to send185* @return String representation of the char sequence186*/187public static String chord(Iterable<CharSequence> value) {188StringBuilder builder = new StringBuilder();189for (CharSequence seq : value) {190builder.append(seq);191}192builder.append(Keys.NULL);193return builder.toString();194}195196/**197* Retrieves the {@link Keys} enum constant corresponding to the given Unicode character.198*199* @param key unicode character code200* @return special key linked to the character code, or null if not found201*/202public static @Nullable Keys getKeyFromUnicode(char key) {203for (Keys unicodeKey : values()) {204if (unicodeKey.charAt(0) == key) {205return unicodeKey;206}207}208return null;209}210}211212213