diff --git a/common/content/browser.js b/common/content/browser.js index 3400f8a1..dcdd5b48 100644 --- a/common/content/browser.js +++ b/common/content/browser.js @@ -148,6 +148,7 @@ var Browser = Module("browser", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), onLocationChange.superapply(this, arguments); contexts.flush(); + options.get("passkeys").flush(); statusline.updateUrl(); statusline.progress = ""; diff --git a/common/content/events.js b/common/content/events.js index 70a587a7..5a25aff9 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -9,13 +9,19 @@ /** @scope modules */ var ProcessorStack = Class("ProcessorStack", { - init: function (mode, hives, keyModes) { + init: function (mode, hives, builtin) { this.main = mode.main; this._actions = []; this.actions = []; this.buffer = ""; this.events = []; + let main = { __proto__: mode.main, params: mode.params }; + let keyModes = array([mode.params.keyModes, main, mode.main.allBases]).flatten().compact(); + + if (builtin) + hives = hives.filter(function (h) h.name === "builtin"); + this.processors = keyModes.map(function (m) hives.map(function (h) KeyProcessor(m, h))) .flatten().array; this.ownsBuffer = !this.processors.some(function (p) p.main.ownsBuffer); @@ -31,6 +37,9 @@ var ProcessorStack = Class("ProcessorStack", { return params.onKeyPress(events) === false ? Events.KILL : Events.PASS; }; } + + if (!builtin && (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement))) + this.processors.unshift(KeyProcessor(modes.BASE, options.get("passkeys").hive)); }, notify: function () { @@ -1207,12 +1216,7 @@ var Events = Module("events", { if (config.ignoreKeys[key] & mode.main) return null; - let hives = mappings.hives.slice(event.noremap ? -1 : 0); - - let main = { __proto__: mode.main, params: mode.params }; - let keyModes = array([mode.params.keyModes, main, mode.main.allBases]).flatten().compact(); - - this.processor = ProcessorStack(mode, hives, keyModes); + this.processor = ProcessorStack(mode, mappings.hives.array, event.noremap); this.processor.allEvents = this.keyEvents; } @@ -1392,7 +1396,7 @@ var Events = Module("events", { }, shouldPass: function shouldPass(event) - (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) && + !event.noremap && (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)) && options.get("passkeys").has(events.toString(event)) }, { ABORT: {}, @@ -1460,6 +1464,14 @@ var Events = Module("events", { }; }, mappings: function () { + + mappings.add(modes.MAIN, + [""], "Process the next key as a builtin mapping", + function () { + events.processor = ProcessorStack(modes.getStack(0), mappings.hives.array, true); + events.processor.allEvents = events.keyEvents; + }); + mappings.add(modes.MAIN, ["", ""], "Temporarily ignore all " + config.appName + " key bindings", function () { modes.push(modes.PASS_THROUGH); }); @@ -1518,18 +1530,35 @@ var Events = Module("events", { options.add(["passkeys", "pk"], "Pass certain keys through directly for the given URLs", "sitemap", "", { - has: function (key) { - let uri = buffer.documentURI; - for (let filter in values(this.value)) - if (filter(uri) && filter.result.some(function (k) k === key)) - return true; - return false; + flush: function flush() { + memoize(this, "hive", function hive() + let (values = this.value.filter(function (f) f(buffer.documentURI))) { + get: function get(mode, key) this.stack.mappings[key], + + getCandidates: function getCandidates(mode, key) this.stack.candidates[key], + + pass: set(array.flatten(values.map(function (v) v.keys))), + + stack: MapHive.Stack(values.map(function (v) v.map)) + }); }, + + has: function (key) set.has(this.hive.pass, key), + + get hive() (this.flush(), this.hive), + + keepQuotes: true, + setter: function (values) { values.forEach(function (filter) { - filter.result = events.fromString(filter.result).map(events.closure.toString); - filter.result.toString = bind(filter.result.join, filter.result); + let vals = Option.splitList(filter.result); + filter.keys = events.fromString(vals[0]).map(events.closure.toString); + filter.map = { + execute: function () Events.PASS_THROUGH, + keys: vals.slice(1).map(events.closure.canonicalKeys) + }; }); + this.flush(); return values; } }); diff --git a/common/locale/en-US/browsing.xml b/common/locale/en-US/browsing.xml index 03011a37..cbb31f10 100644 --- a/common/locale/en-US/browsing.xml +++ b/common/locale/en-US/browsing.xml @@ -20,21 +20,19 @@ want to bypass &dactyl.appName;'s key handling and pass keys directly to &dactyl.host; or to a web page, you have two options: - CTRL-Z]]> - <C-z> + ]]> + ]]>

- Pass all keys except for directly to - &dactyl.host;. When is pressed, - resume normal key handling. This is especially useful - for web sites which make heavy use of key bindings. + Process the next key as a builtin mapping, ignoring any user defined + mappings and passkeys settings.

CTRL-V]]> - <C-v> + ]]>

Pass the next key press directly to &dactyl.host;. @@ -42,6 +40,19 @@ want to bypass &dactyl.appName;'s key handling and pass keys directly to + + CTRL-Z]]> + ]]> + +

+ Pass all keys except for directly to + &dactyl.host;. When is pressed, + resume normal key handling. This is especially useful + for web sites which make heavy use of key bindings. +

+
+
+

Opening web pages

diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml index 6fdd17c7..a5988e98 100644 --- a/common/locale/en-US/options.xml +++ b/common/locale/en-US/options.xml @@ -1122,9 +1122,12 @@ For any page with a URL matching a given regexp, all key events for keys listed in that regexp's value are passed through directly to &dactyl.host;, and are not processed - by &dactyl.appName; in any way. + by &dactyl.appName; in any way. Key names are separated + by commas, where the first key name is treated as a list + of individual keys and each subsequent key is treated as + a key chain.

- https://mail\.google\.com/:jk + mail.google.com:jk<Return>,gi
diff --git a/common/modules/base.jsm b/common/modules/base.jsm index aeb44d76..eb244de4 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -525,12 +525,17 @@ function memoize(obj, key, getter) { return obj; } - obj.__defineGetter__(key, function g_replaceProperty() ( - Class.replaceProperty(this.instance || this, key, null), - Class.replaceProperty(this.instance || this, key, getter.call(this, key)))); + Object.defineProperty(obj, key, { + configurable: true, + enumerable: true, - obj.__defineSetter__(key, function s_replaceProperty(val) - Class.replaceProperty(this.instance || this, key, val)); + get: function g_replaceProperty() ( + Class.replaceProperty(this.instance || this, key, null), + Class.replaceProperty(this.instance || this, key, getter.call(this, key))), + + set: function s_replaceProperty(val) + Class.replaceProperty(this.instance || this, key, val) + }); } /** diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS index 01ef05f9..8beee832 100644 --- a/pentadactyl/NEWS +++ b/pentadactyl/NEWS @@ -75,6 +75,7 @@ - Added site-specific mapping groups and related command changes. [b6] - Added 'timeout' and 'timeoutlen' options. [b6] + - Added to execute a builtin mapping. [b6] - Added l and s to aid in the construction of macros. [b6] - Removed the implicit page load delays during macro playback. [b6]