authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-15 17:02:38-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-15 17:06:16-08:00
logf864ef189d5def4cb2ae3f34cc461f13b3fc5a00
tree16da86ed68283ca70a1a1019af82a6d92be57abe
parent765f4cd00bb05b4111f1279a8dac47b36665fccd

Ignore non-keydown terminal shortcuts

- guard terminal clear/navigation shortcut handlers to only process `keydown` - add tests verifying `keyup` events are ignored

2 files changed, 22 insertions(+), 0 deletions(-)

apps/web/src/keybindings.test.ts+13
...@@ -325,6 +325,10 @@ describe("isTerminalClearShortcut", () => {...@@ -325,6 +325,10 @@ describe("isTerminalClearShortcut", () => {
325 it("matches Cmd+K on macOS", () => {325 it("matches Cmd+K on macOS", () => {
326 assert.isTrue(isTerminalClearShortcut(event({ key: "k", metaKey: true }), "MacIntel"));326 assert.isTrue(isTerminalClearShortcut(event({ key: "k", metaKey: true }), "MacIntel"));
327 });327 });
328
329 it("ignores non-keydown events", () => {
330 assert.isFalse(isTerminalClearShortcut(event({ type: "keyup", key: "l", ctrlKey: true }), "Linux"));
331 });
328});332});
329333
330describe("terminalNavigationShortcutData", () => {334describe("terminalNavigationShortcutData", () => {
...@@ -371,6 +375,15 @@ describe("terminalNavigationShortcutData", () => {...@@ -371,6 +375,15 @@ describe("terminalNavigationShortcutData", () => {
371 assert.isNull(terminalNavigationShortcutData(event({ key: "ArrowLeft", metaKey: true }), "Linux"));375 assert.isNull(terminalNavigationShortcutData(event({ key: "ArrowLeft", metaKey: true }), "Linux"));
372 assert.isNull(terminalNavigationShortcutData(event({ key: "a", altKey: true }), "MacIntel"));376 assert.isNull(terminalNavigationShortcutData(event({ key: "a", altKey: true }), "MacIntel"));
373 });377 });
378
379 it("ignores non-keydown events", () => {
380 assert.isNull(
381 terminalNavigationShortcutData(
382 event({ type: "keyup", key: "ArrowLeft", altKey: true }),
383 "MacIntel",
384 ),
385 );
386 });
374});387});
375388
376describe("plus key parsing", () => {389describe("plus key parsing", () => {
apps/web/src/keybindings.ts+9
...@@ -7,6 +7,7 @@ import {...@@ -7,6 +7,7 @@ import {
7import { isMacPlatform } from "./lib/utils";7import { isMacPlatform } from "./lib/utils";
88
9export interface ShortcutEventLike {9export interface ShortcutEventLike {
10 type?: string;
10 key: string;11 key: string;
11 metaKey: boolean;12 metaKey: boolean;
12 ctrlKey: boolean;13 ctrlKey: boolean;
...@@ -209,6 +210,10 @@ export function isTerminalClearShortcut(...@@ -209,6 +210,10 @@ export function isTerminalClearShortcut(
209 event: ShortcutEventLike,210 event: ShortcutEventLike,
210 platform = navigator.platform,211 platform = navigator.platform,
211): boolean {212): boolean {
213 if (event.type !== undefined && event.type !== "keydown") {
214 return false;
215 }
216
212 const key = event.key.toLowerCase();217 const key = event.key.toLowerCase();
213218
214 if (key === "l" && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {219 if (key === "l" && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
...@@ -229,6 +234,10 @@ export function terminalNavigationShortcutData(...@@ -229,6 +234,10 @@ export function terminalNavigationShortcutData(
229 event: ShortcutEventLike,234 event: ShortcutEventLike,
230 platform = navigator.platform,235 platform = navigator.platform,
231): string | null {236): string | null {
237 if (event.type !== undefined && event.type !== "keydown") {
238 return null;
239 }
240
232 if (event.shiftKey) return null;241 if (event.shiftKey) return null;
233242
234 const key = normalizeEventKey(event.key);243 const key = normalizeEventKey(event.key);