summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/content/autocommands.js12
-rw-r--r--common/content/buffer.js6
-rw-r--r--common/content/commands.js20
-rw-r--r--common/content/contexts.js41
-rw-r--r--common/content/dactyl.js4
-rw-r--r--common/content/events.js70
-rw-r--r--common/content/hints.js2
-rw-r--r--common/content/mappings.js18
-rw-r--r--common/content/marks.js2
-rw-r--r--common/content/tabs.js4
-rw-r--r--common/modules/styles.jsm1
11 files changed, 123 insertions, 57 deletions
diff --git a/common/content/autocommands.js b/common/content/autocommands.js
index 81e38fac..e24d2e6e 100644
--- a/common/content/autocommands.js
+++ b/common/content/autocommands.js
@@ -17,16 +17,12 @@ update(AutoCommand.prototype, {
}
});
-var AutoCmdHive = Class("AutoCmdHive", {
+var AutoCmdHive = Class("AutoCmdHive", Group.Hive, {
init: function init(group) {
- this.group = group;
+ init.supercall(this, group);
this._store = [];
},
- get toStringParams() [this.group.name],
-
- get builtin() this.group.builtin,
-
__iterator__: function () array.iterValues(this._store),
/**
@@ -111,7 +107,7 @@ var AutoCommands = Module("autocommands", {
{
template.map(this.activeHives, function (hive)
<tr highlight="Title">
- <td colspan="3">{hive.group.name}</td>
+ <td colspan="3">{hive.name}</td>
</tr> +
<tr style="height: .5ex;"/> +
template.map(cmds(hive), function ([event, items])
@@ -148,7 +144,7 @@ var AutoCommands = Module("autocommands", {
event = event.toLowerCase();
for (let hive in this.hives.iterValues()) {
let args = update({},
- hive.group.argsExtra(arguments[1]),
+ hive.argsExtra(arguments[1]),
arguments[1]);
for (let autoCmd in values(hive._store))
diff --git a/common/content/buffer.js b/common/content/buffer.js
index b5e4d1ed..4b691261 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -1644,9 +1644,9 @@ var Buffer = Module("buffer", {
};
},
events: function () {
- events.addSessionListener(config.browser, "DOMContentLoaded", buffer.closure.onDOMContentLoaded, true);
- events.addSessionListener(config.browser, "load", buffer.closure.onPageLoad, true);
- events.addSessionListener(config.browser, "scroll", buffer.closure._updateBufferPosition, false);
+ events.listen(config.browser, "DOMContentLoaded", buffer.closure.onDOMContentLoaded, true);
+ events.listen(config.browser, "load", buffer.closure.onPageLoad, true);
+ events.listen(config.browser, "scroll", buffer.closure._updateBufferPosition, false);
},
mappings: function () {
var myModes = config.browserModes;
diff --git a/common/content/commands.js b/common/content/commands.js
index 981ea8cd..86d2e670 100644
--- a/common/content/commands.js
+++ b/common/content/commands.js
@@ -127,7 +127,7 @@ var Command = Class("Command", {
this.options = this.options.map(CommandOption.fromArray, CommandOption);
},
- get toStringParams() [this.name, this.hive.group.name],
+ get toStringParams() [this.name, this.hive.name],
get helpTag() ":" + this.name,
@@ -155,8 +155,8 @@ var Command = Class("Command", {
if (args.bang && !this.bang)
throw FailedAssertion("E477: No ! allowed");
- return !dactyl.trapErrors(function exec(command) {
- // update({}, command.hive.group.argsExtra(args), args);
+ return !dactyl.trapErrors(function exec() {
+ update({}, this.hive.argsExtra(args), args);
if (this.always)
this.always(args, modifiers);
@@ -397,17 +397,13 @@ var ex = {
__noSuchMethod__: function (meth, args) this._run(meth).apply(this, args)
};
-var CommandHive = Class("CommandHive", {
+var CommandHive = Class("CommandHive", Group.Hive, {
init: function init(group) {
- this.group = group;
+ init.supercall(this, group);
this._map = {};
this._list = [];
},
- get toStringParams() [this.group.name],
-
- get builtin() this.group.builtin,
-
/** @property {Iterator(Command)} @private */
__iterator__: function () array.iterValues(this._list.sort(function (a, b) a.name > b.name)),
@@ -610,7 +606,7 @@ var Commands = Module("commands", {
template.map(hive, function (cmd)
template.map(cmd.names, function (name)
<tr>
- <td highlight="Title">{!i++ ? hive.group.name : ""}</td>
+ <td highlight="Title">{!i++ ? hive.name : ""}</td>
<td>{cmd.bang ? "!" : " "}</td>
<td>{cmd.name}</td>
<td>{cmd.argCount}</td>
@@ -1425,7 +1421,7 @@ var Commands = Module("commands", {
literal: 1,
serialize: function () array(commands.userHives)
- .filter(function (h) h.group.persist)
+ .filter(function (h) h.persist)
.map(function (hive) [
{
command: this.name,
@@ -1485,7 +1481,7 @@ var Commands = Module("commands", {
iterate: function (args) commands.iterator().map(function (cmd) ({
__proto__: cmd,
columns: [
- cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.group.name}</span>
+ cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.name}</span>
]
})),
format: {
diff --git a/common/content/contexts.js b/common/content/contexts.js
index e3f2a0d4..9e57e90f 100644
--- a/common/content/contexts.js
+++ b/common/content/contexts.js
@@ -16,8 +16,11 @@ var Group = Class("Group", {
cleanup: function cleanup() {
for (let hive in values(this.hives))
- if (hive.cleanup)
- hive.cleanup();
+ dactyl.trapErrors("cleanup", hive);
+ },
+ destroy: function destroy() {
+ for (let hive in values(this.hives))
+ dactyl.trapErrors("destroy", hive);
},
argsExtra: function argsExtra() ({}),
@@ -58,6 +61,32 @@ var Group = Class("Group", {
hiveMap: {},
+ Hive: Class("Hive", {
+ init: function init(group) {
+ this.group = group;
+ },
+
+ cleanup: function cleanup() {},
+ destroy: function destroy() {},
+
+ get argsExtra() this.group.argsExtra,
+ get builtin() this.group.builtin,
+
+ get name() this.group.name,
+ set name(val) this.group.name = val,
+
+ get description() this.group.description,
+ set description(val) this.group.description = val,
+
+ get filter() this.group.filter,
+ set filter(val) this.group.filter = val,
+
+ get persist() this.group.persist,
+ set persist(val) this.group.persist = val,
+
+ get toStringParams() [this.name]
+ }),
+
Hives: Class("Hives", Class.Property, {
init: function init(name, constructor) {
const self = this;
@@ -100,6 +129,13 @@ var Contexts = Module("contexts", {
this.builtinGroups = [this.system, this.user];
},
+ destroy: function () {
+ for (let hive in values(this.groupList)) {
+ dactyl.trapErrors("cleanup", hive);
+ dactyl.trapErrors("destroy", hive);
+ }
+ },
+
context: null,
groups: Class.memoize(function () Object.create(Group.groupsProto, {
@@ -145,6 +181,7 @@ var Contexts = Module("contexts", {
if (group) {
this.groupList.splice(this.groupList.indexOf(group), 1);
group.cleanup();
+ group.destroy();
}
if (this.context && this.context.group === group)
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index cddbf583..ee2c9b3a 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -1459,8 +1459,8 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
}
}, {
events: function () {
- events.addSessionListener(window, "click", dactyl.closure.onClick, true);
- events.addSessionListener(window, "dactyl.execute", dactyl.closure.onExecute, true);
+ events.listen(window, "click", dactyl.closure.onClick, true);
+ events.listen(window, "dactyl.execute", dactyl.closure.onExecute, true);
},
// Only general options are added here, which are valid for all Dactyl extensions
options: function () {
diff --git a/common/content/events.js b/common/content/events.js
index 26217d4a..bebd5808 100644
--- a/common/content/events.js
+++ b/common/content/events.js
@@ -255,6 +255,54 @@ var KeyArgProcessor = Class("KeyArgProcessor", KeyProcessor, {
}
});
+var EventHive = Class("EventHive", Group.Hive, {
+ init: function init(group) {
+ init.supercall(this, group);
+ this.sessionListeners = [];
+ },
+
+ cleanup: function cleanup() {
+ this.unlisten(null);
+ },
+
+ /**
+ * 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.
+ */
+ listen: function (target, event, callback, capture) {
+ let args = Array.slice(arguments, 0);
+ args[2] = this.wrapListener(callback);
+ args[0].addEventListener.apply(args[0], args.slice(1));
+ args[0] = Cu.getWeakReference(args[0]);
+ this.sessionListeners.push(args);
+ },
+
+ /**
+ * Remove an event listener.
+ *
+ * @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.
+ */
+ unlisten: function (target, event, callback, capture) {
+ this.sessionListeners = this.sessionListeners.filter(function (args) {
+ if (target == null || args[0].get() == target && args[1] == event && args[2] == callback && args[3] == capture) {
+ args[0].get().removeEventListener.apply(args[0].get(), args.slice(1));
+ return true;
+ }
+ return !args[0].get();
+ });
+ }
+});
+
/**
* @instance events
*/
@@ -283,7 +331,9 @@ var Events = Module("events", {
this._macroKeys = [];
this._lastMacro = "";
- this.sessionListeners = [];
+ EventHive.prototype.wrapListener = this.closure.wrapListener;
+ this.user = contexts.hives.events.user;
+ this.builtin = contexts.hives.events.builtin;
this._macros = storage.newMap("macros", { privateData: true, store: true });
for (let [k, m] in this._macros)
@@ -344,19 +394,14 @@ var Events = Module("events", {
this._activeMenubar = false;
for (let [event, callback] in Iterator(this.events))
- this.addSessionListener(window, event, callback, true);
+ this.listen(window, event, callback, true);
dactyl.registerObserver("modeChange", function () {
delete self.processor;
});
},
- destroy: function () {
- util.dump("Removing all event listeners");
- for (let args in values(this.sessionListeners))
- if (args[0].get())
- args[0].get().removeEventListener.apply(args[0].get(), args.slice(1));
- },
+ hives: Group.Hives("events", EventHive),
/**
* Adds an event listener for this session and removes it on
@@ -368,13 +413,8 @@ var Events = Module("events", {
* @param {boolean} capture When true, listen during the capture
* phase, otherwise during the bubbling phase.
*/
- addSessionListener: function (target, event, callback, capture) {
- let args = Array.slice(arguments, 0);
- args[2] = this.wrapListener(callback);
- args[0].addEventListener.apply(args[0], args.slice(1));
- args[0] = Cu.getWeakReference(args[0]);
- this.sessionListeners.push(args);
- },
+ get addSessionListener() this.builtin.closure.listen,
+ get listen() this.builtin.closure.listen,
/**
* Wraps an event listener to ensure that errors are reported.
diff --git a/common/content/hints.js b/common/content/hints.js
index 9a9a7502..7b6d6d52 100644
--- a/common/content/hints.js
+++ b/common/content/hints.js
@@ -677,7 +677,7 @@ var Hints = Module("hints", {
let appContent = document.getElementById("appcontent");
if (appContent)
- events.addSessionListener(appContent, "scroll", this.resizeTimer.closure.tell, false);
+ events.listen(appContent, "scroll", this.resizeTimer.closure.tell, false);
const Mode = Hints.Mode;
Mode.defaultValue("tags", function () function () options["hinttags"]);
diff --git a/common/content/mappings.js b/common/content/mappings.js
index 3f05549a..9512e087 100644
--- a/common/content/mappings.js
+++ b/common/content/mappings.js
@@ -108,7 +108,7 @@ var Map = Class("Map", {
.toObject();
args = update({ context: contexts.context },
- this.hive.group.argsExtra(args),
+ this.hive.argsExtra(args),
args);
let self = this;
@@ -138,16 +138,12 @@ var Map = Class("Map", {
id: 0
});
-var MapHive = Class("MapHive", {
+var MapHive = Class("MapHive", Group.Hive, {
init: function init(group) {
- this.group = group;
+ init.supercall(this, group);
this.stacks = {};
},
- get toStringParams() [this.group.name],
-
- get builtin() this.group.builtin,
-
/**
* Iterates over all mappings present in all of the given *modes*.
*
@@ -423,7 +419,7 @@ var Mappings = Module("mappings", {
template.map(maps(hive), function (map)
template.map(map.names, function (name, i)
<tr>
- <td highlight="Title">{!i ? hive.group.name : ""}</td>
+ <td highlight="Title">{!i ? hive.name : ""}</td>
<td>{modeSign}</td>
<td>{name}</td>
<td>{map.rhs || map.action.toSource()}</td>
@@ -532,12 +528,12 @@ var Mappings = Module("mappings", {
serialize: function () {
return this.name != "map" ? [] :
array(mappings.userHives)
- .filter(function (h) h.group.persist)
+ .filter(function (h) h.persist)
.map(function (hive) [
{
command: "map",
options: array([
- hive !== mappings.user && ["-group", hive.group.name],
+ hive !== mappings.user && ["-group", hive.name],
["-modes", uniqueModes(map.modes)],
["-description", map.description],
map.silent && ["-silent"]])
@@ -678,7 +674,7 @@ var Mappings = Module("mappings", {
name: name,
columns: [
mode == mainMode ? "" : <span highlight="Object" style="padding-right: 1em;">{mode.name}</span>,
- hive == mappings.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{hive.group.name}</span>
+ hive == mappings.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{hive.name}</span>
],
__proto__: map
};
diff --git a/common/content/marks.js b/common/content/marks.js
index 729e23ac..b7df2c89 100644
--- a/common/content/marks.js
+++ b/common/content/marks.js
@@ -208,7 +208,7 @@ var Marks = Module("marks", {
events: function () {
let appContent = document.getElementById("appcontent");
if (appContent)
- events.addSessionListener(appContent, "load", marks.closure._onPageLoad, true);
+ events.listen(appContent, "load", marks.closure._onPageLoad, true);
},
mappings: function () {
var myModes = config.browserModes;
diff --git a/common/content/tabs.js b/common/content/tabs.js
index 13ec4df4..d14d8bbc 100644
--- a/common/content/tabs.js
+++ b/common/content/tabs.js
@@ -874,8 +874,8 @@ var Tabs = Module("tabs", {
tabs.timeout(function () { this.updateTabCount(); });
}
for (let event in values(["TabMove", "TabOpen", "TabClose"]))
- events.addSessionListener(tabContainer, event, callback, false);
- events.addSessionListener(tabContainer, "TabSelect", tabs.closure._onTabSelect, false);
+ events.listen(tabContainer, event, callback, false);
+ events.listen(tabContainer, "TabSelect", tabs.closure._onTabSelect, false);
},
mappings: function () {
mappings.add([modes.NORMAL], ["g0", "g^"],
diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm
index a7259259..aebdc528 100644
--- a/common/modules/styles.jsm
+++ b/common/modules/styles.jsm
@@ -93,6 +93,7 @@ var Hive = Class("Hive", {
for (let sheet in values(this.sheets))
sheet.enabled = false;
},
+ destroy: function destroy() {},
__iterator__: function () Iterator(this.sheets),