spotlight on shift+space, overriding both of its stock behaviours
Fifth setting in three days: ctrl-space → shift-space → alt-space → ctrl-space → shift-space. Ctrl-space was tried twice on the theory that preventDefault would beat Brave's address bar. It does not — that binding is at the browser level and the key never reaches the handler. Recorded in the file so it is not tried a third time. Shift-space overrides two stock behaviours deliberately, and the owner's reasoning is the right one: it types a space in a text field, and it scrolls a page UP when nothing has focus. Neither is worth a launcher. Page-up-by-shift-space is a fossil, and typing a space is what the unmodified spacebar is for. The cost is stated once in the file rather than argued again: typing in CAPS by holding shift instead of using caps lock puts a shift-space between every word, which opens the launcher mid-sentence. If that turns out to bite, the fix is a text-field guard — which this had for one day, and which is exactly what made the launcher unopenable from the composer, where it is most wanted. Trading that back would be trading down. Every other modifier must be absent: ctrl+shift+space is the theme browser, and one chord opening both is the bug that needed a capture-phase listener to fix. Verified disjoint in the built bundle, both conditions quoted from it rather than from the source. Five moves in three days is the argument for making chords configurable rather than for choosing better ones, which is why the ctrl+? registry names the implementing file for each. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,18 +11,28 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems';
|
||||
//
|
||||
// ── Keyboard first, and the trigger ──
|
||||
//
|
||||
// `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:
|
||||
// `shift-space`, and ONLY that. Fifth setting: ctrl-space → shift-space → alt-space → ctrl-space →
|
||||
// shift-space. Every move was the owner naming a collision, and by now the list is the useful part:
|
||||
//
|
||||
// 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.
|
||||
// ctrl-space Brave takes it for the address bar, at the browser level. Tried twice, on the theory that
|
||||
// preventDefault would win. It does not — the key never reaches this handler.
|
||||
// alt-space the GNOME window menu. He rebound the desktop to keep it, disliked the replacement, and
|
||||
// would rather move the app than the window manager.
|
||||
// shift-space where it lands, with BOTH of its stock behaviours deliberately overridden.
|
||||
//
|
||||
// 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 overrides two things, on purpose ──
|
||||
//
|
||||
// It types a space in a text field, and it scrolls a page UP when nothing has focus. The owner's judgement,
|
||||
// and it is his to make: neither is worth a launcher. Page-up-by-shift-space is a fossil nobody reaches for,
|
||||
// and typing a space is what the unmodified spacebar is for.
|
||||
//
|
||||
// The cost, stated once because it is the one that will bite: typing in CAPS by holding shift rather than
|
||||
// using caps lock puts a shift-space between every word. That opens the launcher mid-sentence. If it turns
|
||||
// out to be a nuisance, the fix is a guard for text fields only — which this had for a day, and which is
|
||||
// what made the launcher unopenable from the composer, where it is most wanted.
|
||||
//
|
||||
// This is also why the ctrl+? registry names the file that implements each chord: five moves in three days
|
||||
// is the argument for making them configurable, not for choosing better.
|
||||
//
|
||||
// **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
|
||||
@@ -30,7 +40,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.
|
||||
//
|
||||
// Ctrl-space has no meaning inside a text field, so there is NO focus check at all. The guard shift-space
|
||||
// There is NO focus check, and here that is a choice with a cost rather than a free one — see above. 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.
|
||||
@@ -206,18 +216,18 @@ export const Spotlight = () => {
|
||||
// anywhere — including inside a panel that has its own key handling.
|
||||
useEffect(() => {
|
||||
const onKey = (ev: KeyboardEvent) => {
|
||||
// `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.
|
||||
// `code`, not `key`: shift+space reports `key: ' '` on most layouts and something else on a few, 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.
|
||||
// Every other modifier must be ABSENT. `ctrl+shift+space` is the theme browser, and one chord opening
|
||||
// both 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.ctrlKey && !ev.shiftKey && !ev.altKey && ev.code === 'Space') {
|
||||
if (ev.shiftKey && !ev.ctrlKey && !ev.altKey && !ev.metaKey && 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
|
||||
|
||||
@@ -39,7 +39,7 @@ export const SHORTCUT_SECTIONS: ShortcutSection[] = [
|
||||
title: 'Navigation',
|
||||
shortcuts: [
|
||||
{
|
||||
keys: 'Ctrl+Space',
|
||||
keys: 'Shift+Space',
|
||||
description: 'Spotlight — go to any screen, plugin or setting by name',
|
||||
implementedIn: 'Layout/Spotlight/Spotlight.tsx',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user