keysyms: Add missing evdev keys

- Keys from Linux ≤ 2.6.11. Most are TODOs made explicit.
- Add `XF86XK_MonBrightnessAuto` and make `XF86XK_BrightnessAuto` its
  deprecated alias, for consistency with `XF86XK_BrightnessMin`
- Add `XF86XK_LinkPhone` from Linux 6.14
- Add `XF86XK_PerformanceMode" from Linux 6.17
- Fix and improve the keysym generator script

Co-authored-by: Pierre Le Marre <dev@wismill.eu>
Co-authored-by: Kai Uwe Broulik <kde@privat.broulik.de>
Part-of: <https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/103>
This commit is contained in:
Pierre Le Marre 2025-09-26 11:12:58 +02:00
parent 57a10982c1
commit 81931cc0fd
2 changed files with 108 additions and 17 deletions

View file

@ -295,10 +295,68 @@
*/ */
#define _EVDEVK(_v) (0x10081000 + _v) #define _EVDEVK(_v) (0x10081000 + _v)
/* Use: XF86XK_Eject _EVDEVK(0x0a2) KEY_EJECTCLOSECD */ /* Use: XF86XK_Eject _EVDEVK(0x0a2) KEY_EJECTCLOSECD */
/* TODO: Use XF86XK_AudioNext? _EVDEVK(0x0a3) KEY_NEXTSONG */
/* TODO: XF86XK_MediaPlayPause? _EVDEVK(0x0a4) KEY_PLAYPAUSE */
/* TODO: Use XF86XK_AudioPrev? _EVDEVK(0x0a5) KEY_PREVIOUSSONG */
/* TODO: Use XF86XK_AudioStop? _EVDEVK(0x0a6) KEY_STOPCD */
/* TODO: Use XF86XK_AudioRecord? _EVDEVK(0x0a7) KEY_RECORD */
/* TODO: Use XF86XK_AudioRewind? _EVDEVK(0x0a8) KEY_REWIND */
/* Use: XF86XK_Phone _EVDEVK(0x0a9) KEY_PHONE */
/* TODO: unclear function _EVDEVK(0x0aa) KEY_ISO */
/* TODO: unclear function _EVDEVK(0x0ab) KEY_CONFIG */
/* Use: XF86XK_HomePage _EVDEVK(0x0ac) KEY_HOMEPAGE */
/* Use: XF86XK_Refresh _EVDEVK(0x0ad) KEY_REFRESH */
/* TODO: unclear function _EVDEVK(0x0ae) KEY_EXIT */
/* TODO: unclear function _EVDEVK(0x0af) KEY_MOVE */
/* TODO: unclear function _EVDEVK(0x0b0) KEY_EDIT */
/* Use: XF86XK_ScrollUp _EVDEVK(0x0b1) KEY_SCROLLUP */
/* Use: XF86XK_ScrollDown _EVDEVK(0x0b2) KEY_SCROLLDOWN */
/* NOTE: Unless there are special actions bound to the keys KEY_KPLEFTPAREN and
* KEY_KPRIGHTPAREN, there is no reason to introduce keypad-specific keysyms */
/* Use: XK_parenleft _EVDEVK(0x0b3) KEY_KPLEFTPAREN */
/* Use: XK_parenright _EVDEVK(0x0b4) KEY_KPRIGHTPAREN */
/* Use: XF86XK_New _EVDEVK(0x0b5) v2.6.14 KEY_NEW */ /* Use: XF86XK_New _EVDEVK(0x0b5) v2.6.14 KEY_NEW */
/* Use: XK_Redo _EVDEVK(0x0b6) v2.6.14 KEY_REDO */ /* Use: XK_Redo _EVDEVK(0x0b6) v2.6.14 KEY_REDO */
/* KEY_DASHBOARD has been mapped to LaunchB in xkeyboard-config since 2011 */ /* Use: XK_F13 _EVDEVK(0x0b7) KEY_F13 */
/* Use: XK_F14 _EVDEVK(0x0b8) KEY_F14 */
/* Use: XK_F15 _EVDEVK(0x0b9) KEY_F15 */
/* Use: XK_F16 _EVDEVK(0x0ba) KEY_F16 */
/* Use: XK_F17 _EVDEVK(0x0bb) KEY_F17 */
/* Use: XK_F18 _EVDEVK(0x0bc) KEY_F18 */
/* Use: XK_F19 _EVDEVK(0x0bd) KEY_F19 */
/* Use: XK_F20 _EVDEVK(0x0be) KEY_F20 */
/* Use: XK_F21 _EVDEVK(0x0bf) KEY_F21 */
/* Use: XK_F22 _EVDEVK(0x0c0) KEY_F22 */
/* Use: XK_F23 _EVDEVK(0x0c1) KEY_F23 */
/* Use: XK_F24 _EVDEVK(0x0c2) KEY_F24 */
/* TODO: Use XF86XK_AudioPlay? _EVDEVK(0x0c8) KEY_PLAYCD */
/* TODO: Use XF86XK_AudioPause? _EVDEVK(0x0c9) KEY_PAUSECD */
/* Use: XF86XK_Launch3 _EVDEVK(0x0ca) KEY_PROG3 */
/* Use: XF86XK_Launch4 _EVDEVK(0x0cb) KEY_PROG4 */
/* NOTE: KEY_DASHBOARD has been mapped to LaunchB in xkeyboard-config since 2011 */
/* Use: XF86XK_LaunchB _EVDEVK(0x0cc) v2.6.28 KEY_DASHBOARD */ /* Use: XF86XK_LaunchB _EVDEVK(0x0cc) v2.6.28 KEY_DASHBOARD */
/* Use: XF86XK_Suspend _EVDEVK(0x0cd) KEY_SUSPEND */
/* Use: XF86XK_Close _EVDEVK(0x0ce) KEY_CLOSE */
/* TODO: Use XF86XK_AudioPlay? _EVDEVK(0x0cf) KEY_PLAY */
/* TODO: Use XF86XK_AudioForward? _EVDEVK(0x0d0) KEY_FASTFORWARD */
/* TODO: XF86XK_AudioBassBoost? _EVDEVK(0x0d1) KEY_BASSBOOST */
/* Use: XK_Print _EVDEVK(0x0d2) KEY_PRINT */
/* TODO: headphone or vendor key? _EVDEVK(0x0d3) KEY_HP */
/* Use: XF86XK_WebCam _EVDEVK(0x0d4) KEY_CAMERA */
/* TODO: unclear function _EVDEVK(0x0d5) KEY_SOUND */
/* TODO: unclear function _EVDEVK(0x0d6) KEY_QUESTION */
/* Use: XF86XK_Mail _EVDEVK(0x0d7) KEY_EMAIL */
/* Use: XF86XK_Messenger _EVDEVK(0x0d8) KEY_CHAT */
/* Use: XF86XK_Search _EVDEVK(0x0d9) KEY_SEARCH */
/* TODO: unclear function _EVDEVK(0x0da) KEY_CONNECT */
/* Use: XF86XK_Finance _EVDEVK(0x0db) KEY_FINANCE */
#define XF86XK_Sport _EVDEVK(0x0dc) /* KEY_SPORT */
/* Use: XF86XK_Shop _EVDEVK(0x0dd) KEY_SHOP */
/* TODO: unclear function _EVDEVK(0x0de) KEY_ALTERASE */
/* Use: XK_Cancel _EVDEVK(0x0df) KEY_CANCEL */
/* Use: XF86XK_MonBrightnessDown _EVDEVK(0x0e0) KEY_BRIGHTNESSDOWN */
/* Use: XF86XK_MonBrightnessUp _EVDEVK(0x0e1) KEY_BRIGHTNESSUP */
/* Use: XF86XK_AudioMedia _EVDEVK(0x0e2) KEY_MEDIA */
/* Use: XF86XK_Display _EVDEVK(0x0e3) v2.6.12 KEY_SWITCHVIDEOMODE */ /* Use: XF86XK_Display _EVDEVK(0x0e3) v2.6.12 KEY_SWITCHVIDEOMODE */
/* Use: XF86XK_KbdLightOnOff _EVDEVK(0x0e4) v2.6.12 KEY_KBDILLUMTOGGLE */ /* Use: XF86XK_KbdLightOnOff _EVDEVK(0x0e4) v2.6.12 KEY_KBDILLUMTOGGLE */
/* Use: XF86XK_KbdBrightnessDown _EVDEVK(0x0e5) v2.6.12 KEY_KBDILLUMDOWN */ /* Use: XF86XK_KbdBrightnessDown _EVDEVK(0x0e5) v2.6.12 KEY_KBDILLUMDOWN */
@ -312,10 +370,12 @@
/* Use: XF86XK_Bluetooth _EVDEVK(0x0ed) v2.6.19 KEY_BLUETOOTH */ /* Use: XF86XK_Bluetooth _EVDEVK(0x0ed) v2.6.19 KEY_BLUETOOTH */
/* Use: XF86XK_WLAN _EVDEVK(0x0ee) v2.6.19 KEY_WLAN */ /* Use: XF86XK_WLAN _EVDEVK(0x0ee) v2.6.19 KEY_WLAN */
/* Use: XF86XK_UWB _EVDEVK(0x0ef) v2.6.24 KEY_UWB */ /* Use: XF86XK_UWB _EVDEVK(0x0ef) v2.6.24 KEY_UWB */
/* Use: NoSymbol _EVDEVK(0x0f0) KEY_UNKNOWN */
/* Use: XF86XK_Next_VMode _EVDEVK(0x0f1) v2.6.23 KEY_VIDEO_NEXT */ /* Use: XF86XK_Next_VMode _EVDEVK(0x0f1) v2.6.23 KEY_VIDEO_NEXT */
/* Use: XF86XK_Prev_VMode _EVDEVK(0x0f2) v2.6.23 KEY_VIDEO_PREV */ /* Use: XF86XK_Prev_VMode _EVDEVK(0x0f2) v2.6.23 KEY_VIDEO_PREV */
/* Use: XF86XK_MonBrightnessCycle _EVDEVK(0x0f3) v2.6.23 KEY_BRIGHTNESS_CYCLE */ /* Use: XF86XK_MonBrightnessCycle _EVDEVK(0x0f3) v2.6.23 KEY_BRIGHTNESS_CYCLE */
#define XF86XK_BrightnessAuto _EVDEVK(0x0f4) /* v3.16 KEY_BRIGHTNESS_AUTO */ #define XF86XK_BrightnessAuto _EVDEVK(0x0f4) /* Deprecated alias for XF86XK_MonBrightnessAuto */
#define XF86XK_MonBrightnessAuto _EVDEVK(0x0f4) /* v3.16 KEY_BRIGHTNESS_AUTO */
#define XF86XK_DisplayOff _EVDEVK(0x0f5) /* v2.6.23 KEY_DISPLAY_OFF */ #define XF86XK_DisplayOff _EVDEVK(0x0f5) /* v2.6.23 KEY_DISPLAY_OFF */
/* Use: XF86XK_WWAN _EVDEVK(0x0f6) v3.13 KEY_WWAN */ /* Use: XF86XK_WWAN _EVDEVK(0x0f6) v3.13 KEY_WWAN */
/* Use: XF86XK_RFKill _EVDEVK(0x0f7) v2.6.33 KEY_RFKILL */ /* Use: XF86XK_RFKill _EVDEVK(0x0f7) v2.6.33 KEY_RFKILL */
@ -415,8 +475,32 @@
#define XF86XK_NotificationCenter _EVDEVK(0x1bc) /* v5.10 KEY_NOTIFICATION_CENTER */ #define XF86XK_NotificationCenter _EVDEVK(0x1bc) /* v5.10 KEY_NOTIFICATION_CENTER */
#define XF86XK_PickupPhone _EVDEVK(0x1bd) /* v5.10 KEY_PICKUP_PHONE */ #define XF86XK_PickupPhone _EVDEVK(0x1bd) /* v5.10 KEY_PICKUP_PHONE */
#define XF86XK_HangupPhone _EVDEVK(0x1be) /* v5.10 KEY_HANGUP_PHONE */ #define XF86XK_HangupPhone _EVDEVK(0x1be) /* v5.10 KEY_HANGUP_PHONE */
#define XF86XK_LinkPhone _EVDEVK(0x1bf) /* v6.14 KEY_LINK_PHONE */
/* TODO: XF86XK_DeleteToEndOfLine? _EVDEVK(0x1c0) KEY_DEL_EOL */
/* TODO: XF86XK_DeleteToEndOfScreen? _EVDEVK(0x1c1) KEY_DEL_EOS */
/* TODO: XF86XK_InsertLine? _EVDEVK(0x1c2) KEY_INS_LINE */
/* TODO: XF86XK_DeleteLine? _EVDEVK(0x1c3) KEY_DEL_LINE */
#define XF86XK_Fn _EVDEVK(0x1d0) /* KEY_FN */ #define XF86XK_Fn _EVDEVK(0x1d0) /* KEY_FN */
#define XF86XK_Fn_Esc _EVDEVK(0x1d1) /* KEY_FN_ESC */ #define XF86XK_Fn_Esc _EVDEVK(0x1d1) /* KEY_FN_ESC */
#define XF86XK_Fn_F1 _EVDEVK(0x1d2) /* KEY_FN_F1 */
#define XF86XK_Fn_F2 _EVDEVK(0x1d3) /* KEY_FN_F2 */
#define XF86XK_Fn_F3 _EVDEVK(0x1d4) /* KEY_FN_F3 */
#define XF86XK_Fn_F4 _EVDEVK(0x1d5) /* KEY_FN_F4 */
#define XF86XK_Fn_F5 _EVDEVK(0x1d6) /* KEY_FN_F5 */
#define XF86XK_Fn_F6 _EVDEVK(0x1d7) /* KEY_FN_F6 */
#define XF86XK_Fn_F7 _EVDEVK(0x1d8) /* KEY_FN_F7 */
#define XF86XK_Fn_F8 _EVDEVK(0x1d9) /* KEY_FN_F8 */
#define XF86XK_Fn_F9 _EVDEVK(0x1da) /* KEY_FN_F9 */
#define XF86XK_Fn_F10 _EVDEVK(0x1db) /* KEY_FN_F10 */
#define XF86XK_Fn_F11 _EVDEVK(0x1dc) /* KEY_FN_F11 */
#define XF86XK_Fn_F12 _EVDEVK(0x1dd) /* KEY_FN_F12 */
#define XF86XK_Fn_1 _EVDEVK(0x1de) /* KEY_FN_1 */
#define XF86XK_Fn_2 _EVDEVK(0x1df) /* KEY_FN_2 */
#define XF86XK_Fn_D _EVDEVK(0x1e0) /* KEY_FN_D */
#define XF86XK_Fn_E _EVDEVK(0x1e1) /* KEY_FN_E */
#define XF86XK_Fn_F _EVDEVK(0x1e2) /* KEY_FN_F */
#define XF86XK_Fn_S _EVDEVK(0x1e3) /* KEY_FN_S */
#define XF86XK_Fn_B _EVDEVK(0x1e4) /* KEY_FN_B */
#define XF86XK_FnRightShift _EVDEVK(0x1e5) /* v5.10 KEY_FN_RIGHT_SHIFT */ #define XF86XK_FnRightShift _EVDEVK(0x1e5) /* v5.10 KEY_FN_RIGHT_SHIFT */
/* Use: XK_braille_dot_1 _EVDEVK(0x1f1) v2.6.17 KEY_BRL_DOT1 */ /* Use: XK_braille_dot_1 _EVDEVK(0x1f1) v2.6.17 KEY_BRL_DOT1 */
/* Use: XK_braille_dot_2 _EVDEVK(0x1f2) v2.6.17 KEY_BRL_DOT2 */ /* Use: XK_braille_dot_2 _EVDEVK(0x1f2) v2.6.17 KEY_BRL_DOT2 */
@ -563,4 +647,5 @@
#define XF86XK_KbdLcdMenu3 _EVDEVK(0x2ba) /* v5.5 KEY_KBD_LCD_MENU3 */ #define XF86XK_KbdLcdMenu3 _EVDEVK(0x2ba) /* v5.5 KEY_KBD_LCD_MENU3 */
#define XF86XK_KbdLcdMenu4 _EVDEVK(0x2bb) /* v5.5 KEY_KBD_LCD_MENU4 */ #define XF86XK_KbdLcdMenu4 _EVDEVK(0x2bb) /* v5.5 KEY_KBD_LCD_MENU4 */
#define XF86XK_KbdLcdMenu5 _EVDEVK(0x2bc) /* v5.5 KEY_KBD_LCD_MENU5 */ #define XF86XK_KbdLcdMenu5 _EVDEVK(0x2bc) /* v5.5 KEY_KBD_LCD_MENU5 */
#define XF86XK_PerformanceMode _EVDEVK(0x2bd) /* v6.17 KEY_PERFORMANCE */
#undef _EVDEVK #undef _EVDEVK

View file

@ -42,12 +42,12 @@ def die(msg):
sys.exit(1) sys.exit(1)
def all_keysyms(directory): def all_keysyms(directory) -> set[str]:
""" """
Extract the key names for all keysyms we have in our repo and return Extract the key names for all keysyms we have in our repo and return
them as list. them as list.
""" """
keysym_names = [] keysym_names: set[str] = set()
pattern = re.compile( pattern = re.compile(
r"^#define\s+(?P<name>\w+)\s+(0x[0-9A-Fa-f]+|_EVDEVK\(0x([0-9A-Fa-f]{3}))" r"^#define\s+(?P<name>\w+)\s+(0x[0-9A-Fa-f]+|_EVDEVK\(0x([0-9A-Fa-f]{3}))"
) )
@ -56,7 +56,7 @@ def all_keysyms(directory):
for line in fd: for line in fd:
match = re.match(pattern, line) match = re.match(pattern, line)
if match: if match:
keysym_names.append(match.group("name")) keysym_names.add(match.group("name"))
return keysym_names return keysym_names
@ -193,11 +193,12 @@ def verify(ns):
expected_pattern = re.compile( expected_pattern = re.compile(
r"#define XF86XK_\w+ +_EVDEVK\(0x([0-9A-Fa-f]{3})\) +" r"#define XF86XK_\w+ +_EVDEVK\(0x([0-9A-Fa-f]{3})\) +"
r"/\* (?:(?P<kernel_version>v[2-6]\.[0-9]+(\.[0-9]+)?)? +KEY_\w+|" r"/\* (?:(?P<kernel_version>v[2-6]\.[0-9]+(\.[0-9]+)?)? +KEY_\w+|"
r"(?P<alias>Alias for XF86XK_\w+)) \*/" r"(?P<alias>(?:Deprecated a|A)lias for XF86XK_\w+)) \*/"
) )
# This is the comment pattern we expect # This is the comment pattern we expect
expected_comment_pattern = re.compile( expected_comment_pattern = re.compile(
r"/\* Use: (?P<name>\w+) +_EVDEVK\(0x(?P<value>[0-9A-Fa-f]{3})\) + " r"/\* (?:Use: (?P<name>\w+)|NOTE.+|TODO.*) +"
r"_EVDEVK\(0x(?P<value>[0-9A-Fa-f]{3})\) + "
r"(v[2-6]\.[0-9]+(\.[0-9]+)?)? +KEY_\w+ \*/" r"(v[2-6]\.[0-9]+(\.[0-9]+)?)? +KEY_\w+ \*/"
) )
@ -206,9 +207,10 @@ def verify(ns):
name_pattern = re.compile(r"#define (XF86XK_[^\s]*)") name_pattern = re.compile(r"#define (XF86XK_[^\s]*)")
space_check = re.compile(r"#define \w+(\s+)[^\s]+(\s+)") space_check = re.compile(r"#define \w+(\s+)[^\s]+(\s+)")
hex_pattern = re.compile(r".*0x([a-f0-9]+).*", re.I) hex_pattern = re.compile(r".*0x([a-f0-9]+).*", re.I)
todo_pattern = re.compile(r"^/\* TODO.*\*/$") todo_pattern = re.compile(r"^/\* (TODO|NOTE).*\*/$")
comment_format = re.compile( comment_format = re.compile(
r".*/\* (?:(?:Deprecated a|A)lias for (\w+)|([^\s]+)?\s+(\w+))" r".*/\* (?:(?:Deprecated a|A)lias for (?P<alias>\w+)|"
r"(?P<version>[^\s]+)?\s+(?P<key>\w+))"
) )
kver_format = re.compile(r"v[2-6]\.[0-9]+(\.[0-9]+)?") kver_format = re.compile(r"v[2-6]\.[0-9]+(\.[0-9]+)?")
alias_format = re.compile(r"(?:Deprecated a|A)lias for XF86XK_\w+") alias_format = re.compile(r"(?:Deprecated a|A)lias for XF86XK_\w+")
@ -220,6 +222,8 @@ def verify(ns):
all_defines = [] all_defines = []
all_keysym_names = all_keysyms(ns.header.parent) all_keysym_names = all_keysyms(ns.header.parent)
# NoSymbol is define in another header
all_keysym_names.add("NoSymbol")
class ParserError(Exception): class ParserError(Exception):
pass pass
@ -228,6 +232,7 @@ def verify(ns):
raise ParserError(f"{msg} in '{line.strip()}'") raise ParserError(f"{msg} in '{line.strip()}'")
last_keycode = 0 last_keycode = 0
last_alias = False
for line in open(ns.header): for line in open(ns.header):
try: try:
if not in_evdev_codes_section: if not in_evdev_codes_section:
@ -263,9 +268,9 @@ def verify(ns):
error("Duplicate keycode", line) error("Duplicate keycode", line)
last_keycode = keycode last_keycode = keycode
name = match.group("name") if name := match.group("name"):
if name not in all_keysym_names: if name not in all_keysym_names:
error(f"Unknown keysym {name}", line) error(f"Unknown keysym {name}", line)
elif re.match(hex_pattern, line) and not todo_pattern.match(line): elif re.match(hex_pattern, line) and not todo_pattern.match(line):
logger.warning(f"Unexpected hex code in {line}") logger.warning(f"Unexpected hex code in {line}")
continue continue
@ -298,7 +303,7 @@ def verify(ns):
comment = re.match(comment_format, line) comment = re.match(comment_format, line)
if not comment: if not comment:
error("Invalid comment format", line) error("Invalid comment format", line)
if alias_target := comment.group(1): if alias_target := comment.group("alias"):
alias = True alias = True
else: else:
alias = False alias = False
@ -322,7 +327,7 @@ def verify(ns):
keycode = int(match.group(1), 16) keycode = int(match.group(1), 16)
if keycode < last_keycode: if keycode < last_keycode:
error("Keycode must be ascending", line) error("Keycode must be ascending", line)
if keycode == last_keycode and not alias: if keycode == last_keycode and not (alias or last_keycode):
error("Duplicate keycode", line) error("Duplicate keycode", line)
# May cause a false positive for old libevdev if KEY_MAX is bumped # May cause a false positive for old libevdev if KEY_MAX is bumped
@ -330,6 +335,7 @@ def verify(ns):
error("Keycode outside range", line) error("Keycode outside range", line)
last_keycode = keycode last_keycode = keycode
last_alias = alias
except ParserError as e: except ParserError as e:
logger.error(e) logger.error(e)
success = False success = False
@ -359,13 +365,13 @@ def add_keysyms(ns):
# 3-digit hexcode in brackets and use that as keycode. # 3-digit hexcode in brackets and use that as keycode.
pattern = re.compile(r".*_EVDEVK\((0x[0-9A-Fa-f]{3})\).*") pattern = re.compile(r".*_EVDEVK\((0x[0-9A-Fa-f]{3})\).*")
max_code = max( max_code = max(
[ (
c.value c.value
for c in libevdev.EV_KEY.codes for c in libevdev.EV_KEY.codes
if c.is_defined if c.is_defined
and c != libevdev.EV_KEY.KEY_MAX and c != libevdev.EV_KEY.KEY_MAX
and not c.name.startswith("BTN") and not c.name.startswith("BTN")
] )
) )
def defined_keycodes(path): def defined_keycodes(path):
@ -386,7 +392,7 @@ def add_keysyms(ns):
else: else:
if re.match(r"#undef _EVDEVK\n", line): if re.match(r"#undef _EVDEVK\n", line):
in_evdev_codes_section = False in_evdev_codes_section = False
yield max_code yield max_code + 1 # Upper bound of range()
else: else:
match = re.match(pattern, line) match = re.match(pattern, line)
if match: if match: