1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-02-22 16:35:45 +01:00

Deal with sites with finicky input handling. Add some docs. Fix :reh|foo / :rehash +args. Closes issue #551.

This commit is contained in:
Kris Maglione
2011-07-27 06:45:39 -04:00
parent 8d2f44c379
commit b56963cdfd
5 changed files with 60 additions and 35 deletions

View File

@@ -1894,7 +1894,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
"Reload the " + config.appName + " add-on", "Reload the " + config.appName + " add-on",
function (args) { function (args) {
if (args.trailing) if (args.trailing)
JSMLoader.rehashCmd = args.trailing; // Hack. storage.session.rehashCmd = args.trailing; // Hack.
args.break = true; args.break = true;
util.rehash(args); util.rehash(args);
}, },
@@ -2134,7 +2134,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
dactyl.timeout(function () { dactyl.timeout(function () {
try { try {
var args = JSMLoader.commandlineArgs || services.commandLineHandler.optionValue; var args = storage.session.commandlineArgs || services.commandLineHandler.optionValue;
if (isString(args)) if (isString(args))
args = dactyl.parseCommandLine(args); args = dactyl.parseCommandLine(args);
@@ -2225,9 +2225,9 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
dactyl.execute(cmd); dactyl.execute(cmd);
}); });
if (JSMLoader.rehashCmd) if (storage.session.rehashCmd)
dactyl.execute(JSMLoader.rehashCmd); dactyl.execute(storage.session.rehashCmd);
JSMLoader.rehashCmd = null; storage.session.rehashCmd = null;
dactyl.fullyInitialized = true; dactyl.fullyInitialized = true;
dactyl.triggerObserver("enter", null); dactyl.triggerObserver("enter", null);

View File

@@ -16,6 +16,8 @@ var ProcessorStack = Class("ProcessorStack", {
this.buffer = ""; this.buffer = "";
this.events = []; this.events = [];
events.dbg("STACK " + mode);
let main = { __proto__: mode.main, params: mode.params }; let main = { __proto__: mode.main, params: mode.params };
this.modes = array([mode.params.keyModes, main, mode.main.allBases]).flatten().compact(); this.modes = array([mode.params.keyModes, main, mode.main.allBases]).flatten().compact();
@@ -28,10 +30,13 @@ var ProcessorStack = Class("ProcessorStack", {
for (let [i, input] in Iterator(this.processors)) { for (let [i, input] in Iterator(this.processors)) {
let params = input.main.params; let params = input.main.params;
if (params.preExecute) if (params.preExecute)
input.preExecute = params.preExecute; input.preExecute = params.preExecute;
if (params.postExecute) if (params.postExecute)
input.postExecute = params.postExecute; input.postExecute = params.postExecute;
if (params.onKeyPress && input.hive === mappings.builtin) if (params.onKeyPress && input.hive === mappings.builtin)
input.fallthrough = function fallthrough(events) { input.fallthrough = function fallthrough(events) {
return params.onKeyPress(events) === false ? Events.KILL : Events.PASS; return params.onKeyPress(events) === false ? Events.KILL : Events.PASS;
@@ -39,8 +44,7 @@ var ProcessorStack = Class("ProcessorStack", {
} }
let hive = options.get("passkeys")[this.main.input ? "inputHive" : "commandHive"]; let hive = options.get("passkeys")[this.main.input ? "inputHive" : "commandHive"];
if (!builtin && hive.active if (!builtin && hive.active && (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)))
&& (!dactyl.focusedElement || events.isContentNode(dactyl.focusedElement)))
this.processors.unshift(KeyProcessor(modes.BASE, hive)); this.processors.unshift(KeyProcessor(modes.BASE, hive));
}, },
@@ -63,7 +67,9 @@ var ProcessorStack = Class("ProcessorStack", {
callable(result) ? result.toSource().substr(0, 50) : result), callable(result) ? result.toSource().substr(0, 50) : result),
execute: function execute(result, force) { execute: function execute(result, force) {
events.dbg("EXECUTE(" + this._result(result) + ", " + force + ") events:" + this.events.length + " processors:" + this.processors.length + " actions:" + this.actions.length); events.dbg("EXECUTE(" + this._result(result) + ", " + force + ") events:" + this.events.length
+ " processors:" + this.processors.length + " actions:" + this.actions.length);
let processors = this.processors; let processors = this.processors;
let length = 1; let length = 1;
@@ -126,12 +132,14 @@ var ProcessorStack = Class("ProcessorStack", {
if (result !== Events.ABORT || !this.events[0].isReplay) if (result !== Events.ABORT || !this.events[0].isReplay)
Events.kill(this.events[this.events.length - 1]); Events.kill(this.events[this.events.length - 1]);
if (result === Events.PASS_THROUGH) { if (result === Events.PASS_THROUGH || result === Events.PASS && this.passUnknown)
events.passing = true; events.passing = true;
if (result === Events.PASS_THROUGH)
events.feedevents(null, this.keyEvents, { skipmap: true, isMacro: true, isReplay: true }); events.feedevents(null, this.keyEvents, { skipmap: true, isMacro: true, isReplay: true });
}
else { else {
let list = this.events.filter(function (e) e.getPreventDefault() && !e.dactylDefaultPrevented); let list = this.events.filter(function (e) e.getPreventDefault() && !e.dactylDefaultPrevented);
if (result === Events.PASS) if (result === Events.PASS)
events.dbg("PASS THROUGH: " + list.slice(0, length).filter(function (e) e.type === "keypress").map(events.closure.toString)); events.dbg("PASS THROUGH: " + list.slice(0, length).filter(function (e) e.type === "keypress").map(events.closure.toString));
if (list.length > length) if (list.length > length)
@@ -245,8 +253,10 @@ var KeyProcessor = Class("KeyProcessor", {
function execute() { function execute() {
if (self.preExecute) if (self.preExecute)
self.preExecute.apply(self, args); self.preExecute.apply(self, args);
let res = map.execute.call(map, update({ self: self.main.params.mappingSelf || self.main.mappingSelf || map },
args)); args.self = self.main.params.mappingSelf || self.main.mappingSelf || map;
let res = map.execute.call(map, args);
if (self.postExecute) if (self.postExecute)
self.postExecute.apply(self, args); self.postExecute.apply(self, args);
return res; return res;
@@ -310,6 +320,10 @@ var KeyArgProcessor = Class("KeyArgProcessor", KeyProcessor, {
} }
}); });
/**
* A hive used mainly for tracking event listeners and cleaning them up when a
* group is destroyed.
*/
var EventHive = Class("EventHive", Contexts.Hive, { var EventHive = Class("EventHive", Contexts.Hive, {
init: function init(group) { init: function init(group) {
init.supercall(this, group); init.supercall(this, group);
@@ -396,9 +410,7 @@ var Events = Module("events", {
util.overlayWindow(window, { util.overlayWindow(window, {
append: <e4x xmlns={XUL}> append: <e4x xmlns={XUL}>
<window id={document.documentElement.id}> <window id={document.documentElement.id}>
<!--this notifies us also of focus events in the XUL <!-- http://developer.mozilla.org/en/docs/XUL_Tutorial:Updating_Commands -->
from: http://developer.mozilla.org/en/docs/XUL_Tutorial:Updating_Commands !-->
<!-- I don't think we really need this. Kris -->
<commandset id="dactyl-onfocus" commandupdater="true" events="focus" <commandset id="dactyl-onfocus" commandupdater="true" events="focus"
oncommandupdate="dactyl.modules.events.onFocusChange(event);"/> oncommandupdate="dactyl.modules.events.onFocusChange(event);"/>
<commandset id="dactyl-onselect" commandupdater="true" events="select" <commandset id="dactyl-onselect" commandupdater="true" events="select"
@@ -491,16 +503,6 @@ var Events = Module("events", {
} }
}, },
/**
* Adds an event listener for this session and removes it on
* dactyl shutdown.
*
* @param {Element} target The element on which to listen.
* @param {string} event The event to listen for.
* @param {function} callback The function to call when the event is received.
* @param {boolean} capture When true, listen during the capture
* phase, otherwise during the bubbling phase.
*/
get listen() this.builtin.closure.listen, get listen() this.builtin.closure.listen,
addSessionListener: deprecated("events.listen", { get: function addSessionListener() this.listen }), addSessionListener: deprecated("events.listen", { get: function addSessionListener() this.listen }),
@@ -939,10 +941,10 @@ var Events = Module("events", {
if (evt_obj.keyCode == 60 || evt_obj.charCode == 60) if (evt_obj.keyCode == 60 || evt_obj.charCode == 60)
evt_obj.charCode = evt_obj.keyCode = 60; // <lt> evt_obj.charCode = evt_obj.keyCode = 60; // <lt>
evt_obj.modifiers = (evt_obj.ctrlKey && Ci.nsIDOMNSEvent.CONTROL_MASK) evt_obj.modifiers = (evt_obj.ctrlKey && Ci.nsIDOMNSEvent.CONTROL_MASK)
| (evt_obj.altKey && Ci.nsIDOMNSEvent.ALT_MASK) | (evt_obj.altKey && Ci.nsIDOMNSEvent.ALT_MASK)
| (evt_obj.shiftKey && Ci.nsIDOMNSEvent.SHIFT_MASK) | (evt_obj.shiftKey && Ci.nsIDOMNSEvent.SHIFT_MASK)
| (evt_obj.metaKey && Ci.nsIDOMNSEvent.META_MASK); | (evt_obj.metaKey && Ci.nsIDOMNSEvent.META_MASK);
out.push(evt_obj); out.push(evt_obj);
} }
@@ -1139,8 +1141,8 @@ var Events = Module("events", {
}, },
/** /**
* Whether *key* is a key code defined to accept/execute input on the * Returns true if *key* is a key code defined to accept/execute input on
* command line. * the command line.
* *
* @param {string} key The key code to test. * @param {string} key The key code to test.
* @returns {boolean} * @returns {boolean}
@@ -1148,14 +1150,21 @@ var Events = Module("events", {
isAcceptKey: function (key) key == "<Return>" || key == "<C-j>" || key == "<C-m>", isAcceptKey: function (key) key == "<Return>" || key == "<C-j>" || key == "<C-m>",
/** /**
* Whether *key* is a key code defined to reject/cancel input on the * Returns true if *key* is a key code defined to reject/cancel input on
* command line. * the command line.
* *
* @param {string} key The key code to test. * @param {string} key The key code to test.
* @returns {boolean} * @returns {boolean}
*/ */
isCancelKey: function (key) key == "<Esc>" || key == "<C-[>" || key == "<C-c>", isCancelKey: function (key) key == "<Esc>" || key == "<C-[>" || key == "<C-c>",
/**
* Returns true if *node* belongs to the current content document or any
* sub-frame thereof.
*
* @param {Node|Document|Window} node The node to test.
* @returns {boolean}
*/
isContentNode: function isContentNode(node) { isContentNode: function isContentNode(node) {
let win = (node.ownerDocument || node).defaultView || node; let win = (node.ownerDocument || node).defaultView || node;
return XPCNativeWrapper(win).top == content; return XPCNativeWrapper(win).top == content;
@@ -1406,11 +1415,16 @@ var Events = Module("events", {
}, },
keyup: function onKeyUp(event) { keyup: function onKeyUp(event) {
if (this.type == "keydown") if (event.type == "keydown")
this.keyEvents.push(event); this.keyEvents.push(event);
else else
this.keyEvents = []; this.keyEvents = [];
let isMacro = event.isMacro || this.feedingEvent && this.feedingEvent.isMacro;
if (this.lastKeyFake && !isMacro)
this.passing = false;
this.lastKeyFake = isMacro;
let pass = this.passing && !event.isMacro || let pass = this.passing && !event.isMacro ||
this.feedingEvent && this.feedingEvent.isReplay || this.feedingEvent && this.feedingEvent.isReplay ||
event.isReplay || event.isReplay ||
@@ -1418,7 +1432,13 @@ var Events = Module("events", {
modes.main == modes.QUOTE modes.main == modes.QUOTE
&& modes.getStack(1).main !== modes.PASS_THROUGH && modes.getStack(1).main !== modes.PASS_THROUGH
&& !this.shouldPass(event) || && !this.shouldPass(event) ||
!modes.passThrough && this.shouldPass(event); !modes.passThrough && this.shouldPass(event) ||
!this.processor && event.type === "keydown"
&& options.get("passunknown").getKey(modes.main.allBases)
&& let (key = events.toString(event))
!modes.main.allBases.some(
function (mode) mappings.hives.some(
function (hive) hive.get(mode, key) || hive.getCandidates(mode, key)));
if (event.type === "keydown") if (event.type === "keydown")
this.passing = pass; this.passing = pass;

View File

@@ -25,6 +25,7 @@ var Services = Module("Services", {
this.add("appStartup", "@mozilla.org/toolkit/app-startup;1", "nsIAppStartup"); this.add("appStartup", "@mozilla.org/toolkit/app-startup;1", "nsIAppStartup");
this.add("autoCompleteSearch", "@mozilla.org/autocomplete/search;1?name=history", "nsIAutoCompleteSearch"); this.add("autoCompleteSearch", "@mozilla.org/autocomplete/search;1?name=history", "nsIAutoCompleteSearch");
this.add("bookmarks", "@mozilla.org/browser/nav-bookmarks-service;1", "nsINavBookmarksService"); this.add("bookmarks", "@mozilla.org/browser/nav-bookmarks-service;1", "nsINavBookmarksService");
this.add("bootstrap", "@dactyl.googlecode.com/base/bootstrap");
this.add("browserSearch", "@mozilla.org/browser/search-service;1", "nsIBrowserSearchService"); this.add("browserSearch", "@mozilla.org/browser/search-service;1", "nsIBrowserSearchService");
this.add("cache", "@mozilla.org/network/cache-service;1", "nsICacheService"); this.add("cache", "@mozilla.org/network/cache-service;1", "nsICacheService");
this.add("charset", "@mozilla.org/charset-converter-manager;1", "nsICharsetConverterManager"); this.add("charset", "@mozilla.org/charset-converter-manager;1", "nsICharsetConverterManager");

View File

@@ -150,6 +150,10 @@ var Storage = Module("Storage", {
init: function () { init: function () {
this.cleanup(); this.cleanup();
if (services.bootstrap && !services.bootstrap.session)
services.bootstrap.session = {};
this.session = services.bootstrap ? services.bootstrap.session : {};
}, },
cleanup: function () { cleanup: function () {

View File

@@ -1652,7 +1652,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
* re-enabling it. * re-enabling it.
*/ */
rehash: function (args) { rehash: function (args) {
JSMLoader.commandlineArgs = args; storage.session.commandlineArgs = args;
this.timeout(function () { this.timeout(function () {
services.observer.notifyObservers(null, "startupcache-invalidate", ""); services.observer.notifyObservers(null, "startupcache-invalidate", "");
this.rehashing = true; this.rehashing = true;