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]