2017-10-02 00:59:51 +01:00
|
|
|
/** Shim for the keyboard API because it won't hit in FF57. */
|
2017-09-25 04:44:56 +01:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import * as Messaging from "./messaging"
|
|
|
|
import * as msgsafe from "./msgsafe"
|
|
|
|
import { isTextEditable, getAllDocumentFrames } from "./dom"
|
|
|
|
import { isSimpleKey } from "./keyseq"
|
2017-10-02 00:59:51 +01:00
|
|
|
|
|
|
|
function keyeventHandler(ke: KeyboardEvent) {
|
2017-11-09 06:01:26 +00:00
|
|
|
// Ignore JS-generated events for security reasons.
|
2018-04-13 19:28:03 +01:00
|
|
|
if (!ke.isTrusted) return
|
2017-11-09 06:01:26 +00:00
|
|
|
|
2018-04-15 22:32:26 +01:00
|
|
|
// Mode is changed based on ke target in the bg.
|
2018-05-03 20:21:15 +01:00
|
|
|
modeSpecificSuppression(ke)
|
2017-11-09 06:01:26 +00:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
Messaging.message("keydown_background", "recvEvent", [
|
|
|
|
msgsafe.KeyboardEvent(ke),
|
|
|
|
])
|
2017-10-23 09:42:50 +01:00
|
|
|
}
|
|
|
|
|
2018-04-15 22:32:26 +01:00
|
|
|
// {{{ Bad key suppression system
|
2017-11-19 02:41:01 +00:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
// This is all awful and will go away when we move the parsers and stuff to content properly.
|
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import state from "./state"
|
2017-11-19 02:41:01 +00:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
import * as normalmode from "./parsers/normalmode"
|
|
|
|
let keys = []
|
|
|
|
|
2018-04-15 22:32:26 +01:00
|
|
|
/** Choose to suppress a key or not */
|
|
|
|
function modeSpecificSuppression(ke: KeyboardEvent) {
|
2018-05-03 20:21:15 +01:00
|
|
|
let mode = state.mode
|
|
|
|
|
|
|
|
// Duplicate of the logic in src/controller
|
|
|
|
// Yes, this is not good.
|
|
|
|
// Will be fixed in v2, promise.
|
|
|
|
if (
|
|
|
|
state.mode != "ignore" &&
|
|
|
|
state.mode != "hint" &&
|
|
|
|
state.mode != "input" &&
|
|
|
|
state.mode != "find"
|
|
|
|
) {
|
|
|
|
if (isTextEditable(ke.target as Node)) {
|
|
|
|
if (state.mode !== "insert") {
|
|
|
|
mode = "insert"
|
|
|
|
}
|
|
|
|
} else if (state.mode === "insert") {
|
|
|
|
mode = "normal"
|
|
|
|
}
|
|
|
|
} else if (mode === "input" && !isTextEditable(ke.target as Node)) {
|
|
|
|
mode = "normal"
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (mode) {
|
2017-11-19 02:41:01 +00:00
|
|
|
case "normal":
|
2018-04-15 23:12:54 +01:00
|
|
|
keys.push(ke)
|
|
|
|
const response = normalmode.parser(keys)
|
2017-11-19 03:33:15 +00:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
// Suppress if there's a match.
|
|
|
|
if (response.isMatch) {
|
2017-11-19 02:41:01 +00:00
|
|
|
ke.preventDefault()
|
2017-11-19 03:22:59 +00:00
|
|
|
ke.stopImmediatePropagation()
|
2017-11-19 02:41:01 +00:00
|
|
|
}
|
2018-04-15 23:12:54 +01:00
|
|
|
|
|
|
|
// Update keys array.
|
|
|
|
keys = response.keys || []
|
2017-11-19 02:41:01 +00:00
|
|
|
break
|
2017-11-20 23:21:49 +00:00
|
|
|
// Hintmode can't clean up after itself yet, so it needs to block more FF shortcuts.
|
2017-11-19 02:41:01 +00:00
|
|
|
case "hint":
|
2018-01-28 23:29:09 +00:00
|
|
|
case "find":
|
2018-04-15 22:32:26 +01:00
|
|
|
if (isSimpleKey(ke)) {
|
2017-11-19 16:44:14 +00:00
|
|
|
ke.preventDefault()
|
|
|
|
ke.stopImmediatePropagation()
|
|
|
|
}
|
2018-04-13 19:28:03 +01:00
|
|
|
break
|
2017-11-20 23:21:49 +00:00
|
|
|
case "gobble":
|
2017-11-21 03:20:17 +00:00
|
|
|
if (isSimpleKey(ke) || ke.key === "Escape") {
|
2017-11-20 23:21:49 +00:00
|
|
|
ke.preventDefault()
|
|
|
|
ke.stopImmediatePropagation()
|
|
|
|
}
|
|
|
|
break
|
2017-12-02 23:54:37 +08:00
|
|
|
case "input":
|
2018-04-28 16:35:43 +01:00
|
|
|
if (ke.key === "Tab" || (ke.ctrlKey === true && ke.key === "i")) {
|
2017-12-02 23:54:37 +08:00
|
|
|
ke.preventDefault()
|
|
|
|
ke.stopImmediatePropagation()
|
|
|
|
}
|
|
|
|
break
|
2017-11-19 03:22:59 +00:00
|
|
|
case "ignore":
|
2018-04-13 19:28:03 +01:00
|
|
|
break
|
2017-11-19 03:22:59 +00:00
|
|
|
case "insert":
|
2018-04-28 16:35:43 +01:00
|
|
|
if (ke.ctrlKey === true && ke.key === "i") {
|
|
|
|
ke.preventDefault()
|
|
|
|
ke.stopImmediatePropagation()
|
|
|
|
}
|
2018-04-13 19:28:03 +01:00
|
|
|
break
|
2017-11-19 02:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// }}}
|
2017-10-23 09:42:50 +01:00
|
|
|
|
2017-10-02 00:59:51 +01:00
|
|
|
// Add listeners
|
2017-10-23 09:42:50 +01:00
|
|
|
window.addEventListener("keydown", keyeventHandler, true)
|
2018-03-02 21:18:47 +01:00
|
|
|
document.addEventListener("readystatechange", ev =>
|
|
|
|
getAllDocumentFrames().map(frame => {
|
2018-04-13 19:28:03 +01:00
|
|
|
frame.contentWindow.removeEventListener(
|
|
|
|
"keydown",
|
|
|
|
keyeventHandler,
|
|
|
|
true,
|
|
|
|
)
|
2018-03-02 21:18:47 +01:00
|
|
|
frame.contentWindow.addEventListener("keydown", keyeventHandler, true)
|
2018-04-13 19:28:03 +01:00
|
|
|
}),
|
|
|
|
)
|
|
|
|
import * as SELF from "./keydown_content"
|
|
|
|
Messaging.addListener("keydown_content", Messaging.attributeCaller(SELF))
|
2017-10-23 09:42:50 +01:00
|
|
|
|
2017-10-02 00:59:51 +01:00
|
|
|
// Dummy export so that TS treats this as a module.
|
|
|
|
export {}
|