Path: blob/trunk/java/src/org/openqa/selenium/Keys.java
3991 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.List;20import org.jspecify.annotations.Nullable;2122/**23* Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private24* Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate25* keyboard input where standard Unicode characters are insufficient, such as modifier and control26* keys.27*28* <p>The codes follow conventions partially established by the W3C WebDriver specification and the29* Selenium project. Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are30* not currently part of the W3C spec. Others (e.g., OPTION, FN) are symbolic and reserved for31* possible future mapping.32*33* <p>For consistency across platforms and drivers, values should be verified before assuming native34* support.35*36* @see <a href="https://www.w3.org/TR/webdriver/#keyboard-actions">W3C WebDriver Keyboard37* Actions</a>38* @see <a href="http://www.google.com.au/search?&q=unicode+pua&btnK=Search">Unicode PUA39* Overview</a>40*/41public enum Keys implements CharSequence {42// Basic control characters43NULL('\uE000'),44CANCEL('\uE001'), // ^break45HELP('\uE002'),46BACK_SPACE('\uE003'),47TAB('\uE004'),48CLEAR('\uE005'),49RETURN('\uE006'),50ENTER('\uE007'),51SHIFT('\uE008'),52LEFT_SHIFT(Keys.SHIFT),53CONTROL('\uE009'),54LEFT_CONTROL(Keys.CONTROL),55ALT('\uE00A'),56LEFT_ALT(Keys.ALT),57PAUSE('\uE00B'),58ESCAPE('\uE00C'),59SPACE('\uE00D'),60PAGE_UP('\uE00E'),61PAGE_DOWN('\uE00F'),62END('\uE010'),63HOME('\uE011'),64LEFT('\uE012'),65ARROW_LEFT(Keys.LEFT),66UP('\uE013'),67ARROW_UP(Keys.UP),68RIGHT('\uE014'),69ARROW_RIGHT(Keys.RIGHT),70DOWN('\uE015'),71ARROW_DOWN(Keys.DOWN),72INSERT('\uE016'),73DELETE('\uE017'),74SEMICOLON('\uE018'),75EQUALS('\uE019'),7677// Number pad keys78NUMPAD0('\uE01A'),79NUMPAD1('\uE01B'),80NUMPAD2('\uE01C'),81NUMPAD3('\uE01D'),82NUMPAD4('\uE01E'),83NUMPAD5('\uE01F'),84NUMPAD6('\uE020'),85NUMPAD7('\uE021'),86NUMPAD8('\uE022'),87NUMPAD9('\uE023'),88MULTIPLY('\uE024'),89ADD('\uE025'),90SEPARATOR('\uE026'),91SUBTRACT('\uE027'),92DECIMAL('\uE028'),93DIVIDE('\uE029'),9495// Function keys96F1('\uE031'),97F2('\uE032'),98F3('\uE033'),99F4('\uE034'),100F5('\uE035'),101F6('\uE036'),102F7('\uE037'),103F8('\uE038'),104F9('\uE039'),105F10('\uE03A'),106F11('\uE03B'),107F12('\uE03C'),108109META('\uE03D'),110COMMAND(Keys.META),111112// Extended macOS/ChromeDriver keys (based on observed Chrome usage)113RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver usage114RIGHT_CONTROL('\uE051'),115RIGHT_ALT('\uE052'),116RIGHT_COMMAND('\uE053'),117118// Symbolic macOS keys not yet standardized119OPTION('\uE052'),120FN('\uE051'), // TODO: symbolic only; confirm or remove in future121122ZENKAKU_HANKAKU('\uE040');123124private final char keyCode;125private final int codePoint;126127Keys(Keys key) {128this(key.charAt(0));129}130131Keys(char keyCode) {132this.keyCode = keyCode;133this.codePoint = String.valueOf(keyCode).codePoints().findFirst().getAsInt();134}135136public int getCodePoint() {137return codePoint;138}139140@Override141public char charAt(int index) {142if (index == 0) {143return keyCode;144}145return 0;146}147148@Override149public int length() {150return 1;151}152153@Override154public CharSequence subSequence(int start, int end) {155if (start == 0 && end == 1) {156return String.valueOf(keyCode);157}158throw new IndexOutOfBoundsException();159}160161@Override162public String toString() {163return String.valueOf(keyCode);164}165166/**167* Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings;168* appends each to a string, adds the chord termination key (Keys.NULL), and returns it.169*170* <p>Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events.171*172* @param value characters to send173* @return String representation of the char sequence174*/175public static String chord(CharSequence... value) {176return chord(List.of(value));177}178179/**180* Overload of {@link #chord(CharSequence...)} that accepts an iterable.181*182* @param value characters to send183* @return String representation of the char sequence184*/185public static String chord(Iterable<CharSequence> value) {186StringBuilder builder = new StringBuilder();187for (CharSequence seq : value) {188builder.append(seq);189}190builder.append(Keys.NULL);191return builder.toString();192}193194/**195* Retrieves the {@link Keys} enum constant corresponding to the given Unicode character.196*197* @param key unicode character code198* @return special key linked to the character code, or null if not found199*/200public static @Nullable Keys getKeyFromUnicode(char key) {201for (Keys unicodeKey : values()) {202if (unicodeKey.charAt(0) == key) {203return unicodeKey;204}205}206return null;207}208}209210211