From db4b55945d9d1558b97ff89a108db82a56c6a4be Mon Sep 17 00:00:00 2001 From: Manuel Blanco Date: Wed, 18 Jun 2025 22:53:30 +0200 Subject: [PATCH 1/4] [FEAT] Add macOS-specific keys (OPTION, FN) to Keys enum for improved platform support --- java/src/org/openqa/selenium/Keys.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/src/org/openqa/selenium/Keys.java b/java/src/org/openqa/selenium/Keys.java index 02231ea99cd0c..cef240cad4055 100644 --- a/java/src/org/openqa/selenium/Keys.java +++ b/java/src/org/openqa/selenium/Keys.java @@ -98,6 +98,8 @@ public enum Keys implements CharSequence { META('\uE03D'), COMMAND(Keys.META), + OPTION('\uE050'), + FN('\uE051'), ZENKAKU_HANKAKU('\uE040'); From 2794711007edfbaec2e1ade4c7ed2dea4cce95a6 Mon Sep 17 00:00:00 2001 From: Manuel Blanco Date: Wed, 18 Jun 2025 23:03:57 +0200 Subject: [PATCH 2/4] [FEAT] These additions (RIGHT_SHIFT, RIGHT_CONTROL, RIGHT_ALT, RIGHT_COMMAND) follow conventions already in use by ChromeDriver and allow for more accurate key simulations. While not currently in the W3C WebDriver specification, they represent a practical standard used in the field. --- java/src/org/openqa/selenium/Keys.java | 40 +++++++------------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/java/src/org/openqa/selenium/Keys.java b/java/src/org/openqa/selenium/Keys.java index cef240cad4055..a42de2d017013 100644 --- a/java/src/org/openqa/selenium/Keys.java +++ b/java/src/org/openqa/selenium/Keys.java @@ -98,8 +98,16 @@ public enum Keys implements CharSequence { META('\uE03D'), COMMAND(Keys.META), - OPTION('\uE050'), - FN('\uE051'), + + // Extended macOS/ChromeDriver keys (based on observed codes) + RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver + RIGHT_CONTROL('\uE051'), + RIGHT_ALT('\uE052'), + RIGHT_COMMAND('\uE053'), + + // Symbolic macOS keys not in W3C spec (TODO: verify usage) + OPTION('\uE050'), // TODO: verify Unicode value with WebDriver spec + FN('\uE051'), // TODO: verify Unicode value with WebDriver spec ZENKAKU_HANKAKU('\uE040'); @@ -124,7 +132,6 @@ public char charAt(int index) { if (index == 0) { return keyCode; } - return 0; } @@ -138,7 +145,6 @@ public CharSequence subSequence(int start, int end) { if (start == 0 && end == 1) { return String.valueOf(keyCode); } - throw new IndexOutOfBoundsException(); } @@ -147,51 +153,25 @@ public String toString() { return String.valueOf(keyCode); } - /** - * Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings; - * appends each of the values to a string, and adds the chord termination key (Keys.NULL) and - * returns the resultant string. - * - *

Note: When the low-level webdriver key handlers see Keys.NULL, active modifier keys - * (CTRL/ALT/SHIFT/etc) release via a keyup event. - * - * @param value characters to send - * @return String representation of the char sequence - */ public static String chord(CharSequence... value) { return chord(Arrays.asList(value)); } - /** - * @see #chord(CharSequence...) - * @param value characters to send - * @return String representation of the char sequence - */ public static String chord(Iterable value) { StringBuilder builder = new StringBuilder(); - for (CharSequence seq : value) { builder.append(seq); } - builder.append(Keys.NULL); return builder.toString(); } - /** - * Get the special key representation, {@link Keys}, of the supplied character if there is one. If - * there is no special key tied to this character, null will be returned. - * - * @param key unicode character code - * @return special key linked to the character code, or null if character is not a special key - */ public static @Nullable Keys getKeyFromUnicode(char key) { for (Keys unicodeKey : values()) { if (unicodeKey.charAt(0) == key) { return unicodeKey; } } - return null; } } From 58de79a181d67b004a6ee646a71f28cfd28b9f9d Mon Sep 17 00:00:00 2001 From: Manuel Blanco Date: Thu, 19 Jun 2025 15:14:58 +0200 Subject: [PATCH 3/4] [FEAT] Add macOS-specific and ChromeDriver-aligned extended keys - Added RIGHT_SHIFT, RIGHT_CONTROL, RIGHT_ALT, and RIGHT_COMMAND using Unicode PUA codes observed in ChromeDriver. - Included symbolic macOS keys OPTION and FN, marked with TODO comments for future validation against W3C WebDriver spec. - Updated class-level Javadoc to clarify the role of PUA mappings and their interoperability considerations. These additions improve platform representation and lay the groundwork for consistent macOS key handling. --- java/src/org/openqa/selenium/Keys.java | 43 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/java/src/org/openqa/selenium/Keys.java b/java/src/org/openqa/selenium/Keys.java index a42de2d017013..add9f52571aeb 100644 --- a/java/src/org/openqa/selenium/Keys.java +++ b/java/src/org/openqa/selenium/Keys.java @@ -23,13 +23,21 @@ /** * Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private - * Use Area) code points, 0xE000-0xF8FF. + * Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate + * keyboard input where standard Unicode characters are insufficient, such as modifier and control keys. * - * @see http://www.google.com.au/search?&q=unicode+pua&btnK=Search + * The codes follow conventions partially established by the W3C WebDriver specification and the Selenium project. + * Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are not currently part of the W3C spec. + * Others (e.g., OPTION, FN) are symbolic and reserved for possible future mapping. + * + * For consistency across platforms and drivers, values should be verified before assuming native support. + * + * @see W3C WebDriver Keyboard Actions + * @see Unicode PUA Overview */ @NullMarked public enum Keys implements CharSequence { + // Basic control characters NULL('\uE000'), CANCEL('\uE001'), // ^break HELP('\uE002'), @@ -99,15 +107,15 @@ public enum Keys implements CharSequence { META('\uE03D'), COMMAND(Keys.META), - // Extended macOS/ChromeDriver keys (based on observed codes) - RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver + // Extended macOS/ChromeDriver keys (based on observed Chrome usage) + RIGHT_SHIFT('\uE050'), // aligns with ChromeDriver usage RIGHT_CONTROL('\uE051'), RIGHT_ALT('\uE052'), RIGHT_COMMAND('\uE053'), - // Symbolic macOS keys not in W3C spec (TODO: verify usage) + // Symbolic macOS keys not yet standardized OPTION('\uE050'), // TODO: verify Unicode value with WebDriver spec - FN('\uE051'), // TODO: verify Unicode value with WebDriver spec + FN('\uE051'), // TODO: symbolic only; confirm or remove in future ZENKAKU_HANKAKU('\uE040'); @@ -153,10 +161,25 @@ public String toString() { return String.valueOf(keyCode); } + /** + * Simulate pressing many keys at once in a "chord". + * Takes a sequence of Keys.XXXX or strings; appends each to a string, adds the chord termination key (Keys.NULL), and returns it. + * + *

Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events. + * + * @param value characters to send + * @return String representation of the char sequence + */ public static String chord(CharSequence... value) { return chord(Arrays.asList(value)); } + /** + * Overload of {@link #chord(CharSequence...)} that accepts an iterable. + * + * @param value characters to send + * @return String representation of the char sequence + */ public static String chord(Iterable value) { StringBuilder builder = new StringBuilder(); for (CharSequence seq : value) { @@ -166,6 +189,12 @@ public static String chord(Iterable value) { return builder.toString(); } + /** + * Retrieves the {@link Keys} enum constant corresponding to the given Unicode character. + * + * @param key unicode character code + * @return special key linked to the character code, or null if not found + */ public static @Nullable Keys getKeyFromUnicode(char key) { for (Keys unicodeKey : values()) { if (unicodeKey.charAt(0) == key) { From ed719a81334ce118939b4871652a67a558060bec Mon Sep 17 00:00:00 2001 From: Diego Molina Date: Mon, 23 Jun 2025 10:30:39 +0000 Subject: [PATCH 4/4] Format script --- java/src/org/openqa/selenium/Keys.java | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/java/src/org/openqa/selenium/Keys.java b/java/src/org/openqa/selenium/Keys.java index add9f52571aeb..0b729541cb001 100644 --- a/java/src/org/openqa/selenium/Keys.java +++ b/java/src/org/openqa/selenium/Keys.java @@ -24,16 +24,21 @@ /** * Representations of pressable keys that aren't text. These are stored in the Unicode PUA (Private * Use Area) code points, 0xE000–0xF8FF. These values are used internally by WebDriver to simulate - * keyboard input where standard Unicode characters are insufficient, such as modifier and control keys. + * keyboard input where standard Unicode characters are insufficient, such as modifier and control + * keys. * - * The codes follow conventions partially established by the W3C WebDriver specification and the Selenium project. - * Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are not currently part of the W3C spec. - * Others (e.g., OPTION, FN) are symbolic and reserved for possible future mapping. + *

The codes follow conventions partially established by the W3C WebDriver specification and the + * Selenium project. Some values (e.g., RIGHT_SHIFT, RIGHT_COMMAND) are used in ChromeDriver but are + * not currently part of the W3C spec. Others (e.g., OPTION, FN) are symbolic and reserved for + * possible future mapping. * - * For consistency across platforms and drivers, values should be verified before assuming native support. + *

For consistency across platforms and drivers, values should be verified before assuming native + * support. * - * @see W3C WebDriver Keyboard Actions - * @see Unicode PUA Overview + * @see W3C WebDriver Keyboard + * Actions + * @see Unicode PUA + * Overview */ @NullMarked public enum Keys implements CharSequence { @@ -115,7 +120,7 @@ public enum Keys implements CharSequence { // Symbolic macOS keys not yet standardized OPTION('\uE050'), // TODO: verify Unicode value with WebDriver spec - FN('\uE051'), // TODO: symbolic only; confirm or remove in future + FN('\uE051'), // TODO: symbolic only; confirm or remove in future ZENKAKU_HANKAKU('\uE040'); @@ -162,8 +167,8 @@ public String toString() { } /** - * Simulate pressing many keys at once in a "chord". - * Takes a sequence of Keys.XXXX or strings; appends each to a string, adds the chord termination key (Keys.NULL), and returns it. + * Simulate pressing many keys at once in a "chord". Takes a sequence of Keys.XXXX or strings; + * appends each to a string, adds the chord termination key (Keys.NULL), and returns it. * *

Note: Keys.NULL signals release of modifier keys like CTRL/ALT/SHIFT via keyup events. *