diff --git a/src/ui/cockpitBridge.test.mjs b/src/ui/cockpitBridge.test.mjs index 3da1d72e5..0eb68022a 100644 --- a/src/ui/cockpitBridge.test.mjs +++ b/src/ui/cockpitBridge.test.mjs @@ -439,6 +439,27 @@ test('C enters the selected vessel bridge and aircraft-only entry refuses it', a assert.equal(event.defaultPrevented, true); }); +test('C stays the CCTV shortcut when the bridge gate is shut', async (t) => { + const { cockpit } = fixture(t, { bridgeAllowed: false }); + let stopped = false; + const event = { + key: 'c', + target: document.body, + defaultPrevented: false, + preventDefault() { + this.defaultPrevented = true; + }, + stopImmediatePropagation() { + stopped = true; + }, + }; + cockpit.onKeyDown(event); + await settle(); + assert.equal(cockpit.active, false); + assert.equal(event.defaultPrevented, false); + assert.equal(stopped, false, 'the application shortcut still sees C'); +}); + test('a slow-frame bridge keeps pace with its ship', async (t) => { // One rendered frame a second, as software rendering manages. The bridge // must still cover the ship's distance, not a capped fraction of it. diff --git a/src/ui/cockpitInput.js b/src/ui/cockpitInput.js index a5c1146c2..227ccb4c7 100644 --- a/src/ui/cockpitInput.js +++ b/src/ui/cockpitInput.js @@ -141,7 +141,18 @@ const LOOK_KEY_OWNERS = [ 'textarea', 'select', '[contenteditable]', + '[role=combobox]', + '[role=grid]', + '[role=menubar]', + '[role=menuitemcheckbox]', + '[role=menuitemradio]', + '[role=scrollbar]', + '[role=searchbox]', '[role=slider]', + '[role=spinbutton]', + '[role=textbox]', + '[role=tree]', + '[role=treeitem]', '[role=tab]', '[role=tablist]', '[role=radio]', @@ -231,13 +242,18 @@ export function onKeyDown(event) { const cockpitAttempt = !!( this.readAircraftInfo() && this.viewer.trackedEntity?.position ); - // With no tracked aircraft, C takes the selected vessel's bridge. - const bridgeAttempt = !cockpitAttempt && !!this.readVesselInfo(); + // With no tracked aircraft, C takes the selected vessel's bridge, but + // only when the bridge can be entered: otherwise C stays the CCTV + // shortcut, as it is with nothing selected. + const bridgeAttempt = + !cockpitAttempt && + !!this.readVesselInfo() && + this.isBridgeEntryAllowed(); if (!cockpitAttempt && !bridgeAttempt) return; if (bridgeAttempt) { event.preventDefault(); event.stopImmediatePropagation(); - if (this.isBridgeEntryAllowed()) this.enter({ kind: 'vessel' }); + this.enter({ kind: 'vessel' }); return; } }