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
|
|
|
|
2017-10-23 09:42:50 +01:00
|
|
|
// Bad workaround: never suppress events in an editable field
|
2017-11-04 18:03:58 +00:00
|
|
|
// and never suppress keys pressed with modifiers
|
2018-04-13 19:28:03 +01:00
|
|
|
if (
|
|
|
|
state.mode === "input" ||
|
|
|
|
!(isTextEditable(ke.target as Node) || ke.ctrlKey || ke.altKey)
|
|
|
|
) {
|
2017-10-23 09:42:50 +01:00
|
|
|
suppressKey(ke)
|
2017-09-25 04:44:56 +01:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2017-11-19 03:22:59 +00:00
|
|
|
/** Choose to suppress a key or not */
|
2017-10-23 09:42:50 +01:00
|
|
|
function suppressKey(ke: KeyboardEvent) {
|
2017-11-19 03:22:59 +00:00
|
|
|
// Mode specific suppression
|
2017-11-19 02:41:01 +00:00
|
|
|
TerribleModeSpecificSuppression(ke)
|
2017-10-02 00:59:51 +01:00
|
|
|
}
|
2017-09-25 04:44:56 +01:00
|
|
|
|
2017-11-19 02:41:01 +00:00
|
|
|
// {{{ Shitty key suppression workaround.
|
|
|
|
|
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
|
|
|
|
2017-11-19 03:33:15 +00:00
|
|
|
// Keys not to suppress in normal mode.
|
2017-11-19 08:07:01 +00:00
|
|
|
const normalmodewhitelist = [
|
2018-03-18 15:08:09 +00:00
|
|
|
// comment line below out once find mode is done
|
2018-04-13 19:28:03 +01:00
|
|
|
"/",
|
2017-11-19 08:07:01 +00:00
|
|
|
"'",
|
2018-04-13 19:28:03 +01:00
|
|
|
" ",
|
2017-11-19 08:07:01 +00:00
|
|
|
]
|
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
const hintmodewhitelist = ["F3", "F5", "F12"]
|
2017-11-19 03:33:15 +00:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
import * as normalmode from "./parsers/normalmode"
|
|
|
|
let keys = []
|
|
|
|
|
2017-11-19 02:41:01 +00:00
|
|
|
function TerribleModeSpecificSuppression(ke: KeyboardEvent) {
|
|
|
|
switch (state.mode) {
|
|
|
|
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-13 19:28:03 +01:00
|
|
|
if (!hintmodewhitelist.includes(ke.key)) {
|
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":
|
|
|
|
if (ke.key === "Tab") {
|
|
|
|
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-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 {}
|