diff --git a/common/content/events.js b/common/content/events.js index 93ae7dfb..85084d44 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -76,7 +76,9 @@ const Events = Module("events", { this.addSessionListener(window, "DOMMenuBarActive", this.closure.onDOMMenuBarActive, true); this.addSessionListener(window, "DOMMenuBarInactive", this.closure.onDOMMenuBarInactive, true); this.addSessionListener(window, "focus", this.wrapListener(this.onFocus), true); + this.addSessionListener(window, "keydown", this.wrapListener(this.onKeyUpOrDown), true); this.addSessionListener(window, "keypress", this.wrapListener(this.onKeyPress), true); + this.addSessionListener(window, "keyup", this.wrapListener(this.onKeyUpOrDown), true); this.addSessionListener(window, "mousedown", this.wrapListener(this.onMouseDown), true); this.addSessionListener(window, "popuphidden", this.closure.onPopupHidden, true); this.addSessionListener(window, "popupshown", this.closure.onPopupShown, true); @@ -600,7 +602,6 @@ const Events = Module("events", { let ret = (buffer.loaded == 1); if (!ret) dactyl.echoerr("Page did not load completely in " + maxWaitTime + " seconds. Macro stopped."); - //util.dump("done waiting: " + ret); // sometimes the input widget had focus when replaying a macro // maybe this call should be moved somewhere else? @@ -684,6 +685,10 @@ const Events = Module("events", { if (elem && elem.readOnly) return; + if (Events.isContentNode(elem) && !buffer.focusAllowed(win) + && isinstance(elem, [HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement])) + return; + if (elem instanceof HTMLInputElement && set.has(util.editableInputs, elem.type) || elem instanceof HTMLSelectElement) { dactyl.mode = modes.INSERT; @@ -783,6 +788,8 @@ const Events = Module("events", { let stop = false; let mode = modes.getStack(0); + util.dump(String(mode), key); + let win = document.commandDispatcher.focusedWindow; if (win && win.document && "designMode" in win.document && win.document.designMode == "on" && !config.isComposeWindow) stop = true; @@ -803,6 +810,8 @@ const Events = Module("events", { } // handle Escape-all-keys mode (Ctrl-q) + util.dump(String(mode), key, stop); + if (stop) { this._input.buffer = ""; return null; @@ -934,6 +943,14 @@ const Events = Module("events", { } }, + onKeyUpOrDown: function onKeyUpOrDown(event) { + // Prevent certain sites from transferring focus to an input box + // before we get a chance to process our key bindings on the + // "keypress" event. + if (!Events.isInputElemFocused() && !modes.passThrough) + event.stopPropagation(); + }, + onMouseDown: function onMouseDown(event) { let elem = event.target; let win = elem.ownerDocument && elem.ownerDocument.defaultView || elem; diff --git a/common/content/modes.js b/common/content/modes.js index e4319258..90c7da0c 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -135,6 +135,8 @@ const Modes = Module("modes", { get mainMode() this._modeMap[this._main], + get passThrough() !!(this.main & (this.PASS_THROUGH|this.QUOTE)) ^ (this.getStack(1).main === this.PASS_THROUGH), + get topOfStack() this._modeStack[this._modeStack.length - 1], addMode: function (name, extended, options, params) { @@ -258,10 +260,6 @@ const Modes = Module("modes", { this.show(); }, - push: function push(mainMode, extendedMode, params) { - this.set(mainMode, extendedMode, params, { push: this.topOfStack }); - }, - onCaretChange: function onPrefChange(value) { if (!value && modes.main === modes.CARET) modes.pop(); @@ -269,7 +267,12 @@ const Modes = Module("modes", { modes.push(modes.CARET); }, + push: function push(mainMode, extendedMode, params) { + this.set(mainMode, extendedMode, params, { push: this.topOfStack }); + }, + pop: function pop(mode) { + util.dumpStack(mode); while (this._modeStack.length > 1 && this.main != mode) { let a = this._modeStack.pop(); this.set(this.topOfStack.main, this.topOfStack.extended, this.topOfStack.params,