From 1c9d1b2548cc2c2a41faf393cb8797562d3037f8 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 25 Dec 2010 19:45:05 -0500 Subject: [PATCH 1/4] Allow binding keys in "menu" modes. --- common/content/commandline.js | 4 ++-- common/content/events.js | 12 ++++++++---- common/modules/util.jsm | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/common/content/commandline.js b/common/content/commandline.js index 18865e97..c53ed173 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -1168,9 +1168,9 @@ var CommandLine = Module("commandline", { availableHeight -= extra || 0; doc.body.style.minWidth = this.widgets.commandbar.commandline.scrollWidth + "px"; - this.widgets.mowContainer.height = Math.min(doc.height, availableHeight) + "px"; + this.widgets.mowContainer.height = Math.min(doc.body.clientHeight, availableHeight) + "px"; this.timeout(function () - this.widgets.mowContainer.height = Math.min(doc.height, availableHeight) + "px", + this.widgets.mowContainer.height = Math.min(doc.body.clientHeight, availableHeight) + "px", 0); doc.body.style.minWidth = ""; diff --git a/common/content/events.js b/common/content/events.js index b9c4f5c7..1d4dedaa 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -106,7 +106,8 @@ var Events = Module("events", { */ wrapListener: function wrapListener(method, self) { self = self || this; - return function wrappedListener(event) { + method.wrapped = wrappedListener; + function wrappedListener(event) { try { method.apply(self, arguments); } @@ -118,6 +119,7 @@ var Events = Module("events", { dactyl.echoerr("Processing " + event.type + " event: " + (e.echoerr || e)); } }; + return wrappedListener; }, /** @@ -865,11 +867,13 @@ var Events = Module("events", { this._input = null; if (!input) { let ignore = false; + let overrideMode = null; // menus have their own command handlers if (modes.extended & modes.MENU) - ignore = true; - else if (modes.main == modes.PASS_THROUGH) + overrideMode = modes.MENU; + + if (modes.main == modes.PASS_THROUGH) ignore = !Events.isEscape(key) && key != ""; else if (modes.main == modes.QUOTE) { if (modes.getStack(1).main == modes.PASS_THROUGH) { @@ -896,7 +900,7 @@ var Events = Module("events", { if (key in config.ignoreKeys && (config.ignoreKeys[key] & mode.main)) return null; - input = Events.KeyProcessor(mode.params.mainMode || mode.main, mode.extended); + input = Events.KeyProcessor(overrideMode || mode.params.mainMode || mode.main, mode.extended); if (mode.params.preExecute) input.preExecute = mode.params.preExecute; if (mode.params.postExecute) diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 0fcdc920..919b1221 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -68,7 +68,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), __noSuchMethod__: function (meth, args) { let win = util.activeWindow; var dactyl = global && global.dactyl || win && win.dactyl; - if (!win) + if (!dactyl) return null; let prop = dactyl[meth]; @@ -102,6 +102,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } catch (e) {} } + Class.replaceProperty(obj, "observe", function (subject, target, data) { try { From 289b766266e86eb35dd514fccc2918afce6da85c Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 25 Dec 2010 22:57:00 -0500 Subject: [PATCH 2/4] Get rid of stupid special casing of "q" in the key press handler. --- common/content/events.js | 60 +++++++++++++++++++++------------------- common/content/modes.js | 16 +++++------ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/common/content/events.js b/common/content/events.js index 1d4dedaa..2ab628d2 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -16,6 +16,7 @@ var Events = Module("events", { this._fullscreen = window.fullScreen; this._lastFocus = null; this._currentMacro = ""; + this._macroKeys = []; this._lastMacro = ""; this.sessionListeners = []; @@ -138,19 +139,30 @@ var Events = Module("events", { dactyl.assert(/[a-zA-Z0-9]/.test(macro), "E354: Invalid register name: '" + macro + "'"); - modes.isRecording = true; + modes.recording = true; if (/[A-Z]/.test(macro)) { // uppercase (append) this._currentMacro = macro.toLowerCase(); - if (!this._macros.get(this._currentMacro)) - this._macros.set(this._currentMacro, { keys: "", timeRecorded: Date.now() }); // initialize if it does not yet exist + this._macroKeys = events.fromString((this._macros.get(this._currentMacro) || { keys: "" }).keys, true) + .map(events.closure.toString); } else { this._currentMacro = macro; - this._macros.set(this._currentMacro, { keys: "", timeRecorded: Date.now() }); + this._macroKeys = []; } }, + finishRecording: function () { + modes.recording = false; + this._macros.set(this._currentMacro, { + keys: this._macroKeys.join(""), + timeRecorded: Date.now() + }); + + dactyl.log("Recorded " + this._currentMacro + ": " + this._macroKeys.join(""), 9); + dactyl.echomsg("Recorded macro '" + this._currentMacro + "'"); + }, + /** * Replays a macro. * @@ -181,9 +193,9 @@ var Events = Module("events", { catch (e) {} buffer.loaded = 1; // even if not a full page load, assume it did load correctly before starting the macro - modes.isReplaying = true; + modes.replaying = true; res = events.feedkeys(this._macros.get(this._lastMacro).keys, { noremap: true }); - modes.isReplaying = false; + modes.replaying = false; } else // TODO: ignore this like Vim? @@ -263,7 +275,7 @@ var Events = Module("events", { break; // Stop feeding keys if page loading failed. - if (modes.isReplaying && !this.waitForPageLoad()) + if (modes.replaying && !this.waitForPageLoad()) break; } } @@ -822,19 +834,8 @@ var Events = Module("events", { if (!key) return null; - if (modes.isRecording) { - if (key == "q" && !modes.main.input) { // TODO: should not be hard-coded - modes.isRecording = false; - dactyl.log("Recorded " + this._currentMacro + ": " + this._macros.get(this._currentMacro, {}).keys, 9); - dactyl.echomsg("Recorded macro '" + this._currentMacro + "'"); - return killEvent(); - } - else if (this._input && !mappings.hasMap(modes.main, this._input.buffer + key)) - this._macros.set(this._currentMacro, { - keys: this._macros.get(this._currentMacro, {}).keys + key, - timeRecorded: Date.now() - }); - } + if (modes.recording && (!this._input || !mappings.hasMap(modes.main, this._input.buffer + key))) + events._macroKeys.push(key); // feedingKeys needs to be separate from interrupted so // we can differentiate between a recorded @@ -843,8 +844,8 @@ var Events = Module("events", { if (events.feedingKeys && !event.isMacro) { if (key == "") { events.feedingKeys = false; - if (modes.isReplaying) { - modes.isReplaying = false; + if (modes.replaying) { + modes.replaying = false; this.timeout(function () { dactyl.echomsg("Canceled playback of macro '" + this._lastMacro + "'"); }, 100); } } @@ -1091,7 +1092,7 @@ var Events = Module("events", { else if (this.pendingArgMap) { let map = this.pendingArgMap; if (!Events.isEscape(key)) - if (!modes.isReplaying || this.waitForPageLoad()) + if (!modes.replaying || this.waitForPageLoad()) execute(map, null, this.count, key); return true; } @@ -1118,7 +1119,7 @@ var Events = Module("events", { this.pendingMotionMap = map; } else { - if (modes.isReplaying && !this.waitForPageLoad()) + if (modes.replaying && !this.waitForPageLoad()) return true; let ret = execute(map, null, this.count); @@ -1211,12 +1212,15 @@ var Events = Module("events", { function () { return; }); // macros - mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE].filter(util.identity), + mappings.add([modes.NORMAL, modes.TEXT_AREA, modes.PLAYER].filter(util.identity), ["q"], "Record a key sequence into a macro", - function (arg) { events.startRecording(arg); }, - { arg: true }); + function (arg) { + events._macroKeys.pop(); + events[modes.recording ? "finishRecording" : "startRecording"](arg); + }, + { get arg() !modes.recording }); - mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE].filter(util.identity), + mappings.add([modes.NORMAL, modes.TEXT_AREA, modes.PLAYER].filter(util.identity), ["@"], "Play a macro", function (count, arg) { count = Math.max(count, 1); diff --git a/common/content/modes.js b/common/content/modes.js index aab3b314..8f3f0ca1 100644 --- a/common/content/modes.js +++ b/common/content/modes.js @@ -18,8 +18,8 @@ var Modes = Module("modes", { this._passNextKey = false; this._passAllKeys = false; - this._isRecording = false; - this._isReplaying = false; // playing a macro + this._recording = false; + this._replaying = false; // playing a macro this._modeStack = update([], { pop: function pop() { @@ -119,9 +119,9 @@ var Modes = Module("modes", { _getModeMessage: function () { // when recording a macro let macromode = ""; - if (modes.isRecording) + if (modes.recording) macromode = "recording"; - else if (modes.isReplaying) + else if (modes.replaying) macromode = "replaying"; let ext = ""; @@ -323,11 +323,11 @@ var Modes = Module("modes", { } }, - get isRecording() this._isRecording, - set isRecording(value) { this._isRecording = value; this.show(); }, + get recording() this._recording, + set recording(value) { this._recording = value; this.show(); }, - get isReplaying() this._isReplaying, - set isReplaying(value) { this._isReplaying = value; this.show(); }, + get replaying() this._replaying, + set replaying(value) { this._replaying = value; this.show(); }, get main() this._main, set main(value) { this.set(value); }, From cd55bfbcb1d0fd28f432aa6b7f81fff630d387c3 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 26 Dec 2010 14:41:10 -0500 Subject: [PATCH 3/4] Fix macro interpolation of null counts in key bindings. --- common/content/commands.js | 8 ++++---- common/modules/util.jsm | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index b650f464..ea26975d 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -335,14 +335,14 @@ var Command = Class("Command", { case "-keys": let silent = args["-silent"]; rhs = events.canonicalKeys(rhs, true); - let macro = util.compileMacro(rhs, true); - var action = function action(count) events.feedkeys(macro({ count: count }), + var action = function action(count) events.feedkeys(action.macro({ count: count || "" }), noremap, silent); + action.macro = util.compileMacro(rhs, true); break; case "-ex": - macro = util.compileMacro(rhs, true); - action = function action() commands.execute(macro, makeParams.apply(this, arguments), + action = function action() commands.execute(action.macro, makeParams.apply(this, arguments), false, null, action.sourcing); + action.macro = util.compileMacro(rhs, true); action.sourcing = io.sourcing && update({}, io.sourcing); break; case "-javascript": diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 919b1221..50ed3c9a 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -328,7 +328,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), stack.top.elements.push(quote(defaults[name])); else { stack.top.elements.push(update( - function (obj) obj[name] != null ? quote(obj[name]) : unknown(full), + function (obj) obj[name] != null ? quote(obj[name]) : set.has(obj, name) ? "" : unknown(full), { test: function (obj) obj[name] != null && obj[name] !== false })); for (let elem in array.iterValues(stack)) From acd7ce68c06bcad64392149a12a213d89f1aedc8 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 26 Dec 2010 14:47:06 -0500 Subject: [PATCH 4/4] Fix typo that breaks parsing of command line arguments. --- common/content/dactyl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/content/dactyl.js b/common/content/dactyl.js index ca2e011a..48848609 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -2069,7 +2069,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { if (!services.commandLineHandler) services.add("commandLineHandler", "@mozilla.org/commandlinehandler/general-startup;1?type=" + config.name); - if (services.commandlinehandler) { + if (services.commandLineHandler) { let commandline = services.commandLineHandler.optionValue; if (commandline) { let args = dactyl.parseCommandLine(commandline);