ctrl+space opens spotlight, and ctrl+? tells you everything else
Fourth chord for the launcher, and the last move is a return: ctrl-space → shift-space → alt-space → ctrl-space. Every one was the owner naming a real collision, and this one is the interesting direction — alt-space is the GNOME window menu, he rebound the desktop to keep it, disliked what he rebound it to, and would rather move the app than the window manager. ctrl-space was ruled out on 2026-08-20 as "focuses the address bar in Brave". That observation was made before anything preventDefault'ed it, and the trade has changed: rebinding a browser is cheaper than rebinding a desktop. Written down in the file, because if the address bar still wins the key never reaches the handler and nothing in this repository can help — the fix would be in Brave. `!ev.shiftKey && !ev.altKey` matters: ctrl+SHIFT+space is the theme browser, and one chord opening both is the bug that needed a capture-phase listener to fix on the theme side. Verified in the built bundle that the two conditions are disjoint. CTRL+? renders every shortcut from a registry, ported in shape from vimazing's gameInfo.ts — controls declared as data, help screen renders them. Its renderer was a recursive `any` walk, right for a game whose help also carries rules and scoring; here the content is one shape, so the renderer is typed and boring and the value is in state/shortcuts.ts. The registry is deliberately NOT authoritative yet, and says so: the handlers still hold their own conditions, so changing a chord here does not move it. Each entry names the file that implements it, so the pair is one search apart. Making it the source of truth is the configurable-shortcuts work, and doing it now would rewrite three handlers for nothing visible. Also removed a line I put in the theme dropdown yesterday promising "alt+space to search every theme by name". Themes are not Spotlight items — that was an instruction for a feature nobody built, sitting in the UI as though it worked. It now points at ctrl+?, which exists. Two comments naming ctrl+alt+space for the theme browser were corrected to ctrl+shift+space with the older chord noted as still accepted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,12 +11,18 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems';
|
||||
//
|
||||
// ── Keyboard first, and the trigger ──
|
||||
//
|
||||
// `alt-space`, and ONLY that. It went ctrl-space → shift-space → alt-space, and each move was the owner
|
||||
// telling us what the chord actually collides with on the machine he uses:
|
||||
// `ctrl-space`, and ONLY that. It has now been ctrl-space → shift-space → alt-space → ctrl-space, and every
|
||||
// move was the owner naming a real collision on the machine he uses:
|
||||
//
|
||||
// ctrl-space focuses the address bar in Brave
|
||||
// shift-space types a space — see below, this was the real problem
|
||||
// alt-space taken by the window menu, and the owner rebound it rather than give up the chord
|
||||
// shift-space types a space — see below, this was the worst of them
|
||||
// alt-space the GNOME window menu. He rebound the OS to keep it, disliked what he rebound it TO, and
|
||||
// asked for the OS binding back — so the app moves rather than the desktop.
|
||||
// ctrl-space chosen deliberately on the way back. It was ruled out on 2026-08-20 as "focuses the
|
||||
// address bar in Brave"; that observation was made before anything preventDefault'ed it, and
|
||||
// the owner would rather rebind a browser than his window manager.
|
||||
//
|
||||
// If the address bar still steals it, the key never reaches this handler and nothing here can help — the fix
|
||||
// is in Brave, not in this file. Worth knowing WHICH of the two it is before changing anything.
|
||||
//
|
||||
// **Shift-space was never a good choice**, and that is why it did not last a day. It is a real key
|
||||
// combination inside a text field: it types a space, and people hold shift through one more often than
|
||||
@@ -24,7 +30,7 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems';
|
||||
// — which is where focus usually is, the chat composer — so opening Spotlight meant clicking out first.
|
||||
// A launcher you have to prepare for is not a launcher.
|
||||
//
|
||||
// Alt-space has no meaning inside a text field, so there is NO focus check at all. The guard shift-space
|
||||
// Ctrl-space has no meaning inside a text field, so there is NO focus check at all. The guard shift-space
|
||||
// needed was kept for one commit as "belt-and-braces" and was simply the old bug wearing a new hat: focus
|
||||
// is usually in the chat composer, so a launcher that stands down there is a launcher that does not open
|
||||
// when you want it. `preventDefault` on the handler covers the only real risk the guard addressed.
|
||||
@@ -200,15 +206,18 @@ export const Spotlight = () => {
|
||||
// anywhere — including inside a panel that has its own key handling.
|
||||
useEffect(() => {
|
||||
const onKey = (ev: KeyboardEvent) => {
|
||||
// `altKey` and `code`, not `key`: alt-space produces a different `key` on several layouts (and
|
||||
// `ctrlKey` and `code`, not `key`: a modifier+space produces a different `key` on several layouts (and
|
||||
// nothing at all on some), while the physical key is `Space` everywhere.
|
||||
//
|
||||
// `!ev.shiftKey`, because ctrl+SHIFT+space is the theme browser. Without it one chord would open both,
|
||||
// which is the bug that took a capture-phase listener to fix on the theme side.
|
||||
//
|
||||
// No focus check. There was one, inherited from shift-space where it was mandatory, and keeping it
|
||||
// "as belt-and-braces" was wrong in the plainest way: focus is usually IN the chat composer, so the
|
||||
// guard meant the launcher did not open from the place it is most often wanted. `preventDefault`
|
||||
// below covers the only thing the guard was protecting against — a layout that would otherwise type
|
||||
// a character.
|
||||
if (ev.altKey && ev.code === 'Space') {
|
||||
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && ev.code === 'Space') {
|
||||
ev.preventDefault();
|
||||
// Take focus off whatever had it, explicitly, before the overlay mounts. The effect below focuses
|
||||
// this panel's own input, and on paper that is enough — but "on paper" is what produced arrow keys
|
||||
|
||||
Reference in New Issue
Block a user