From 4a31b3ac201e9292274f103dc20e44bdc3fae46e Mon Sep 17 00:00:00 2001 From: petoncle Date: Fri, 27 Oct 2023 23:37:54 +0200 Subject: [PATCH 01/31] Attempt to buffer keyboard events until command line is opened --- src/commandline_frame.ts | 148 ++++++++++++++++++----------- src/content/commandline_content.ts | 4 +- src/content/controller_content.ts | 28 +++++- src/lib/messaging.ts | 1 + 4 files changed, 122 insertions(+), 59 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 7f54e586..775e8097 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -162,9 +162,42 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { - commandline_state.clInput.focus() - commandline_state.clInput.removeEventListener("blur", noblur) - commandline_state.clInput.addEventListener("blur", noblur) + setTimeout(() => { + logger.info("Called focus() after 2000ms") + Messaging.messageOwnTab("clInputFocused", "unused") + commandline_state.clInput.focus() + commandline_state.clInput.removeEventListener("blur", noblur) + commandline_state.clInput.addEventListener("blur", noblur) + if (buffer.length !== 0) { + logger.info("Dispatching " + JSON.stringify(buffer)); + buffer.forEach(e => processKeyboardEvent(e)) + buffer.splice(-1) + } + }, 2000) +} + +let buffer: KeyboardEvent[] = [] +export function bufferUntil([ code, + key, + altKey, + ctrlKey, + metaKey, + shiftKey]) { + const keyevent = new KeyboardEvent('keydown', { + code: code, + key: key, + altKey: altKey, + ctrlKey: ctrlKey, + metaKey: metaKey, + shiftKey: shiftKey, + }) + logger.info("Received keyboardEvent for buffering", keyevent) + if (window.document.activeElement === commandline_state.clInput) { + processKeyboardEvent(keyevent) + } + else { + buffer.push(keyevent); + } } /** @hidden **/ @@ -182,68 +215,73 @@ let prev_cmd_called_history = false // Save programmer time by generating an immediately resolved promise // eslint-disable-next-line @typescript-eslint/no-empty-function const QUEUE: Promise[] = [(async () => {})()] +logger.info("Setting event listeners of commandline_state.clInput") /** @hidden **/ commandline_state.clInput.addEventListener( "keydown", function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return - commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) - const response = keyParser(commandline_state.keyEvents) - if (response.isMatch) { - keyevent.preventDefault() - keyevent.stopImmediatePropagation() - } else { - // Ideally, all keys that aren't explicitly bound to an ex command - // should be bound to a "self-insert" command that would input the - // key itself. Because it's not possible to generate events as if - // they originated from the user, we can't do this, but we still - // need to simulate it, in order to have history() work. - prev_cmd_called_history = false - } - if (response.value) { - commandline_state.keyEvents = [] - history_called = false - - // If excmds start with 'ex.' they're coming back to us anyway, so skip that. - // This is definitely a hack. Should expand aliases with exmode, etc. - // but this whole thing should be scrapped soon, so whatever. - if (response.value.startsWith("ex.")) { - const [funcname, ...args] = response.value.slice(3).split(/\s+/) - - QUEUE[QUEUE.length - 1].then(() => { - QUEUE.push( - // Abuse async to wrap non-promises in a promise - // eslint-disable-next-line @typescript-eslint/require-await - (async () => - commandline_state.fns[ - funcname as keyof typeof commandline_state.fns - ]( - args.length === 0 ? undefined : args.join(" "), - ))(), - ) - prev_cmd_called_history = history_called - }) - } else { - // Send excmds directly to our own tab, which fixes the - // old bug where a command would be issued in one tab but - // land in another because the active tab had - // changed. Background-mode excmds will be received by the - // own tab's content script and then bounced through a - // shim to the background, but the latency increase should - // be acceptable becuase the background-mode excmds tend - // to be a touch less latency-sensitive. - Messaging.messageOwnTab("controller_content", "acceptExCmd", [ - response.value, - ]).then(_ => (prev_cmd_called_history = history_called)) - } - } else { - commandline_state.keyEvents = response.keys - } + processKeyboardEvent(keyevent); }, true, ) +function processKeyboardEvent(keyevent: KeyboardEvent) { + commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) + const response = keyParser(commandline_state.keyEvents) + if (response.isMatch) { + keyevent.preventDefault() + keyevent.stopImmediatePropagation() + } else { + // Ideally, all keys that aren't explicitly bound to an ex command + // should be bound to a "self-insert" command that would input the + // key itself. Because it's not possible to generate events as if + // they originated from the user, we can't do this, but we still + // need to simulate it, in order to have history() work. + prev_cmd_called_history = false + } + if (response.value) { + commandline_state.keyEvents = [] + history_called = false + + // If excmds start with 'ex.' they're coming back to us anyway, so skip that. + // This is definitely a hack. Should expand aliases with exmode, etc. + // but this whole thing should be scrapped soon, so whatever. + if (response.value.startsWith("ex.")) { + const [funcname, ...args] = response.value.slice(3).split(/\s+/) + + QUEUE[QUEUE.length - 1].then(() => { + QUEUE.push( + // Abuse async to wrap non-promises in a promise + // eslint-disable-next-line @typescript-eslint/require-await + (async () => + commandline_state.fns[ + funcname as keyof typeof commandline_state.fns + ]( + args.length === 0 ? undefined : args.join(" "), + ))(), + ) + prev_cmd_called_history = history_called + }) + } else { + // Send excmds directly to our own tab, which fixes the + // old bug where a command would be issued in one tab but + // land in another because the active tab had + // changed. Background-mode excmds will be received by the + // own tab's content script and then bounced through a + // shim to the background, but the latency increase should + // be acceptable becuase the background-mode excmds tend + // to be a touch less latency-sensitive. + Messaging.messageOwnTab("controller_content", "acceptExCmd", [ + response.value, + ]).then(_ => (prev_cmd_called_history = history_called)) + } + } else { + commandline_state.keyEvents = response.keys + } +} + export function refresh_completions(exstr) { if (!commandline_state.activeCompletions) enableCompletions() return Promise.all( diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index e12c3e70..b6bf86b5 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -63,7 +63,7 @@ export function show(hidehover = false) { * * Inspired by VVimpulation: https://github.com/amedama41/vvimpulation/commit/53065d015d1e9a892496619b51be83771f57b3d5 */ - + logger.info("Called show()") if (hidehover) { const a = window.document.createElement("A") ;(a as any).href = "" @@ -98,7 +98,7 @@ export function hide() { export function focus() { try { - cmdline_iframe.focus() + // cmdline_iframe.focus() } catch (e) { // Note: We can't use cmdline_logger.error because it will try to log // the error in the commandline, which will need to focus() it again, diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 56491f6f..c9db1ab1 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -14,6 +14,7 @@ import * as hinting from "@src/content/hinting" import * as gobblemode from "@src/parsers/gobblemode" import * as generic from "@src/parsers/genericmode" import * as nmode from "@src/parsers/nmode" +import * as Messaging from "@src/lib/messaging"; const logger = new Logger("controller") @@ -191,6 +192,10 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr + if (exstr.startsWith("fillcmdline ")) { + logger.info("Setting bufferUntilClInputFocused to true") + bufferUntilClInputFocused = true + } break } else { keyEvents = response.keys @@ -211,11 +216,30 @@ function* ParserController() { } } } - +Messaging.addListener("clInputFocused", () => { + logger.info("Callback clInputFocused") + bufferUntilClInputFocused = false +}) +let bufferUntilClInputFocused: boolean = false export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() /** Feed keys to the ParserController */ export function acceptKey(keyevent: KeyboardEvent) { - return generator.next(keyevent) + logger.info("bufferUntilClInputFocused = " + bufferUntilClInputFocused) + if (bufferUntilClInputFocused) { + logger.info("Sending keyboardEvent for buffering " + keyevent.key) + Messaging.messageOwnTab("commandline_frame", "bufferUntil", + [keyevent.code, + keyevent.key, + keyevent.altKey, + keyevent.ctrlKey, + keyevent.metaKey, + keyevent.shiftKey] + ); + keyevent.preventDefault() + keyevent.stopImmediatePropagation() + canceller.push(keyevent) + } else + return generator.next(keyevent) } diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index 3920810d..fc7b398b 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -15,6 +15,7 @@ export type TabMessageType = | "lock" | "alive" | "tab_changes" + | "clInputFocused" export type NonTabMessageType = | "owntab_background" From 70e63ccae903d4c66be6f134c56ebb19b4c3a06a Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 00:12:10 +0200 Subject: [PATCH 02/31] Attempt to buffer keyboard events until command line is opened --- src/commandline_frame.ts | 27 +++++++-------------------- src/content/controller_content.ts | 9 +-------- src/excmds.ts | 1 + 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 775e8097..d911ceed 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -170,33 +170,20 @@ export function focus() { commandline_state.clInput.addEventListener("blur", noblur) if (buffer.length !== 0) { logger.info("Dispatching " + JSON.stringify(buffer)); - buffer.forEach(e => processKeyboardEvent(e)) - buffer.splice(-1) + buffer.forEach(key => commandline_state.clInput.value += key) + buffer = [] } }, 2000) } -let buffer: KeyboardEvent[] = [] -export function bufferUntil([ code, - key, - altKey, - ctrlKey, - metaKey, - shiftKey]) { - const keyevent = new KeyboardEvent('keydown', { - code: code, - key: key, - altKey: altKey, - ctrlKey: ctrlKey, - metaKey: metaKey, - shiftKey: shiftKey, - }) - logger.info("Received keyboardEvent for buffering", keyevent) +let buffer: string[] = [] +export function bufferUntil([key]) { + logger.info("Received keyboardEvent for buffering " + key) if (window.document.activeElement === commandline_state.clInput) { - processKeyboardEvent(keyevent) + commandline_state.clInput.value += key } else { - buffer.push(keyevent); + buffer.push(key); } } diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index c9db1ab1..dbdcbb12 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -229,14 +229,7 @@ export function acceptKey(keyevent: KeyboardEvent) { logger.info("bufferUntilClInputFocused = " + bufferUntilClInputFocused) if (bufferUntilClInputFocused) { logger.info("Sending keyboardEvent for buffering " + keyevent.key) - Messaging.messageOwnTab("commandline_frame", "bufferUntil", - [keyevent.code, - keyevent.key, - keyevent.altKey, - keyevent.ctrlKey, - keyevent.metaKey, - keyevent.shiftKey] - ); + Messaging.messageOwnTab("commandline_frame", "bufferUntil", [keyevent.key]); keyevent.preventDefault() keyevent.stopImmediatePropagation() canceller.push(keyevent) diff --git a/src/excmds.ts b/src/excmds.ts index bdc844cf..e11b3c9c 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3861,6 +3861,7 @@ export function sleep(time_ms: number) { /** @hidden */ //#content export function showcmdline(focus = true) { + logger.info("Called showcmdline") const hidehover = true CommandLineContent.show(hidehover) let done = Promise.resolve() From ac02eae1798e593296df8c34a9c4fb7738ecd11a Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 16:13:09 +0200 Subject: [PATCH 03/31] Rename variables --- src/commandline_frame.ts | 122 +++++++++++++++--------------- src/content/controller_content.ts | 8 +- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index d911ceed..0529adc1 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -168,22 +168,22 @@ export function focus() { commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - if (buffer.length !== 0) { - logger.info("Dispatching " + JSON.stringify(buffer)); - buffer.forEach(key => commandline_state.clInput.value += key) - buffer = [] + if (keysFromContentProcess.length !== 0) { + logger.info("Dispatching " + JSON.stringify(keysFromContentProcess)); + keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) + keysFromContentProcess = [] } }, 2000) } -let buffer: string[] = [] -export function bufferUntil([key]) { +let keysFromContentProcess: string[] = [] +export function bufferUntilClInputFocused([key]) { logger.info("Received keyboardEvent for buffering " + key) if (window.document.activeElement === commandline_state.clInput) { commandline_state.clInput.value += key } else { - buffer.push(key); + keysFromContentProcess.push(key); } } @@ -209,66 +209,62 @@ commandline_state.clInput.addEventListener( "keydown", function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return - processKeyboardEvent(keyevent); + commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) + const response = keyParser(commandline_state.keyEvents) + if (response.isMatch) { + keyevent.preventDefault() + keyevent.stopImmediatePropagation() + } else { + // Ideally, all keys that aren't explicitly bound to an ex command + // should be bound to a "self-insert" command that would input the + // key itself. Because it's not possible to generate events as if + // they originated from the user, we can't do this, but we still + // need to simulate it, in order to have history() work. + prev_cmd_called_history = false + } + if (response.value) { + commandline_state.keyEvents = [] + history_called = false + + // If excmds start with 'ex.' they're coming back to us anyway, so skip that. + // This is definitely a hack. Should expand aliases with exmode, etc. + // but this whole thing should be scrapped soon, so whatever. + if (response.value.startsWith("ex.")) { + const [funcname, ...args] = response.value.slice(3).split(/\s+/) + + QUEUE[QUEUE.length - 1].then(() => { + QUEUE.push( + // Abuse async to wrap non-promises in a promise + // eslint-disable-next-line @typescript-eslint/require-await + (async () => + commandline_state.fns[ + funcname as keyof typeof commandline_state.fns + ]( + args.length === 0 ? undefined : args.join(" "), + ))(), + ) + prev_cmd_called_history = history_called + }) + } else { + // Send excmds directly to our own tab, which fixes the + // old bug where a command would be issued in one tab but + // land in another because the active tab had + // changed. Background-mode excmds will be received by the + // own tab's content script and then bounced through a + // shim to the background, but the latency increase should + // be acceptable becuase the background-mode excmds tend + // to be a touch less latency-sensitive. + Messaging.messageOwnTab("controller_content", "acceptExCmd", [ + response.value, + ]).then(_ => (prev_cmd_called_history = history_called)) + } + } else { + commandline_state.keyEvents = response.keys + } }, true, ) -function processKeyboardEvent(keyevent: KeyboardEvent) { - commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) - const response = keyParser(commandline_state.keyEvents) - if (response.isMatch) { - keyevent.preventDefault() - keyevent.stopImmediatePropagation() - } else { - // Ideally, all keys that aren't explicitly bound to an ex command - // should be bound to a "self-insert" command that would input the - // key itself. Because it's not possible to generate events as if - // they originated from the user, we can't do this, but we still - // need to simulate it, in order to have history() work. - prev_cmd_called_history = false - } - if (response.value) { - commandline_state.keyEvents = [] - history_called = false - - // If excmds start with 'ex.' they're coming back to us anyway, so skip that. - // This is definitely a hack. Should expand aliases with exmode, etc. - // but this whole thing should be scrapped soon, so whatever. - if (response.value.startsWith("ex.")) { - const [funcname, ...args] = response.value.slice(3).split(/\s+/) - - QUEUE[QUEUE.length - 1].then(() => { - QUEUE.push( - // Abuse async to wrap non-promises in a promise - // eslint-disable-next-line @typescript-eslint/require-await - (async () => - commandline_state.fns[ - funcname as keyof typeof commandline_state.fns - ]( - args.length === 0 ? undefined : args.join(" "), - ))(), - ) - prev_cmd_called_history = history_called - }) - } else { - // Send excmds directly to our own tab, which fixes the - // old bug where a command would be issued in one tab but - // land in another because the active tab had - // changed. Background-mode excmds will be received by the - // own tab's content script and then bounced through a - // shim to the background, but the latency increase should - // be acceptable becuase the background-mode excmds tend - // to be a touch less latency-sensitive. - Messaging.messageOwnTab("controller_content", "acceptExCmd", [ - response.value, - ]).then(_ => (prev_cmd_called_history = history_called)) - } - } else { - commandline_state.keyEvents = response.keys - } -} - export function refresh_completions(exstr) { if (!commandline_state.activeCompletions) enableCompletions() return Promise.all( diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index dbdcbb12..9c1c48b0 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -228,8 +228,12 @@ generator.next() export function acceptKey(keyevent: KeyboardEvent) { logger.info("bufferUntilClInputFocused = " + bufferUntilClInputFocused) if (bufferUntilClInputFocused) { - logger.info("Sending keyboardEvent for buffering " + keyevent.key) - Messaging.messageOwnTab("commandline_frame", "bufferUntil", [keyevent.key]); + let isCharacterKey = keyevent.key.length == 1 + && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; + if (isCharacterKey) { + logger.info("Sending keyboardEvent for buffering ", keyevent) + Messaging.messageOwnTab("commandline_frame", "bufferUntilClInputFocused", [keyevent.key]); + } keyevent.preventDefault() keyevent.stopImmediatePropagation() canceller.push(keyevent) From 256da68c70c5aa7e75b8857026ceed8cbf4f913a Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 16:25:41 +0200 Subject: [PATCH 04/31] Remove delaying of clInput focus that was used for reproducing the lost chars bug --- src/commandline_frame.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 0529adc1..f4ffd7ab 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -162,18 +162,16 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { - setTimeout(() => { - logger.info("Called focus() after 2000ms") - Messaging.messageOwnTab("clInputFocused", "unused") - commandline_state.clInput.focus() - commandline_state.clInput.removeEventListener("blur", noblur) - commandline_state.clInput.addEventListener("blur", noblur) - if (keysFromContentProcess.length !== 0) { - logger.info("Dispatching " + JSON.stringify(keysFromContentProcess)); - keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) - keysFromContentProcess = [] - } - }, 2000) + logger.info("Called focus() after 2000ms") + Messaging.messageOwnTab("clInputFocused", "unused") + commandline_state.clInput.focus() + commandline_state.clInput.removeEventListener("blur", noblur) + commandline_state.clInput.addEventListener("blur", noblur) + if (keysFromContentProcess.length !== 0) { + logger.info("Dispatching " + JSON.stringify(keysFromContentProcess)); + keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) + keysFromContentProcess = [] + } } let keysFromContentProcess: string[] = [] From ad6eb518ec7cbe69a5d6497e8abffd9b1198a206 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 16:31:24 +0200 Subject: [PATCH 05/31] Change logs to debug and use snake case for cl_input_focused message --- src/commandline_frame.ts | 9 ++++----- src/content/commandline_content.ts | 2 +- src/content/controller_content.ts | 10 +++++----- src/excmds.ts | 2 +- src/lib/messaging.ts | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index f4ffd7ab..ede63f97 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -162,13 +162,13 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { - logger.info("Called focus() after 2000ms") - Messaging.messageOwnTab("clInputFocused", "unused") + logger.debug("Called focus()") + Messaging.messageOwnTab("cl_input_focused", "unused") commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) if (keysFromContentProcess.length !== 0) { - logger.info("Dispatching " + JSON.stringify(keysFromContentProcess)); + logger.debug("Dispatching " + JSON.stringify(keysFromContentProcess)); keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) keysFromContentProcess = [] } @@ -176,7 +176,7 @@ export function focus() { let keysFromContentProcess: string[] = [] export function bufferUntilClInputFocused([key]) { - logger.info("Received keyboardEvent for buffering " + key) + logger.debug("Received keyboardEvent for buffering " + key) if (window.document.activeElement === commandline_state.clInput) { commandline_state.clInput.value += key } @@ -200,7 +200,6 @@ let prev_cmd_called_history = false // Save programmer time by generating an immediately resolved promise // eslint-disable-next-line @typescript-eslint/no-empty-function const QUEUE: Promise[] = [(async () => {})()] -logger.info("Setting event listeners of commandline_state.clInput") /** @hidden **/ commandline_state.clInput.addEventListener( diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index b6bf86b5..efac967e 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -63,7 +63,7 @@ export function show(hidehover = false) { * * Inspired by VVimpulation: https://github.com/amedama41/vvimpulation/commit/53065d015d1e9a892496619b51be83771f57b3d5 */ - logger.info("Called show()") + logger.debug("Called show()") if (hidehover) { const a = window.document.createElement("A") ;(a as any).href = "" diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 9c1c48b0..20710c99 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -193,7 +193,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr if (exstr.startsWith("fillcmdline ")) { - logger.info("Setting bufferUntilClInputFocused to true") + logger.debug("Setting bufferUntilClInputFocused to true") bufferUntilClInputFocused = true } break @@ -216,8 +216,8 @@ function* ParserController() { } } } -Messaging.addListener("clInputFocused", () => { - logger.info("Callback clInputFocused") +Messaging.addListener("cl_input_focused", () => { + logger.debug("Callback cl_input_focused") bufferUntilClInputFocused = false }) let bufferUntilClInputFocused: boolean = false @@ -226,12 +226,12 @@ generator.next() /** Feed keys to the ParserController */ export function acceptKey(keyevent: KeyboardEvent) { - logger.info("bufferUntilClInputFocused = " + bufferUntilClInputFocused) + logger.debug("bufferUntilClInputFocused = " + bufferUntilClInputFocused) if (bufferUntilClInputFocused) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { - logger.info("Sending keyboardEvent for buffering ", keyevent) + logger.debug("Sending keyboardEvent for buffering ", keyevent) Messaging.messageOwnTab("commandline_frame", "bufferUntilClInputFocused", [keyevent.key]); } keyevent.preventDefault() diff --git a/src/excmds.ts b/src/excmds.ts index e11b3c9c..a71dd89f 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3861,7 +3861,7 @@ export function sleep(time_ms: number) { /** @hidden */ //#content export function showcmdline(focus = true) { - logger.info("Called showcmdline") + logger.debug("Called showcmdline") const hidehover = true CommandLineContent.show(hidehover) let done = Promise.resolve() diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index fc7b398b..f8999e27 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -15,7 +15,7 @@ export type TabMessageType = | "lock" | "alive" | "tab_changes" - | "clInputFocused" + | "cl_input_focused" export type NonTabMessageType = | "owntab_background" From 3f4746760d93b343d5f4311c3e56158831918745 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 16:42:04 +0200 Subject: [PATCH 06/31] Add comments --- src/content/commandline_content.ts | 1 + src/content/controller_content.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index efac967e..fea7a9e1 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -98,6 +98,7 @@ export function hide() { export function focus() { try { + // I don't think this is necessary because clInput is going to be focused. // cmdline_iframe.focus() } catch (e) { // Note: We can't use cmdline_logger.error because it will try to log diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 20710c99..7eece206 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -192,7 +192,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr - if (exstr.startsWith("fillcmdline ")) { + if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. logger.debug("Setting bufferUntilClInputFocused to true") bufferUntilClInputFocused = true } From fcc3d76a3e9ed997970e6558b156c270a9583ef4 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 19:28:29 +0200 Subject: [PATCH 07/31] Focus clInput only after its value has been initialized by fillcmdline --- src/commandline_frame.ts | 44 ++++++++++++++++++++----------- src/content/controller_content.ts | 12 ++++----- src/excmds.ts | 8 +++--- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index ede63f97..9d95232f 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -163,12 +163,20 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { logger.debug("Called focus()") - Messaging.messageOwnTab("cl_input_focused", "unused") commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - if (keysFromContentProcess.length !== 0) { - logger.debug("Dispatching " + JSON.stringify(keysFromContentProcess)); + Messaging.messageOwnTab("cl_input_focused", "unused") + tryConsumingBufferedKeysFromContentProcess(); +} + +function isClInputReady() { + return window.document.activeElement === commandline_state.clInput; +} + +function tryConsumingBufferedKeysFromContentProcess() { + if (keysFromContentProcess.length !== 0 && isClInputReady()) { + logger.debug("Consuming " + JSON.stringify(keysFromContentProcess)); keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) keysFromContentProcess = [] } @@ -176,8 +184,8 @@ export function focus() { let keysFromContentProcess: string[] = [] export function bufferUntilClInputFocused([key]) { - logger.debug("Received keyboardEvent for buffering " + key) - if (window.document.activeElement === commandline_state.clInput) { + logger.debug("Command line process received content process keydown event: " + key) + if (isClInputReady()) { commandline_state.clInput.value += key } else { @@ -359,16 +367,22 @@ export function fillcmdline( trailspace = true, ffocus = true, ) { - if (trailspace) commandline_state.clInput.value = newcommand + " " - else commandline_state.clInput.value = newcommand - commandline_state.isVisible = true - let result = Promise.resolve([]) - // Focus is lost for some reason. - if (ffocus) { - focus() - result = refresh_completions(commandline_state.clInput.value) - } - return result + setTimeout(() => { + logger.debug("Called commandline_frame fillcmdline after 2000ms") + // 1. Initialize clInput value. + // 2. Focus it. + // 3. Stop forwarding key events from content process to command line process. + if (trailspace) commandline_state.clInput.value = newcommand + " " + else commandline_state.clInput.value = newcommand + commandline_state.isVisible = true + let result = Promise.resolve([]) + // Focus is lost for some reason. + if (ffocus) { + focus() + result = refresh_completions(commandline_state.clInput.value) + } + // return result + }, 2000); } /** @hidden **/ diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 7eece206..0f811812 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -193,8 +193,8 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. - logger.debug("Setting bufferUntilClInputFocused to true") - bufferUntilClInputFocused = true + logger.debug("Setting clInputFocused to false") + clInputFocused = false } break } else { @@ -218,16 +218,16 @@ function* ParserController() { } Messaging.addListener("cl_input_focused", () => { logger.debug("Callback cl_input_focused") - bufferUntilClInputFocused = false + clInputFocused = true }) -let bufferUntilClInputFocused: boolean = false +let clInputFocused: boolean = true export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() /** Feed keys to the ParserController */ export function acceptKey(keyevent: KeyboardEvent) { - logger.debug("bufferUntilClInputFocused = " + bufferUntilClInputFocused) - if (bufferUntilClInputFocused) { + logger.debug("clInputFocused = " + clInputFocused) + if (!clInputFocused) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { diff --git a/src/excmds.ts b/src/excmds.ts index a71dd89f..29b51dde 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3882,16 +3882,16 @@ export function hidecmdline() { //#content export function fillcmdline(...strarr: string[]) { const str = strarr.join(" ") - showcmdline() - return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str]) + showcmdline(false) + return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, true/*trailspace*/, true/*focus*/]) } /** Set the current value of the commandline to string *without* a trailing space */ //#content export function fillcmdline_notrail(...strarr: string[]) { const str = strarr.join(" ") - showcmdline() - return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, false]) + showcmdline(false) + return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, , false/*trailspace*/, true/*focus*/]) } /** Show and fill the command line without focusing it */ From af385e0433b5a3557a202a8121a2e3840db83c60 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 20:03:29 +0200 Subject: [PATCH 08/31] Avoid relying on window.document.activeElement and use custom clInputFocused boolean --- src/commandline_frame.ts | 50 ++++++++++++++---------------- src/content/commandline_content.ts | 1 + 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 9d95232f..c1ed7711 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -82,6 +82,7 @@ const commandline_state = { keyEvents: new Array(), refresh_completions, state, + clInputFocused: false, } // first theming of commandline iframe @@ -166,26 +167,25 @@ export function focus() { commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) + commandline_state.clInputFocused = true Messaging.messageOwnTab("cl_input_focused", "unused") - tryConsumingBufferedKeysFromContentProcess(); -} - -function isClInputReady() { - return window.document.activeElement === commandline_state.clInput; -} - -function tryConsumingBufferedKeysFromContentProcess() { - if (keysFromContentProcess.length !== 0 && isClInputReady()) { + if (keysFromContentProcess.length !== 0) { logger.debug("Consuming " + JSON.stringify(keysFromContentProcess)); keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) keysFromContentProcess = [] } } +/** @hidden **/ +export function hide() { + logger.debug("Called hide()") + commandline_state.clInputFocused = false +} + let keysFromContentProcess: string[] = [] export function bufferUntilClInputFocused([key]) { logger.debug("Command line process received content process keydown event: " + key) - if (isClInputReady()) { + if (commandline_state.clInputFocused) { commandline_state.clInput.value += key } else { @@ -367,22 +367,20 @@ export function fillcmdline( trailspace = true, ffocus = true, ) { - setTimeout(() => { - logger.debug("Called commandline_frame fillcmdline after 2000ms") - // 1. Initialize clInput value. - // 2. Focus it. - // 3. Stop forwarding key events from content process to command line process. - if (trailspace) commandline_state.clInput.value = newcommand + " " - else commandline_state.clInput.value = newcommand - commandline_state.isVisible = true - let result = Promise.resolve([]) - // Focus is lost for some reason. - if (ffocus) { - focus() - result = refresh_completions(commandline_state.clInput.value) - } - // return result - }, 2000); + logger.debug("Called commandline_frame fillcmdline") + // 1. Initialize clInput value. + // 2. Focus it. + // 3. Stop forwarding key events from content process to command line process. + if (trailspace) commandline_state.clInput.value = newcommand + " " + else commandline_state.clInput.value = newcommand + commandline_state.isVisible = true + let result = Promise.resolve([]) + // Focus is lost for some reason. + if (ffocus) { + focus() + result = refresh_completions(commandline_state.clInput.value) + } + return result } /** @hidden **/ diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index fea7a9e1..fd9089fa 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -88,6 +88,7 @@ export function hide() { try { cmdline_iframe.classList.add("hidden") cmdline_iframe.setAttribute("style", "height: 0px !important;") + Messaging.messageOwnTab("commandline_frame", "hide") } catch (e) { // Using cmdline_logger here is OK because cmdline_logger won't try to // call hide(), thus we avoid the recursion that happens for show() and From 28242d8a5efe4677b2e0550ca0c57d280e4199ba Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 21:27:43 +0200 Subject: [PATCH 09/31] Call clInputValueChanged() to update completions --- src/commandline_frame.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index c1ed7711..f2c11f10 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -171,7 +171,10 @@ export function focus() { Messaging.messageOwnTab("cl_input_focused", "unused") if (keysFromContentProcess.length !== 0) { logger.debug("Consuming " + JSON.stringify(keysFromContentProcess)); - keysFromContentProcess.forEach(key => commandline_state.clInput.value += key) + for (const key of keysFromContentProcess) { + commandline_state.clInput.value += key + clInputValueChanged() + } keysFromContentProcess = [] } } @@ -186,7 +189,9 @@ let keysFromContentProcess: string[] = [] export function bufferUntilClInputFocused([key]) { logger.debug("Command line process received content process keydown event: " + key) if (commandline_state.clInputFocused) { + logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true") commandline_state.clInput.value += key + clInputValueChanged() } else { keysFromContentProcess.push(key); @@ -214,6 +219,7 @@ commandline_state.clInput.addEventListener( "keydown", function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return + logger.info("Called keydown event listener") commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) const response = keyParser(commandline_state.keyEvents) if (response.isMatch) { @@ -288,8 +294,8 @@ export function refresh_completions(exstr) { /** @hidden **/ let onInputPromise: Promise = Promise.resolve() -/** @hidden **/ -commandline_state.clInput.addEventListener("input", () => { + +function clInputValueChanged() { const exstr = commandline_state.clInput.value contentState.current_cmdline = exstr contentState.cmdline_filter = "" @@ -308,6 +314,12 @@ commandline_state.clInput.addEventListener("input", () => { contentState.cmdline_filter = exstr }) }, 100) +} + +/** @hidden **/ +commandline_state.clInput.addEventListener("input", () => { + logger.info("Called input event listener") + clInputValueChanged(); }) /** @hidden **/ From 5779121d5ca0ec20aef8a6b4124c34c6372b1f90 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 28 Oct 2023 23:22:16 +0200 Subject: [PATCH 10/31] Avoid interprocess message for notifying commandline hide, and insert content script keys at the beginning if clInput already received normal keyboard events --- src/commandline_frame.ts | 32 ++++++++++++++++++++++-------- src/content/commandline_content.ts | 1 - src/lib/commandline_cmds.ts | 4 ++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index f2c11f10..e5ee9d60 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -83,6 +83,9 @@ const commandline_state = { refresh_completions, state, clInputFocused: false, + clInputNormalEventsReceived: false, + clInputInitialValue: "", + contentProcessKeysReceivedAfterClInputFocused: 0 } // first theming of commandline iframe @@ -179,18 +182,29 @@ export function focus() { } } -/** @hidden **/ -export function hide() { - logger.debug("Called hide()") - commandline_state.clInputFocused = false -} - let keysFromContentProcess: string[] = [] export function bufferUntilClInputFocused([key]) { logger.debug("Command line process received content process keydown event: " + key) if (commandline_state.clInputFocused) { - logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true") - commandline_state.clInput.value += key + logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true," + + " clInputNormalEventsReceived = " + commandline_state.clInputNormalEventsReceived + + " contentProcessKeysReceivedAfterClInputFocused = " + commandline_state.contentProcessKeysReceivedAfterClInputFocused + + " clInputInitialValue = " + commandline_state.clInputInitialValue) + if (!commandline_state.clInputNormalEventsReceived) { + // Insert at the end. + commandline_state.clInput.value += key + } + else { + // Normal keys are assumed to always be at the end. + let normalKeyCount = commandline_state.contentProcessKeysReceivedAfterClInputFocused; + let initialCommandLength = commandline_state.clInputInitialValue.length; + // Insert received key at the beginning. + commandline_state.clInput.value = + commandline_state.clInput.value.substring(0, initialCommandLength + normalKeyCount) + + key + + commandline_state.clInput.value.substring(initialCommandLength + normalKeyCount) + commandline_state.contentProcessKeysReceivedAfterClInputFocused++; + } clInputValueChanged() } else { @@ -220,6 +234,7 @@ commandline_state.clInput.addEventListener( function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return logger.info("Called keydown event listener") + commandline_state.clInputNormalEventsReceived = true commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) const response = keyParser(commandline_state.keyEvents) if (response.isMatch) { @@ -385,6 +400,7 @@ export function fillcmdline( // 3. Stop forwarding key events from content process to command line process. if (trailspace) commandline_state.clInput.value = newcommand + " " else commandline_state.clInput.value = newcommand + commandline_state.clInputInitialValue = commandline_state.clInput.value commandline_state.isVisible = true let result = Promise.resolve([]) // Focus is lost for some reason. diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index fd9089fa..fea7a9e1 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -88,7 +88,6 @@ export function hide() { try { cmdline_iframe.classList.add("hidden") cmdline_iframe.setAttribute("style", "height: 0px !important;") - Messaging.messageOwnTab("commandline_frame", "hide") } catch (e) { // Using cmdline_logger here is OK because cmdline_logger won't try to // call hide(), thus we avoid the recursion that happens for show() and diff --git a/src/lib/commandline_cmds.ts b/src/lib/commandline_cmds.ts index 754e5f2b..30702311 100644 --- a/src/lib/commandline_cmds.ts +++ b/src/lib/commandline_cmds.ts @@ -138,6 +138,10 @@ export function getCommandlineFns(cmdline_state: { ) cmdline_state.activeCompletions = undefined cmdline_state.isVisible = false + console.debug("Called hide_and_clear()") + cmdline_state.clInputFocused = false + cmdline_state.clInputNormalEventsReceived = false + cmdline_state.contentProcessKeysReceivedAfterClInputFocused = 0 }, /** From 6b61b69455bf7f09ea8b0e7e3a204f593038fabc Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 00:27:39 +0200 Subject: [PATCH 11/31] Send all keys typed in content page instead of just one key Tab messages are not always received in order --- src/commandline_frame.ts | 63 +++++++++++++++++-------------- src/content/controller_content.ts | 7 +++- src/lib/commandline_cmds.ts | 3 ++ 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index e5ee9d60..15735413 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -82,6 +82,8 @@ const commandline_state = { keyEvents: new Array(), refresh_completions, state, + keysFromContentProcess: [], + consumedKeyCount: 0, clInputFocused: false, clInputNormalEventsReceived: false, clInputInitialValue: "", @@ -172,43 +174,48 @@ export function focus() { commandline_state.clInput.addEventListener("blur", noblur) commandline_state.clInputFocused = true Messaging.messageOwnTab("cl_input_focused", "unused") + const keysFromContentProcess = commandline_state.keysFromContentProcess; if (keysFromContentProcess.length !== 0) { - logger.debug("Consuming " + JSON.stringify(keysFromContentProcess)); - for (const key of keysFromContentProcess) { + logger.debug("Consuming " + JSON.stringify(keysFromContentProcess.slice(commandline_state.consumedKeyCount))); + for (let keyIndex = commandline_state.consumedKeyCount; keyIndex < keysFromContentProcess.length; keyIndex++) { + const key = keysFromContentProcess[keyIndex]; commandline_state.clInput.value += key clInputValueChanged() + commandline_state.consumedKeyCount++; } - keysFromContentProcess = [] } } -let keysFromContentProcess: string[] = [] -export function bufferUntilClInputFocused([key]) { - logger.debug("Command line process received content process keydown event: " + key) +export function bufferUntilClInputFocused(bufferedClInputKeys) { + logger.debug("Command line process received content process keys: " + bufferedClInputKeys) + if (bufferedClInputKeys.length < commandline_state.keysFromContentProcess.length) + return + commandline_state.keysFromContentProcess = bufferedClInputKeys; + const keysFromContentProcess = commandline_state.keysFromContentProcess; if (commandline_state.clInputFocused) { - logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true," + - " clInputNormalEventsReceived = " + commandline_state.clInputNormalEventsReceived + - " contentProcessKeysReceivedAfterClInputFocused = " + commandline_state.contentProcessKeysReceivedAfterClInputFocused + - " clInputInitialValue = " + commandline_state.clInputInitialValue) - if (!commandline_state.clInputNormalEventsReceived) { - // Insert at the end. - commandline_state.clInput.value += key + for (let keyIndex = commandline_state.consumedKeyCount; keyIndex < keysFromContentProcess.length; keyIndex++) { + const key = keysFromContentProcess[keyIndex]; + logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true," + + " clInputNormalEventsReceived = " + commandline_state.clInputNormalEventsReceived + + " contentProcessKeysReceivedAfterClInputFocused = " + commandline_state.contentProcessKeysReceivedAfterClInputFocused + + " clInputInitialValue = " + commandline_state.clInputInitialValue) + if (!commandline_state.clInputNormalEventsReceived) { + // Insert at the end. + commandline_state.clInput.value += key + } else { + // Normal keys are assumed to always be at the end. + let normalKeyCount = commandline_state.contentProcessKeysReceivedAfterClInputFocused; + let initialCommandLength = commandline_state.clInputInitialValue.length; + // Insert received key at the beginning. + commandline_state.clInput.value = + commandline_state.clInput.value.substring(0, initialCommandLength + normalKeyCount) + + key + + commandline_state.clInput.value.substring(initialCommandLength + normalKeyCount) + commandline_state.contentProcessKeysReceivedAfterClInputFocused++; + } + commandline_state.consumedKeyCount++; + clInputValueChanged() } - else { - // Normal keys are assumed to always be at the end. - let normalKeyCount = commandline_state.contentProcessKeysReceivedAfterClInputFocused; - let initialCommandLength = commandline_state.clInputInitialValue.length; - // Insert received key at the beginning. - commandline_state.clInput.value = - commandline_state.clInput.value.substring(0, initialCommandLength + normalKeyCount) - + key - + commandline_state.clInput.value.substring(initialCommandLength + normalKeyCount) - commandline_state.contentProcessKeysReceivedAfterClInputFocused++; - } - clInputValueChanged() - } - else { - keysFromContentProcess.push(key); } } diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 0f811812..7be50df1 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -195,6 +195,7 @@ function* ParserController() { if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. logger.debug("Setting clInputFocused to false") clInputFocused = false + bufferedClInputKeys = [] } break } else { @@ -221,6 +222,7 @@ Messaging.addListener("cl_input_focused", () => { clInputFocused = true }) let clInputFocused: boolean = true +let bufferedClInputKeys: string[] = [] export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() @@ -231,8 +233,9 @@ export function acceptKey(keyevent: KeyboardEvent) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { - logger.debug("Sending keyboardEvent for buffering ", keyevent) - Messaging.messageOwnTab("commandline_frame", "bufferUntilClInputFocused", [keyevent.key]); + bufferedClInputKeys.push(keyevent.key); + logger.debug("Sending keyboardEvent for buffering ", bufferedClInputKeys) + Messaging.messageOwnTab("commandline_frame", "bufferUntilClInputFocused", [ bufferedClInputKeys ]); } keyevent.preventDefault() keyevent.stopImmediatePropagation() diff --git a/src/lib/commandline_cmds.ts b/src/lib/commandline_cmds.ts index 30702311..643084b0 100644 --- a/src/lib/commandline_cmds.ts +++ b/src/lib/commandline_cmds.ts @@ -139,8 +139,11 @@ export function getCommandlineFns(cmdline_state: { cmdline_state.activeCompletions = undefined cmdline_state.isVisible = false console.debug("Called hide_and_clear()") + cmdline_state.keysFromContentProcess = [] + cmdline_state.consumedKeyCount = 0 cmdline_state.clInputFocused = false cmdline_state.clInputNormalEventsReceived = false + cmdline_state.clInputInitialValue = "" cmdline_state.contentProcessKeysReceivedAfterClInputFocused = 0 }, From dbe5a8e8a632e2e3563b3c718f203c09979fe42e Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 11:48:15 +0100 Subject: [PATCH 12/31] Make commandline process request buffered page keys from page process --- src/commandline_frame.ts | 75 +++++++++++-------------------- src/content/controller_content.ts | 28 ++++++------ src/lib/commandline_cmds.ts | 7 --- 3 files changed, 41 insertions(+), 69 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 15735413..d4100eb8 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -82,12 +82,7 @@ const commandline_state = { keyEvents: new Array(), refresh_completions, state, - keysFromContentProcess: [], - consumedKeyCount: 0, - clInputFocused: false, - clInputNormalEventsReceived: false, - clInputInitialValue: "", - contentProcessKeysReceivedAfterClInputFocused: 0 + initialClInputValue: "", } // first theming of commandline iframe @@ -168,55 +163,38 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { - logger.debug("Called focus()") commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - commandline_state.clInputFocused = true - Messaging.messageOwnTab("cl_input_focused", "unused") - const keysFromContentProcess = commandline_state.keysFromContentProcess; - if (keysFromContentProcess.length !== 0) { - logger.debug("Consuming " + JSON.stringify(keysFromContentProcess.slice(commandline_state.consumedKeyCount))); - for (let keyIndex = commandline_state.consumedKeyCount; keyIndex < keysFromContentProcess.length; keyIndex++) { - const key = keysFromContentProcess[keyIndex]; - commandline_state.clInput.value += key - clInputValueChanged() - commandline_state.consumedKeyCount++; - } - } -} - -export function bufferUntilClInputFocused(bufferedClInputKeys) { - logger.debug("Command line process received content process keys: " + bufferedClInputKeys) - if (bufferedClInputKeys.length < commandline_state.keysFromContentProcess.length) - return - commandline_state.keysFromContentProcess = bufferedClInputKeys; - const keysFromContentProcess = commandline_state.keysFromContentProcess; - if (commandline_state.clInputFocused) { - for (let keyIndex = commandline_state.consumedKeyCount; keyIndex < keysFromContentProcess.length; keyIndex++) { - const key = keysFromContentProcess[keyIndex]; - logger.debug("Dispatching received keydown event " + key + " since clInputFocused is true," + - " clInputNormalEventsReceived = " + commandline_state.clInputNormalEventsReceived + - " contentProcessKeysReceivedAfterClInputFocused = " + commandline_state.contentProcessKeysReceivedAfterClInputFocused + - " clInputInitialValue = " + commandline_state.clInputInitialValue) - if (!commandline_state.clInputNormalEventsReceived) { - // Insert at the end. - commandline_state.clInput.value += key + logger.debug("Called focus()") + Messaging.messageOwnTab("buffered_page_keys", "").then((bufferedPageKeys : string[]) => { + let clInputStillFocused = window.document.activeElement === commandline_state.clInput; + logger.debug("buffered_page_keys response received", bufferedPageKeys, + "clInputStillFocused = " + clInputStillFocused) + if (!clInputStillFocused) + return + if (bufferedPageKeys.length !== 0) { + const currentClInputValue = commandline_state.clInput.value; + // Native events are assumed to be characters added at the end of clInput. + const clInputNativeEventKeysReceived = commandline_state.initialClInputValue.length > currentClInputValue.length + logger.debug("Consuming buffered page keys", bufferedPageKeys, + "initialClInputValue = " + commandline_state.initialClInputValue, + "currentClInputValue = " + currentClInputValue); + if (clInputNativeEventKeysReceived) { + // Insert page keys at the end. + commandline_state.clInput.value += bufferedPageKeys.join("") } else { - // Normal keys are assumed to always be at the end. - let normalKeyCount = commandline_state.contentProcessKeysReceivedAfterClInputFocused; - let initialCommandLength = commandline_state.clInputInitialValue.length; - // Insert received key at the beginning. + let initialClInputValueLength = commandline_state.initialClInputValue.length; + // Insert page keys just after the command. commandline_state.clInput.value = - commandline_state.clInput.value.substring(0, initialCommandLength + normalKeyCount) - + key - + commandline_state.clInput.value.substring(initialCommandLength + normalKeyCount) - commandline_state.contentProcessKeysReceivedAfterClInputFocused++; + currentClInputValue.substring(0, initialClInputValueLength) + + bufferedPageKeys.join("") + + currentClInputValue.substring(initialClInputValueLength) } - commandline_state.consumedKeyCount++; + // Update completion. clInputValueChanged() } - } + }) } /** @hidden **/ @@ -241,7 +219,6 @@ commandline_state.clInput.addEventListener( function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return logger.info("Called keydown event listener") - commandline_state.clInputNormalEventsReceived = true commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) const response = keyParser(commandline_state.keyEvents) if (response.isMatch) { @@ -407,7 +384,7 @@ export function fillcmdline( // 3. Stop forwarding key events from content process to command line process. if (trailspace) commandline_state.clInput.value = newcommand + " " else commandline_state.clInput.value = newcommand - commandline_state.clInputInitialValue = commandline_state.clInput.value + commandline_state.initialClInputValue = commandline_state.clInput.value commandline_state.isVisible = true let result = Promise.resolve([]) // Focus is lost for some reason. diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 7be50df1..abd28261 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -193,9 +193,9 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. - logger.debug("Setting clInputFocused to false") - clInputFocused = false - bufferedClInputKeys = [] + logger.debug("Setting mustBufferPageKeysForClInput to true") + mustBufferPageKeysForClInput = true + bufferedPageKeys = [] } break } else { @@ -217,25 +217,27 @@ function* ParserController() { } } } -Messaging.addListener("cl_input_focused", () => { - logger.debug("Callback cl_input_focused") - clInputFocused = true +Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { + logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys) + // At this point, clInput is focused and the page will not get any more keyboard events. + sendResponse(Promise.resolve(bufferedPageKeys)) + mustBufferPageKeysForClInput = false + bufferedPageKeys = [] }) -let clInputFocused: boolean = true -let bufferedClInputKeys: string[] = [] +let mustBufferPageKeysForClInput = false +let bufferedPageKeys: string[] = [] export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() /** Feed keys to the ParserController */ export function acceptKey(keyevent: KeyboardEvent) { - logger.debug("clInputFocused = " + clInputFocused) - if (!clInputFocused) { + logger.debug("mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) + if (mustBufferPageKeysForClInput) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { - bufferedClInputKeys.push(keyevent.key); - logger.debug("Sending keyboardEvent for buffering ", bufferedClInputKeys) - Messaging.messageOwnTab("commandline_frame", "bufferUntilClInputFocused", [ bufferedClInputKeys ]); + bufferedPageKeys.push(keyevent.key); + logger.debug("Buffering page keys for clInput", bufferedPageKeys) } keyevent.preventDefault() keyevent.stopImmediatePropagation() diff --git a/src/lib/commandline_cmds.ts b/src/lib/commandline_cmds.ts index 643084b0..754e5f2b 100644 --- a/src/lib/commandline_cmds.ts +++ b/src/lib/commandline_cmds.ts @@ -138,13 +138,6 @@ export function getCommandlineFns(cmdline_state: { ) cmdline_state.activeCompletions = undefined cmdline_state.isVisible = false - console.debug("Called hide_and_clear()") - cmdline_state.keysFromContentProcess = [] - cmdline_state.consumedKeyCount = 0 - cmdline_state.clInputFocused = false - cmdline_state.clInputNormalEventsReceived = false - cmdline_state.clInputInitialValue = "" - cmdline_state.contentProcessKeysReceivedAfterClInputFocused = 0 }, /** From d7f0435a5a3a587ee2a88cb017ff8e46b3b7594f Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 12:18:13 +0100 Subject: [PATCH 13/31] Simplify page key buffer consumption --- src/commandline_frame.ts | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index d4100eb8..a29e8140 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -175,22 +175,17 @@ export function focus() { return if (bufferedPageKeys.length !== 0) { const currentClInputValue = commandline_state.clInput.value; - // Native events are assumed to be characters added at the end of clInput. - const clInputNativeEventKeysReceived = commandline_state.initialClInputValue.length > currentClInputValue.length + let initialClInputValue = commandline_state.initialClInputValue; logger.debug("Consuming buffered page keys", bufferedPageKeys, - "initialClInputValue = " + commandline_state.initialClInputValue, + "initialClInputValue = " + initialClInputValue, "currentClInputValue = " + currentClInputValue); - if (clInputNativeEventKeysReceived) { - // Insert page keys at the end. - commandline_state.clInput.value += bufferedPageKeys.join("") - } else { - let initialClInputValueLength = commandline_state.initialClInputValue.length; - // Insert page keys just after the command. - commandline_state.clInput.value = - currentClInputValue.substring(0, initialClInputValueLength) - + bufferedPageKeys.join("") - + currentClInputValue.substring(initialClInputValueLength) - } + // Native events are assumed to be characters added at the end of clInput. + // If the user edits the command (initial clInput value) before the buffered page keys are received, we are out of luck. + // Insert page keys just after the command. + commandline_state.clInput.value = + initialClInputValue + + bufferedPageKeys.join("") + + currentClInputValue.substring(initialClInputValue.length) // Update completion. clInputValueChanged() } From 580f48446dd85230cece57182eca6b62bba8b2c0 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 12:41:39 +0100 Subject: [PATCH 14/31] Fix typo I've introduced in fillcmdline_notrail --- src/commandline_frame.ts | 5 +---- src/excmds.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index a29e8140..b994da4c 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -373,10 +373,7 @@ export function fillcmdline( trailspace = true, ffocus = true, ) { - logger.debug("Called commandline_frame fillcmdline") - // 1. Initialize clInput value. - // 2. Focus it. - // 3. Stop forwarding key events from content process to command line process. + logger.debug("Called commandline_frame fillcmdline, trailspace = " + trailspace + " ffocus = " + ffocus) if (trailspace) commandline_state.clInput.value = newcommand + " " else commandline_state.clInput.value = newcommand commandline_state.initialClInputValue = commandline_state.clInput.value diff --git a/src/excmds.ts b/src/excmds.ts index 29b51dde..d6002d14 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3891,7 +3891,7 @@ export function fillcmdline(...strarr: string[]) { export function fillcmdline_notrail(...strarr: string[]) { const str = strarr.join(" ") showcmdline(false) - return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, , false/*trailspace*/, true/*focus*/]) + return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, false/*trailspace*/, true/*focus*/]) } /** Show and fill the command line without focusing it */ From 880c8a1d86bf6b78ac683c99032c2cb44b7373e5 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 14:28:10 +0100 Subject: [PATCH 15/31] Use debug log level instead of info --- src/commandline_frame.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index b994da4c..9e5afa09 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -213,7 +213,7 @@ commandline_state.clInput.addEventListener( "keydown", function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return - logger.info("Called keydown event listener") + logger.debug("Called clInput keydown event listener", keyevent) commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) const response = keyParser(commandline_state.keyEvents) if (response.isMatch) { @@ -312,7 +312,7 @@ function clInputValueChanged() { /** @hidden **/ commandline_state.clInput.addEventListener("input", () => { - logger.info("Called input event listener") + logger.debug("Called clInput input event listener") clInputValueChanged(); }) From c3c12df8cbb610c11017b72a7838509bac2dc1c7 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 20:04:56 +0100 Subject: [PATCH 16/31] Add missing buffered_page_keys message type --- src/lib/messaging.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index f8999e27..fee72c2b 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -15,7 +15,7 @@ export type TabMessageType = | "lock" | "alive" | "tab_changes" - | "cl_input_focused" + | "buffered_page_keys" export type NonTabMessageType = | "owntab_background" From 3d5576bb738723842f3fe04850c1ab02b4fcbe10 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 20:41:48 +0100 Subject: [PATCH 17/31] Clean logs and move code around --- src/commandline_frame.ts | 17 ++++++++--------- src/content/commandline_content.ts | 5 ++++- src/content/controller_content.ts | 27 +++++++++++++++------------ src/excmds.ts | 3 +-- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 9e5afa09..96601120 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -166,7 +166,7 @@ export function focus() { commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - logger.debug("Called focus()") + logger.debug("commandline_frame focus()") Messaging.messageOwnTab("buffered_page_keys", "").then((bufferedPageKeys : string[]) => { let clInputStillFocused = window.document.activeElement === commandline_state.clInput; logger.debug("buffered_page_keys response received", bufferedPageKeys, @@ -213,7 +213,7 @@ commandline_state.clInput.addEventListener( "keydown", function (keyevent: KeyboardEvent) { if (!keyevent.isTrusted) return - logger.debug("Called clInput keydown event listener", keyevent) + logger.debug("commandline_frame clInput keydown event listener", keyevent) commandline_state.keyEvents.push(minimalKeyFromKeyboardEvent(keyevent)) const response = keyParser(commandline_state.keyEvents) if (response.isMatch) { @@ -288,6 +288,11 @@ export function refresh_completions(exstr) { /** @hidden **/ let onInputPromise: Promise = Promise.resolve() +/** @hidden **/ +commandline_state.clInput.addEventListener("input", () => { + logger.debug("commandline_frame clInput input event listener") + clInputValueChanged(); +}) function clInputValueChanged() { const exstr = commandline_state.clInput.value @@ -310,12 +315,6 @@ function clInputValueChanged() { }, 100) } -/** @hidden **/ -commandline_state.clInput.addEventListener("input", () => { - logger.debug("Called clInput input event listener") - clInputValueChanged(); -}) - /** @hidden **/ let cmdline_history_current = "" @@ -373,7 +372,7 @@ export function fillcmdline( trailspace = true, ffocus = true, ) { - logger.debug("Called commandline_frame fillcmdline, trailspace = " + trailspace + " ffocus = " + ffocus) + logger.debug("commandline_frame fillcmdline(newcommand = " + newcommand + " trailspace = " + trailspace + " ffocus = " + ffocus + ")") if (trailspace) commandline_state.clInput.value = newcommand + " " else commandline_state.clInput.value = newcommand commandline_state.initialClInputValue = commandline_state.clInput.value diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index fea7a9e1..5786051e 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -63,7 +63,7 @@ export function show(hidehover = false) { * * Inspired by VVimpulation: https://github.com/amedama41/vvimpulation/commit/53065d015d1e9a892496619b51be83771f57b3d5 */ - logger.debug("Called show()") + logger.debug("commandline_content show()") if (hidehover) { const a = window.document.createElement("A") ;(a as any).href = "" @@ -96,6 +96,9 @@ export function hide() { } } +/** + * TODO: Discuss removal of this method? + */ export function focus() { try { // I don't think this is necessary because clInput is going to be focused. diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index abd28261..b2bdfa2f 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -100,6 +100,17 @@ class KeyCanceller { export const canceller = new KeyCanceller() +let mustBufferPageKeysForClInput = false +let bufferedPageKeys: string[] = [] +Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { + logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys) + sendResponse(Promise.resolve(bufferedPageKeys)) + // At this point, clInput is focused and the page cannot get any more keyboard events + // until it is refocused. + mustBufferPageKeysForClInput = false + bufferedPageKeys = [] +}) + /** Accepts keyevents, resolves them to maps, maps to exstrs, executes exstrs */ function* ParserController() { const parsers: { @@ -193,7 +204,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. - logger.debug("Setting mustBufferPageKeysForClInput to true") + logger.debug("Starting buffering of page keys") mustBufferPageKeysForClInput = true bufferedPageKeys = [] } @@ -217,27 +228,19 @@ function* ParserController() { } } } -Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { - logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys) - // At this point, clInput is focused and the page will not get any more keyboard events. - sendResponse(Promise.resolve(bufferedPageKeys)) - mustBufferPageKeysForClInput = false - bufferedPageKeys = [] -}) -let mustBufferPageKeysForClInput = false -let bufferedPageKeys: string[] = [] + export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() /** Feed keys to the ParserController */ export function acceptKey(keyevent: KeyboardEvent) { - logger.debug("mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) + logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) if (mustBufferPageKeysForClInput) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { bufferedPageKeys.push(keyevent.key); - logger.debug("Buffering page keys for clInput", bufferedPageKeys) + logger.debug("Buffering page keys", bufferedPageKeys) } keyevent.preventDefault() keyevent.stopImmediatePropagation() diff --git a/src/excmds.ts b/src/excmds.ts index d6002d14..af528ee9 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3861,12 +3861,11 @@ export function sleep(time_ms: number) { /** @hidden */ //#content export function showcmdline(focus = true) { - logger.debug("Called showcmdline") + logger.debug("excmds showcmdline()") const hidehover = true CommandLineContent.show(hidehover) let done = Promise.resolve() if (focus) { - CommandLineContent.focus() done = Messaging.messageOwnTab("commandline_frame", "focus") } return done From 6b620276b60ffa43e5a64b0cc5254802fd0a1218 Mon Sep 17 00:00:00 2001 From: petoncle Date: Sun, 29 Oct 2023 23:33:46 +0100 Subject: [PATCH 18/31] Clean up logs and lets --- src/commandline_frame.ts | 10 +++++----- src/content/commandline_content.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 96601120..31644f8c 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -166,21 +166,21 @@ export function focus() { commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - logger.debug("commandline_frame focus()") + logger.debug("commandline_frame clInput focus()") Messaging.messageOwnTab("buffered_page_keys", "").then((bufferedPageKeys : string[]) => { - let clInputStillFocused = window.document.activeElement === commandline_state.clInput; + const clInputStillFocused = window.document.activeElement === commandline_state.clInput; logger.debug("buffered_page_keys response received", bufferedPageKeys, "clInputStillFocused = " + clInputStillFocused) if (!clInputStillFocused) return if (bufferedPageKeys.length !== 0) { const currentClInputValue = commandline_state.clInput.value; - let initialClInputValue = commandline_state.initialClInputValue; + const initialClInputValue = commandline_state.initialClInputValue; logger.debug("Consuming buffered page keys", bufferedPageKeys, "initialClInputValue = " + initialClInputValue, "currentClInputValue = " + currentClInputValue); - // Native events are assumed to be characters added at the end of clInput. - // If the user edits the command (initial clInput value) before the buffered page keys are received, we are out of luck. + // Native events are assumed to be character keydowns events, + // i.e. characters appended at the end of clInput. // Insert page keys just after the command. commandline_state.clInput.value = initialClInputValue diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index 5786051e..dd4bb16e 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -97,7 +97,7 @@ export function hide() { } /** - * TODO: Discuss removal of this method? + * TODO: Discuss removal of this method. We want clInput to be focused, not cmdline_iframe? */ export function focus() { try { From 50f4288ffc5b8553467e6d482e4fb629235f7144 Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 09:58:55 +0100 Subject: [PATCH 19/31] Extract methods bufferPageKeyForClInput and consumeBufferedPageKeys --- src/commandline_frame.ts | 15 ++++++++------- src/content/controller_content.ts | 11 +++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 31644f8c..e1c7da32 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -55,6 +55,7 @@ import state, * as State from "@src/state" import * as R from "ramda" import { MinimalKey, minimalKeyFromKeyboardEvent } from "@src/lib/keyseq" import { TabGroupCompletionSource } from "@src/completions/TabGroup" +import {ownTabId} from "@src/lib/webext"; /** @hidden **/ const logger = new Logger("cmdline") @@ -163,11 +164,7 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) /** @hidden **/ export function focus() { - commandline_state.clInput.focus() - commandline_state.clInput.removeEventListener("blur", noblur) - commandline_state.clInput.addEventListener("blur", noblur) - logger.debug("commandline_frame clInput focus()") - Messaging.messageOwnTab("buffered_page_keys", "").then((bufferedPageKeys : string[]) => { + function consumeBufferedPageKeys(bufferedPageKeys: string[]) { const clInputStillFocused = window.document.activeElement === commandline_state.clInput; logger.debug("buffered_page_keys response received", bufferedPageKeys, "clInputStillFocused = " + clInputStillFocused) @@ -181,7 +178,6 @@ export function focus() { "currentClInputValue = " + currentClInputValue); // Native events are assumed to be character keydowns events, // i.e. characters appended at the end of clInput. - // Insert page keys just after the command. commandline_state.clInput.value = initialClInputValue + bufferedPageKeys.join("") @@ -189,7 +185,12 @@ export function focus() { // Update completion. clInputValueChanged() } - }) + } + logger.debug("commandline_frame clInput focus()") + commandline_state.clInput.focus() + commandline_state.clInput.removeEventListener("blur", noblur) + commandline_state.clInput.addEventListener("blur", noblur) + Messaging.messageTab(ownTabId(), "buffered_page_keys").then(consumeBufferedPageKeys) } /** @hidden **/ diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index b2bdfa2f..198bbf54 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -232,10 +232,9 @@ function* ParserController() { export const generator = ParserController() // var rather than let stops weirdness in repl. generator.next() -/** Feed keys to the ParserController */ +/** Feed keys to the ParserController, unless they should be buffered to be later fed to clInput */ export function acceptKey(keyevent: KeyboardEvent) { - logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) - if (mustBufferPageKeysForClInput) { + function bufferPageKeyForClInput(keyevent: KeyboardEvent) { let isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { @@ -245,6 +244,10 @@ export function acceptKey(keyevent: KeyboardEvent) { keyevent.preventDefault() keyevent.stopImmediatePropagation() canceller.push(keyevent) - } else + } + logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) + if (mustBufferPageKeysForClInput) + bufferPageKeyForClInput(keyevent) + else return generator.next(keyevent) } From fbc16a57f3dbe154b2f7be1c83249e348e1e26a7 Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 11:34:40 +0100 Subject: [PATCH 20/31] Make command optional in messageOwnTab to be in line with messageTab --- src/commandline_frame.ts | 3 +-- src/lib/messaging.ts | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index e1c7da32..d8e4607c 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -55,7 +55,6 @@ import state, * as State from "@src/state" import * as R from "ramda" import { MinimalKey, minimalKeyFromKeyboardEvent } from "@src/lib/keyseq" import { TabGroupCompletionSource } from "@src/completions/TabGroup" -import {ownTabId} from "@src/lib/webext"; /** @hidden **/ const logger = new Logger("cmdline") @@ -190,7 +189,7 @@ export function focus() { commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) - Messaging.messageTab(ownTabId(), "buffered_page_keys").then(consumeBufferedPageKeys) + Messaging.messageOwnTab("buffered_page_keys").then(consumeBufferedPageKeys) } /** @hidden **/ diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index fee72c2b..dfc80137 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -133,7 +133,7 @@ export async function message< /** Message the active tab of the currentWindow */ export async function messageActiveTab( type: TabMessageType, - command: string, + command?: string, args?: any[], ) { return messageTab(await activeTabId(), type, command, args) @@ -154,7 +154,7 @@ export async function messageTab( } let _ownTabId -export async function messageOwnTab(type: TabMessageType, command, args?) { +export async function messageOwnTab(type: TabMessageType, command?, args?) { if (_ownTabId === undefined) { _ownTabId = await ownTabId() } @@ -165,7 +165,7 @@ export async function messageOwnTab(type: TabMessageType, command, args?) { export async function messageAllTabs( type: TabMessageType, - command: string, + command?: string, args?: any[], ) { const responses = [] From 270aafb5f54800ca9df2819ea8b2461b4794d01f Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 11:40:28 +0100 Subject: [PATCH 21/31] Replace one comment with TODO and add @hidden annotation for clInputValueChanged() --- src/commandline_frame.ts | 3 ++- src/content/controller_content.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index d8e4607c..c43117ee 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -80,9 +80,9 @@ const commandline_state = { */ isVisible: false, keyEvents: new Array(), + initialClInputValue: "", refresh_completions, state, - initialClInputValue: "", } // first theming of commandline iframe @@ -294,6 +294,7 @@ commandline_state.clInput.addEventListener("input", () => { clInputValueChanged(); }) +/** @hidden **/ function clInputValueChanged() { const exstr = commandline_state.clInput.value contentState.current_cmdline = exstr diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 198bbf54..33fdaa4a 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -203,7 +203,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr - if (exstr.startsWith("fillcmdline ")) { // Ugh. That's ugly. I needed a way to know if this command is going to open the cmdline. + if (exstr.startsWith("fillcmdline ")) { // TODO That's ugly. I need a way to know if this command is going to open the command line. Is there a better way? logger.debug("Starting buffering of page keys") mustBufferPageKeysForClInput = true bufferedPageKeys = [] From 3f252ddf45dec49e82e568dd6992d39a8cd895de Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 11:48:04 +0100 Subject: [PATCH 22/31] Move common keyboardEvent stopping logic into KeyCanceller --- src/content/controller_content.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 33fdaa4a..be08f274 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -65,6 +65,8 @@ class KeyCanceller { } push(ke: KeyboardEvent) { + ke.preventDefault() + ke.stopImmediatePropagation() this.keyPress.push(ke) this.keyUp.push(ke) } @@ -196,8 +198,6 @@ function* ParserController() { ) if (response.isMatch && keyevent instanceof KeyboardEvent) { - keyevent.preventDefault() - keyevent.stopImmediatePropagation() canceller.push(keyevent) } @@ -241,8 +241,6 @@ export function acceptKey(keyevent: KeyboardEvent) { bufferedPageKeys.push(keyevent.key); logger.debug("Buffering page keys", bufferedPageKeys) } - keyevent.preventDefault() - keyevent.stopImmediatePropagation() canceller.push(keyevent) } logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) From 7f6d8603b2b0273e5c9e7c494c1c515d730deda8 Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 14:46:25 +0100 Subject: [PATCH 23/31] Replace let with const --- src/content/controller_content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index be08f274..e225615a 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -235,7 +235,7 @@ generator.next() /** Feed keys to the ParserController, unless they should be buffered to be later fed to clInput */ export function acceptKey(keyevent: KeyboardEvent) { function bufferPageKeyForClInput(keyevent: KeyboardEvent) { - let isCharacterKey = keyevent.key.length == 1 + const isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { bufferedPageKeys.push(keyevent.key); From 6c0d4d79737342b81ef2c14343a9cf02927d2d71 Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 16:54:59 +0100 Subject: [PATCH 24/31] Stop buffering keys after 5s in the event clInput is never focused --- src/commandline_frame.ts | 2 +- src/content/controller_content.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index c43117ee..57af4280 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -185,10 +185,10 @@ export function focus() { clInputValueChanged() } } - logger.debug("commandline_frame clInput focus()") commandline_state.clInput.focus() commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) + logger.debug("commandline_frame clInput focus(), activeElement is clInput: " + (window.document.activeElement === commandline_state.clInput)) Messaging.messageOwnTab("buffered_page_keys").then(consumeBufferedPageKeys) } diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index e225615a..285fea22 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -104,6 +104,7 @@ export const canceller = new KeyCanceller() let mustBufferPageKeysForClInput = false let bufferedPageKeys: string[] = [] +let stopBufferingPageKeysTimeoutId : number Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys) sendResponse(Promise.resolve(bufferedPageKeys)) @@ -111,6 +112,7 @@ Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { // until it is refocused. mustBufferPageKeysForClInput = false bufferedPageKeys = [] + clearTimeout(stopBufferingPageKeysTimeoutId); }) /** Accepts keyevents, resolves them to maps, maps to exstrs, executes exstrs */ @@ -207,6 +209,11 @@ function* ParserController() { logger.debug("Starting buffering of page keys") mustBufferPageKeysForClInput = true bufferedPageKeys = [] + // Stop buffering keys after 5s if something goes wrong and clInput never gets focused. + stopBufferingPageKeysTimeoutId = setTimeout(() => { + logger.debug("Aborting buffering of page keys since clInput still has not been focused") + mustBufferPageKeysForClInput = false + }, 5000) } break } else { From 38252b1388b26b9f3972465b52365a507ad7c66b Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 17:29:54 +0100 Subject: [PATCH 25/31] Record buffering duration --- src/content/controller_content.ts | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 285fea22..2d05be6e 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -104,15 +104,16 @@ export const canceller = new KeyCanceller() let mustBufferPageKeysForClInput = false let bufferedPageKeys: string[] = [] -let stopBufferingPageKeysTimeoutId : number +let bufferingPageKeysBeginTime: number Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { - logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys) + const bufferingDuration = performance.now() - bufferingPageKeysBeginTime; + logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys + + " bufferingDuration = " + bufferingDuration + "ms") sendResponse(Promise.resolve(bufferedPageKeys)) // At this point, clInput is focused and the page cannot get any more keyboard events // until it is refocused. mustBufferPageKeysForClInput = false bufferedPageKeys = [] - clearTimeout(stopBufferingPageKeysTimeoutId); }) /** Accepts keyevents, resolves them to maps, maps to exstrs, executes exstrs */ @@ -207,13 +208,9 @@ function* ParserController() { exstr = response.exstr if (exstr.startsWith("fillcmdline ")) { // TODO That's ugly. I need a way to know if this command is going to open the command line. Is there a better way? logger.debug("Starting buffering of page keys") + bufferingPageKeysBeginTime = performance.now() mustBufferPageKeysForClInput = true bufferedPageKeys = [] - // Stop buffering keys after 5s if something goes wrong and clInput never gets focused. - stopBufferingPageKeysTimeoutId = setTimeout(() => { - logger.debug("Aborting buffering of page keys since clInput still has not been focused") - mustBufferPageKeysForClInput = false - }, 5000) } break } else { @@ -241,7 +238,18 @@ generator.next() /** Feed keys to the ParserController, unless they should be buffered to be later fed to clInput */ export function acceptKey(keyevent: KeyboardEvent) { - function bufferPageKeyForClInput(keyevent: KeyboardEvent) { + function tryBufferingPageKeyForClInput(keyevent: KeyboardEvent) { + if (!mustBufferPageKeysForClInput) + return false; + const bufferingDuration = performance.now() - bufferingPageKeysBeginTime; + logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput + + " bufferingDuration = " + bufferingDuration + "ms"); + // Stop buffering keys after 5s if something goes wrong and clInput never gets focused. + if (bufferingDuration > 5000) { + logger.debug("Aborting buffering of page keys since clInput still has not been focused") + mustBufferPageKeysForClInput = false + return false + } const isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { @@ -249,10 +257,8 @@ export function acceptKey(keyevent: KeyboardEvent) { logger.debug("Buffering page keys", bufferedPageKeys) } canceller.push(keyevent) + return true } - logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput) - if (mustBufferPageKeysForClInput) - bufferPageKeyForClInput(keyevent) - else + if (!tryBufferingPageKeyForClInput(keyevent)) return generator.next(keyevent) } From 01b2ba85160cebe60b0074e229fc95cd7e29476b Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 17:35:28 +0100 Subject: [PATCH 26/31] Consume page key buffer even when clInput is not focused --- src/commandline_frame.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 57af4280..3caaa430 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -167,8 +167,6 @@ export function focus() { const clInputStillFocused = window.document.activeElement === commandline_state.clInput; logger.debug("buffered_page_keys response received", bufferedPageKeys, "clInputStillFocused = " + clInputStillFocused) - if (!clInputStillFocused) - return if (bufferedPageKeys.length !== 0) { const currentClInputValue = commandline_state.clInput.value; const initialClInputValue = commandline_state.initialClInputValue; From 8f6acd27cafe830a12856054ee5085c0ecb0beaa Mon Sep 17 00:00:00 2001 From: petoncle Date: Mon, 30 Oct 2023 19:26:55 +0100 Subject: [PATCH 27/31] Also start buffering of page keys with fillcmdline_notrail --- src/content/controller_content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 2d05be6e..5b1950de 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -206,7 +206,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr - if (exstr.startsWith("fillcmdline ")) { // TODO That's ugly. I need a way to know if this command is going to open the command line. Is there a better way? + if (exstr.startsWith("fillcmdline")) { // TODO That's ugly. I need a way to know if this command is going to open the command line. Is there a better way? logger.debug("Starting buffering of page keys") bufferingPageKeysBeginTime = performance.now() mustBufferPageKeysForClInput = true From 7ee8efc5af69bf2d4e0c908fe330d95196474e8d Mon Sep 17 00:00:00 2001 From: petoncle Date: Tue, 31 Oct 2023 09:35:02 +0100 Subject: [PATCH 28/31] Wait for commandline_frame message listener to be set up before trying to send messages from content process --- src/commandline_frame.ts | 3 +++ src/content/controller_content.ts | 20 ++++++++++++++------ src/excmds.ts | 1 + src/lib/messaging.ts | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 3caaa430..6a717d71 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -405,6 +405,7 @@ export function editor_function(fn_name: keyof typeof tri_editor, ...args) { } Messaging.addListener("commandline_frame", Messaging.attributeCaller(SELF)) +logger.debug("Added commandline_frame message listener") commandline_state.fns = getCommandlineFns(commandline_state) Messaging.addListener( @@ -420,3 +421,5 @@ Messaging.addListener( ;(window as any).tri = Object.assign(window.tri || {}, { perfObserver: perf.listenForCounters(), }) + +Messaging.messageOwnTab("commandline_frame_ready_to_receive_messages") diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 5b1950de..93f25284 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -102,6 +102,12 @@ class KeyCanceller { export const canceller = new KeyCanceller() +let commandlineFrameReadyToReceiveMessages = false +Messaging.addListener("commandline_frame_ready_to_receive_messages", () => { + logger.debug("Received commandline_frame_ready_to_receive_messages") + commandlineFrameReadyToReceiveMessages = true +}) + let mustBufferPageKeysForClInput = false let bufferedPageKeys: string[] = [] let bufferingPageKeysBeginTime: number @@ -244,12 +250,6 @@ export function acceptKey(keyevent: KeyboardEvent) { const bufferingDuration = performance.now() - bufferingPageKeysBeginTime; logger.debug("controller_content mustBufferPageKeysForClInput = " + mustBufferPageKeysForClInput + " bufferingDuration = " + bufferingDuration + "ms"); - // Stop buffering keys after 5s if something goes wrong and clInput never gets focused. - if (bufferingDuration > 5000) { - logger.debug("Aborting buffering of page keys since clInput still has not been focused") - mustBufferPageKeysForClInput = false - return false - } const isCharacterKey = keyevent.key.length == 1 && !keyevent.metaKey && !keyevent.ctrlKey && !keyevent.altKey && !keyevent.metaKey; if (isCharacterKey) { @@ -259,6 +259,14 @@ export function acceptKey(keyevent: KeyboardEvent) { canceller.push(keyevent) return true } + if (!commandlineFrameReadyToReceiveMessages) { + // If commandline frame cannot receive message, excmds.fillcmdline() will send a fillcmdline message to the + // commandline frame that it will never receive. As a result, clInput will not be focused (commandline_frame.focus() will not be called). + // If we (content/page process) start buffering keys for clInput, but clInput is not focused, then commandline_frame.focus() will not run, + // and it will not send the buffered_page_keys message back to us, and we will keep buffering (and eating events) forever. + logger.debug("controller_content Ignoring key event since commandline frame is not yet ready to receive messages", keyevent) + return + } if (!tryBufferingPageKeyForClInput(keyevent)) return generator.next(keyevent) } diff --git a/src/excmds.ts b/src/excmds.ts index af528ee9..ae530c32 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -3882,6 +3882,7 @@ export function hidecmdline() { export function fillcmdline(...strarr: string[]) { const str = strarr.join(" ") showcmdline(false) + logger.debug("excmds fillcmdline sending fillcmdline to commandline_frame") return Messaging.messageOwnTab("commandline_frame", "fillcmdline", [str, true/*trailspace*/, true/*focus*/]) } diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index dfc80137..7f9cf540 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -16,6 +16,7 @@ export type TabMessageType = | "alive" | "tab_changes" | "buffered_page_keys" + | "commandline_frame_ready_to_receive_messages" export type NonTabMessageType = | "owntab_background" From ae5db07df0244e72dcaface29854b037295f7a15 Mon Sep 17 00:00:00 2001 From: petoncle Date: Tue, 31 Oct 2023 14:19:18 +0100 Subject: [PATCH 29/31] Rename buffered_page_keys message to stop_buffering_page_keys --- src/commandline_frame.ts | 4 ++-- src/content/controller_content.ts | 15 ++++++++------- src/lib/messaging.ts | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 6a717d71..7549ff0a 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -165,7 +165,7 @@ const noblur = () => setTimeout(() => commandline_state.clInput.focus(), 0) export function focus() { function consumeBufferedPageKeys(bufferedPageKeys: string[]) { const clInputStillFocused = window.document.activeElement === commandline_state.clInput; - logger.debug("buffered_page_keys response received", bufferedPageKeys, + logger.debug("stop_buffering_page_keys response received, bufferedPageKeys = ", bufferedPageKeys, "clInputStillFocused = " + clInputStillFocused) if (bufferedPageKeys.length !== 0) { const currentClInputValue = commandline_state.clInput.value; @@ -187,7 +187,7 @@ export function focus() { commandline_state.clInput.removeEventListener("blur", noblur) commandline_state.clInput.addEventListener("blur", noblur) logger.debug("commandline_frame clInput focus(), activeElement is clInput: " + (window.document.activeElement === commandline_state.clInput)) - Messaging.messageOwnTab("buffered_page_keys").then(consumeBufferedPageKeys) + Messaging.messageOwnTab("stop_buffering_page_keys").then(consumeBufferedPageKeys) } /** @hidden **/ diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 93f25284..33a732c5 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -111,9 +111,9 @@ Messaging.addListener("commandline_frame_ready_to_receive_messages", () => { let mustBufferPageKeysForClInput = false let bufferedPageKeys: string[] = [] let bufferingPageKeysBeginTime: number -Messaging.addListener("buffered_page_keys", (message, sender, sendResponse) => { +Messaging.addListener("stop_buffering_page_keys", (message, sender, sendResponse) => { const bufferingDuration = performance.now() - bufferingPageKeysBeginTime; - logger.debug("buffered_page_keys request received, responding with", bufferedPageKeys + logger.debug("stop_buffering_page_keys request received, responding with bufferedPageKeys = ", bufferedPageKeys + " bufferingDuration = " + bufferingDuration + "ms") sendResponse(Promise.resolve(bufferedPageKeys)) // At this point, clInput is focused and the page cannot get any more keyboard events @@ -260,11 +260,12 @@ export function acceptKey(keyevent: KeyboardEvent) { return true } if (!commandlineFrameReadyToReceiveMessages) { - // If commandline frame cannot receive message, excmds.fillcmdline() will send a fillcmdline message to the - // commandline frame that it will never receive. As a result, clInput will not be focused (commandline_frame.focus() will not be called). - // If we (content/page process) start buffering keys for clInput, but clInput is not focused, then commandline_frame.focus() will not run, - // and it will not send the buffered_page_keys message back to us, and we will keep buffering (and eating events) forever. - logger.debug("controller_content Ignoring key event since commandline frame is not yet ready to receive messages", keyevent) + // If the commandline frame cannot receive messages, the fillcmdline message sent by excmds.fillcmdline() to the + // commandline frame will never be received. As a result, commandline_frame.focus() will not be called, which + // in turn means that the stop_buffering_page_keys message will never be sent to the content/page process. + // If the content/page process starts buffering keys for clInput, but the stop_buffering_page_keys message is never received, + // it will keep buffering (and eating events) forever. + logger.debug("controller_content Ignoring key event ", keyevent, " since commandline frame is not yet ready to receive messages", keyevent) return } if (!tryBufferingPageKeyForClInput(keyevent)) diff --git a/src/lib/messaging.ts b/src/lib/messaging.ts index 7f9cf540..de2946a6 100644 --- a/src/lib/messaging.ts +++ b/src/lib/messaging.ts @@ -15,7 +15,7 @@ export type TabMessageType = | "lock" | "alive" | "tab_changes" - | "buffered_page_keys" + | "stop_buffering_page_keys" | "commandline_frame_ready_to_receive_messages" export type NonTabMessageType = From ba977dc6ba9be41714b020886785b46a45c6be2e Mon Sep 17 00:00:00 2001 From: petoncle Date: Tue, 31 Oct 2023 14:48:52 +0100 Subject: [PATCH 30/31] Remove commandline_content.focus() --- src/commandline_frame.ts | 1 - src/content/commandline_content.ts | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index 7549ff0a..b8ce5813 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -92,7 +92,6 @@ theme(document.querySelector(":root")) function resizeArea() { if (commandline_state.isVisible) { Messaging.messageOwnTab("commandline_content", "show") - Messaging.messageOwnTab("commandline_content", "focus") focus() } } diff --git a/src/content/commandline_content.ts b/src/content/commandline_content.ts index dd4bb16e..52d4fd8f 100644 --- a/src/content/commandline_content.ts +++ b/src/content/commandline_content.ts @@ -96,22 +96,6 @@ export function hide() { } } -/** - * TODO: Discuss removal of this method. We want clInput to be focused, not cmdline_iframe? - */ -export function focus() { - try { - // I don't think this is necessary because clInput is going to be focused. - // cmdline_iframe.focus() - } catch (e) { - // Note: We can't use cmdline_logger.error because it will try to log - // the error in the commandline, which will need to focus() it again, - // which will throw again... - // cmdline_logger.error(e) - console.error(e) - } -} - export function blur() { try { cmdline_iframe.blur() From ac7d7e577b327d313168807f3a80d4e68629171e Mon Sep 17 00:00:00 2001 From: petoncle Date: Sat, 16 Dec 2023 18:41:15 +0100 Subject: [PATCH 31/31] Buffer page keys only for commands that open and focus the cmdline --- src/commandline_frame.ts | 2 +- src/content/controller_content.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commandline_frame.ts b/src/commandline_frame.ts index b8ce5813..70298720 100644 --- a/src/commandline_frame.ts +++ b/src/commandline_frame.ts @@ -172,7 +172,7 @@ export function focus() { logger.debug("Consuming buffered page keys", bufferedPageKeys, "initialClInputValue = " + initialClInputValue, "currentClInputValue = " + currentClInputValue); - // Native events are assumed to be character keydowns events, + // Native events are assumed to be character keydown events, // i.e. characters appended at the end of clInput. commandline_state.clInput.value = initialClInputValue diff --git a/src/content/controller_content.ts b/src/content/controller_content.ts index 33a732c5..eff685dc 100644 --- a/src/content/controller_content.ts +++ b/src/content/controller_content.ts @@ -212,7 +212,7 @@ function* ParserController() { if (response.exstr) { exstr = response.exstr - if (exstr.startsWith("fillcmdline")) { // TODO That's ugly. I need a way to know if this command is going to open the command line. Is there a better way? + if (exstr === "fillcmdline" || exstr === "fillcmdline_notrail") { logger.debug("Starting buffering of page keys") bufferingPageKeysBeginTime = performance.now() mustBufferPageKeysForClInput = true