diff --git a/common/content/buffer.js b/common/content/buffer.js index 895f8c91..e63c8c8c 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -671,8 +671,8 @@ var Buffer = Module("buffer", { null, null, null, persist)); persist.progressListener = update(Object.create(downloadListener), { - onStateChange: function onStateChange(progress, request, flag, status) { - if (callback && (flag & Ci.nsIWebProgressListener.STATE_STOP) && status == 0) + onStateChange: function onStateChange(progress, request, flags, status) { + if (callback && (flags & Ci.nsIWebProgressListener.STATE_STOP) && status == 0) dactyl.trapErrors(callback, self, uri, file, progress, request, flag, status); return onStateChange.superapply(this, arguments); @@ -1011,8 +1011,8 @@ var Buffer = Module("buffer", { return null; }, - onStateChange: function onStateChange(progress, request, flag, status) { - if ((flag & this.STATE_STOP) && status == 0) { + onStateChange: function onStateChange(progress, request, flags, status) { + if ((flags & this.STATE_STOP) && status == 0) { try { var ok = this.callback(this.file, true); } diff --git a/common/content/editor.js b/common/content/editor.js index 52778d2f..d0a935eb 100644 --- a/common/content/editor.js +++ b/common/content/editor.js @@ -858,7 +858,7 @@ var Editor = Module("editor", { options: function () { options.add(["editor"], "The external text editor", - "string", "gvim -f '+<{|sil! call cursor(0, )}>' ", { + "string", "gvim -f + '+sil! call cursor(0, )' ", { format: function (obj, value) { let args = commands.parseArgs(value || this.value, { argCount: "*", allowUnknownOptions: true }) .map(util.compileMacro).filter(function (fmt) fmt.valid(obj)) diff --git a/common/content/events.js b/common/content/events.js index 939515a0..8f5ef0c2 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -98,7 +98,7 @@ var ProcessorStack = Class("ProcessorStack", { // Kill the event, set a timeout to give up waiting if applicable. result = Events.KILL; - if (options["timeout"]) + if (options["timeout"] && (this.actions.length || events.hasNativeKey(this.main, this.events[0]))) this.timer = services.Timer(this, options["timeoutlen"], services.Timer.TYPE_ONE_SHOT); } else if (result !== Events.KILL && !this.actions.length && @@ -442,6 +442,7 @@ var Events = Module("events", { this._key_key = {}; this._code_key = {}; this._key_code = {}; + this._code_nativeKey = {}; for (let list in values(this._keyTable)) for (let v in values(list)) { @@ -451,6 +452,8 @@ var Events = Module("events", { } for (let [k, v] in Iterator(KeyEvent)) { + this._code_nativeKey[v] = k.substr(4); + k = k.substr(7).toLowerCase(); let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase()) .replace(/^NUMPAD/, "k")]; @@ -1060,6 +1063,65 @@ var Events = Module("events", { return "<" + modifier + key + ">"; }, + /** + * Returns true if there's a known native key handler for the given + * event in the given mode. + * + * @param {Modes.Mode} mode The main mode. + * @param {Event} event A keypress event. + */ + hasNativeKey: function hasNativeKey(mode, event) { + if (mode.input) + return event.charCode && !(event.ctrlKey || event.metaKey); + + var elements = document.getElementsByTagNameNS(XUL, "key"); + var filters = []; + + if (event.keyCode) + filters.push(["keycode", this._code_nativeKey[event.keyCode]]); + if (event.charCode) { + let key = String.fromCharCode(event.charCode); + filters.push(["key", key.toUpperCase()], + ["key", key.toLowerCase()]); + } + + let accel = util.OS.isMacOSX ? "metaKey" : "ctrlKey"; + + let access = iter({ 1: "shiftKey", 2: "ctrlKey", 4: "altKey", 8: "metaKey" }) + .filter(function ([k, v]) this & k, prefs.get("ui.key.chromeAccess")) + .map(function ([k, v]) [v, true]) + .toObject(); + + outer: + for (let [, key] in iter(elements)) + if (filters.some(function ([k, v]) key.getAttribute(k) == v)) { + let keys = { ctrlKey: false, altKey: false, shiftKey: false, metaKey: false }; + let needed = { ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey, metaKey: event.metaKey }; + + let modifiers = (key.getAttribute("modifiers") || "").trim().split(/[\s,]+/); + for (let modifier in values(modifiers)) + switch (modifier) { + case "access": update(keys, access); break; + case "accel": keys[accel] = true; break; + default: keys[modifier + "Key"] = true; break; + case "any": + if (!iter.some(keys, function ([k, v]) v && needed[k])) + continue outer; + for (let [k, v] in iter(keys)) { + if (v) + needed[k] = false; + keys[k] = false; + } + break; + } + + if (iter(needed).every(function ([k, v]) v == keys[k])) + return key; + } + + return false; + }, + /** * Whether *key* is a key code defined to accept/execute input on the * command line. diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml index 0b1ea25c..f7b21148 100644 --- a/common/locale/en-US/options.xml +++ b/common/locale/en-US/options.xml @@ -82,7 +82,7 @@ of :command macros, may be accessed by appending [n], where n is the one-based array index, to the macro name. The first argument of a command is - therefore accessed with <args[1]<. + therefore accessed with <args[1]>.

Any substring enclosed by <{ and }>