Answer "what can I press" in one keypress

The Shortcuts settings page answers "how do I change this", which is
worth opening a window for. This answers the other question, the one
you have with your hands already on the keyboard, so it is an overlay
on SUPER + / and the same key closes it.

It reads Keybinds.grouped() rather than a written-down list, so a
shortcut rebound in Settings shows its new chord here with nothing kept
in sync. A cheatsheet that lies is worse than none: it gets consulted
exactly when somebody does not already know.

Three columns, balanced by how many shortcuts each category holds. The
first attempt used a Flow, which wraps into as many columns as it likes
and made 120 binds across six uneven categories unreadable; it also
sized the card from a child that filled it, which is a circular binding
and produced a card taller than the display with its contents running
off the bottom. Both were found by looking at it rather than by a test,
which is the argument for looking at it.

Fixes a real bug on the way past: luaChord and formatChord appended the
key unconditionally, so the window switcher's modifier-only release
bind became "SUPER + " with a dangling separator. That matched neither
the chord keybinds.lua binds nor the one an override is keyed by, so
that bind could never be rebound and had no category -- it was sitting
in a seventh group of its own, which is how it was noticed.
This commit is contained in:
Gabriel Brown
2026-08-21 23:53:50 -04:00
parent 6ae8265730
commit 9fbbdd902b
12 changed files with 469 additions and 5 deletions
+10 -2
View File
@@ -260,7 +260,14 @@ Singleton {
if ((bind.modmask & modifier.bit) !== 0)
parts.push(modifier.name.toUpperCase());
}
parts.push(String(bind.key ?? ""));
// A modifier-only bind has no key at all -- the window switcher commits
// on Super RELEASE. Appending an empty string left a dangling "SUPER + "
// that matched neither the chord hypr/keybinds.lua binds nor the one an
// override would be keyed by, so that bind could never be rebound and
// never found its category.
const key = String(bind.key ?? "");
if (key !== "")
parts.push(key);
return parts.join(" + ");
}
@@ -271,7 +278,8 @@ Singleton {
parts.push(modifier.name);
}
const key = String(bind.key ?? "");
parts.push(root.keyNames[key] ?? (key.length === 1 ? key.toUpperCase() : key));
if (key !== "")
parts.push(root.keyNames[key] ?? (key.length === 1 ? key.toUpperCase() : key));
return parts.join(" + ");
}
@@ -17,7 +17,7 @@ Singleton {
id: root
// Exactly one of these may be non-empty at a time.
// "" | "overview" | "quicksettings" | "notifications" | "clipboard" | "capture" | "activity" | "powermenu"
// "" | "overview" | "quicksettings" | "notifications" | "clipboard" | "capture" | "activity" | "powermenu" | "cheatsheet"
property string activeOverlay: ""
readonly property bool overviewOpen: activeOverlay === "overview"
@@ -27,6 +27,7 @@ Singleton {
readonly property bool captureOpen: activeOverlay === "capture"
readonly property bool activityOpen: activeOverlay === "activity"
readonly property bool powerMenuOpen: activeOverlay === "powermenu"
readonly property bool cheatsheetOpen: activeOverlay === "cheatsheet"
// Settings is a normal application window rather than a transient overlay.
// It can stay open while Quick Settings or the notification center appears.