VR keyboard: Fn key on layouts without AltGr

US, Dvorak, Colemak, Bulgarian, Chinese, Japanese and Korean have no AltGr
key, so AltGr + Delete and the AltGr arrows were unreachable. They get
Steam's own AltGr toggle key, labelled Fn, right of the space bar like
German AltGr.
This commit is contained in:
Pierre Kisters committed 2026-09-28 04:18:09 +02:00
1 parent 971ba3d489
commit 7cfe78aed0
2 files changed
+13 -2

No files matched your search

+3
View File
@@ -463,6 +463,9 @@ reboot or Steam restart needed.
labelled like Steam's Delete key in its language (`Entf`; `Del` if that is labelled like Steam's Delete key in its language (`Entf`; `Del` if that is
longer), hinted on the key without AltGr; repeats while held. Layouts with longer), hinted on the key without AltGr; repeats while held. Layouts with
an AltGr character on that key get none. an AltGr character on that key get none.
- Layouts without AltGr (US, Dvorak, Colemak, Bulgarian, Chinese, Japanese,
Korean) get an `Fn` key right of the space bar: Steam's AltGr toggle
(tap: once, tap twice: locked, hold), for Delete and Home/End/Page Up/Down.
- Ctrl/Alt chords and Esc are sent with `xdotool key` on `:0` (focus follows - Ctrl/Alt chords and Esc are sent with `xdotool key` on `:0` (focus follows
the VR-selected window); a toggled Ctrl/Alt is held down while the the VR-selected window); a toggled Ctrl/Alt is held down while the
keyboard is open (e.g. Ctrl+scroll). keyboard is open (e.g. Ctrl+scroll).
+10 -2
View File
@@ -3,7 +3,8 @@
// - bottom row: Esc Ctrl Alt [space] AltGr ← ↑ ↓ → Close, stable with Shift // - bottom row: Esc Ctrl Alt [space] AltGr ← ↑ ↓ → Close, stable with Shift
// and AltGr; AltGr + arrows = Pos1/PgUp/PgDn/End // and AltGr; AltGr + arrows = Pos1/PgUp/PgDn/End
// - AltGr + the key left of Backspace (German ´/`, empty on AltGr) = Delete // - AltGr + the key left of Backspace (German ´/`, empty on AltGr) = Delete
// (Steam's "#Key_Delete" label, e.g. Entf), repeating while held // (Steam's "#Key_Delete" label, e.g. Entf), repeating while held; layouts
// without AltGr (US, ...) get Steam's AltGr key labelled Fn
// - Ctrl/Alt chords, Esc, the AltGr arrow keys and Shift+arrows are pressed // - Ctrl/Alt chords, Esc, the AltGr arrow keys and Shift+arrows are pressed
// for real (Steam can't: in VR SteamClient.Input.ControllerKeyboardSetKeyState // for real (Steam can't: in VR SteamClient.Input.ControllerKeyboardSetKeyState
// throws "Unknown method") // throws "Unknown method")
@@ -21,7 +22,7 @@
// mkPatch patch (see lib/default.nix); no options. On a signature mismatch // mkPatch patch (see lib/default.nix); no options. On a signature mismatch
// it returns an error and changes nothing. Idempotent. // it returns an error and changes nothing. Idempotent.
((find, sigs) => { ((find, sigs) => {
const VERSION = 19; const VERSION = 20;
const send = (msg) => window.__vrkbdKey && window.__vrkbdKey(msg); const send = (msg) => window.__vrkbdKey && window.__vrkbdKey(msg);
let mods; let mods;
try { try {
@@ -62,13 +63,20 @@
.map((a, i) => [{ ...a, type: HALF }, null, ALTGR_ARROWS[i]]); .map((a, i) => [{ ...a, type: HALF }, null, ALTGR_ARROWS[i]]);
const first = (x) => (Array.isArray(x) ? x.find((y) => y) : x); const first = (x) => (Array.isArray(x) ? x.find((y) => y) : x);
const isArrow = (x) => (Array.isArray(x) ? x : [x]).some((y) => y?.key?.startsWith?.('Arrow')); const isArrow = (x) => (Array.isArray(x) ? x : [x]).some((y) => y?.key?.startsWith?.('Arrow'));
// Layouts without AltGr (Steam's bottom row without it: US, Dvorak,
// Colemak, Bulgarian, Chinese, Japanese, Korean) get Steam's own AltGr
// toggle key, labelled Fn, where German has AltGr (right of the space bar):
// same one-shot/locked/held semantics, AltGr layer, Delete, arrow keys.
const FN = { key: 'AltGr', label: 'Fn', type: 4 }; // type Meta, like Steam's AltGr key
const bottomRow = (row) => { const bottomRow = (row) => {
const out = []; const out = [];
const hasAltGr = row.some((x) => (Array.isArray(x) ? x : [x]).some((y) => y?.key === 'AltGr'));
for (const x of row) { for (const x of row) {
const key = first(x); const key = first(x);
if (!key || isArrow(x)) continue; if (!key || isArrow(x)) continue;
if (key.key === ' ') out.push(...MODS.map(same)); if (key.key === ' ') out.push(...MODS.map(same));
out.push(same(key)); out.push(same(key));
if (key.key === ' ' && !hasAltGr) out.push(same(FN));
} }
out.splice(out.length - 1, 0, ...ARROWS); // before Close/Done (last entry) out.splice(out.length - 1, 0, ...ARROWS); // before Close/Done (last entry)
return out; return out;