WM: support the "Hyper" modifier key on Linux

Add support for a 5th modifier key called "hyper",
this is a modifier supported on Wayland & X11 although
other platforms could support an additional modifier too.

Both GNOME and KDE can map CapsLock to Hyper.
Other compositors can use the XKB_DEFAULT_OPTIONS environment variable.

This allows users to have an additional modifier for their own use
that doesn't conflict with other keys.

Ref !136340
This commit is contained in:
Campbell Barton 2025-03-25 23:32:41 +00:00
parent 241f626015
commit 5e2b421996
34 changed files with 258 additions and 30 deletions

View file

@ -47,7 +47,7 @@ def kmi_args_as_data(kmi):
if kmi.any:
s.append("\"any\": True")
else:
for attr in ("shift", "ctrl", "alt", "oskey"):
for attr in ("shift", "ctrl", "alt", "oskey", "hyper"):
if mod := getattr(kmi, attr):
s.append(f"\"{attr:s}\": " + ("-1" if mod == -1 else "True"))
if (mod := kmi.key_modifier) and (mod != 'NONE'):

View file

@ -24,6 +24,7 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
("ctrl", False),
("alt", False),
("oskey", False),
("hyper", False),
("key_modifier", 'NONE'),
):
val = getattr(kmi, attr)

View file

@ -201,6 +201,11 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
subrow.prop(kmi, "alt_ui", toggle=True)
subrow.prop(kmi, "oskey_ui", text="Cmd", toggle=True)
# On systems that don't support Hyper, only show if it's enabled.
# Otherwise the user may have a key binding that doesn't work and can't be changed.
if _platform_supports_hyper_key() or kmi.hyper == 1:
subrow.prop(kmi, "hyper_ui", text="Hyper", toggle=True)
subrow.prop(kmi, "key_modifier", text="", event=True)
# Operator properties
@ -218,6 +223,16 @@ _EVENT_TYPES = set()
_EVENT_TYPE_MAP = {}
_EVENT_TYPE_MAP_EXTRA = {}
_HAS_HYPER_KEY = None
def _platform_supports_hyper_key():
global _HAS_HYPER_KEY
if _HAS_HYPER_KEY is None:
from _bpy import _ghost_backend
_HAS_HYPER_KEY = _ghost_backend() in {'WAYLAND', 'X11'}
return _HAS_HYPER_KEY
def draw_filtered(display_keymaps, filter_type, filter_text, layout):
@ -259,6 +274,7 @@ def draw_filtered(display_keymaps, filter_type, filter_text, layout):
"alt": "alt",
"shift": "shift",
"oskey": "oskey",
"hyper": "hyper",
"any": "any",
# macOS specific modifiers names