summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcommon/bootstrap.js2
-rw-r--r--common/content/buffer.js54
-rw-r--r--common/content/commandline.js29
-rw-r--r--common/content/dactyl.js4
-rw-r--r--common/content/statusline.js39
-rw-r--r--common/modules/storage.jsm64
-rw-r--r--common/modules/util.jsm94
-rw-r--r--common/skin/dactyl.css2
8 files changed, 163 insertions, 125 deletions
diff --git a/common/bootstrap.js b/common/bootstrap.js
index 1d64596b..21514102 100755
--- a/common/bootstrap.js
+++ b/common/bootstrap.js
@@ -171,10 +171,10 @@ function init() {
function shutdown(data, reason) {
dump("dactyl: bootstrap: shutdown\n");
+ services.observer.notifyObservers(null, "dactyl-cleanup", null);
for (let factory in values(components))
// TODO: Categories;
factory.unregister();
- services.observer.notifyObservers(null, "dactyl-cleanup", null);
}
function reasonToString(reason) {
diff --git a/common/content/buffer.js b/common/content/buffer.js
index 456062e8..04dc93ed 100644
--- a/common/content/buffer.js
+++ b/common/content/buffer.js
@@ -147,6 +147,40 @@ const Buffer = Module("buffer", {
let elem = event.originalTarget;
buffer.viewSource([elem.getAttribute("href"), Number(elem.getAttribute("line"))])
};
+
+ this.replaceProgressListener(this.progressListener);
+ },
+
+ cleanup: function () {
+ for (let prop in properties(this.progressListener))
+ if (!this.progressListener.__lookupGetter__(prop) &&
+ !callable(this.progressListener[prop]))
+ this.origProgressListener[prop] = this.progressListener[prop]
+
+ this.replaceProgressListener(this.origProgressListener);
+ },
+
+ replaceProgressListener: function (newListener) {
+ // I hate this whole hack. --Kris
+ let obj = window.XULBrowserWindow, getter;
+ for (let prop in properties(obj))
+ if ((getter = obj.__lookupGetter__(prop)) && !obj.__lookupSetter__(prop)) {
+ newListener.__defineGetter__(prop, getter);
+ delete obj[prop];
+ }
+
+ this.origProgressListener = window.XULBrowserWindow;
+ try {
+ config.browser.removeProgressListener(window.XULBrowserWindow);
+ }
+ catch (e) {} // Why? --djk
+
+ config.browser.addProgressListener(newListener, Ci.nsIWebProgress.NOTIFY_ALL);
+ window.XULBrowserWindow = newListener;
+ window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
+ .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
+ .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIXULWindow)
+ .XULBrowserWindow = newListener;
},
destroy: function () {
@@ -1502,26 +1536,6 @@ const Buffer = Module("buffer", {
};
},
events: function () {
- try {
- config.browser.removeProgressListener(window.XULBrowserWindow);
- }
- catch (e) {} // Why? --djk
-
- // I hate this whole hack. --Kris
- let obj = window.XULBrowserWindow, getter;
- for (let p in properties(obj))
- if ((getter = obj.__lookupGetter__(p)) && !obj.__lookupSetter__(p)) {
- this.progressListener.__defineGetter__(p, getter);
- delete obj[p];
- }
-
- config.browser.addProgressListener(this.progressListener, Ci.nsIWebProgress.NOTIFY_ALL);
- window.XULBrowserWindow = this.progressListener;
- window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
- .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIXULWindow)
- .XULBrowserWindow = this.progressListener;
-
events.addSessionListener(config.browser, "DOMContentLoaded", this.closure.onDOMContentLoaded, true);
events.addSessionListener(config.browser, "load", this.closure.onPageLoad, true);
events.addSessionListener(config.browser, "scroll", this.closure._updateBufferPosition, false);
diff --git a/common/content/commandline.js b/common/content/commandline.js
index e4ca3534..3454f0e0 100644
--- a/common/content/commandline.js
+++ b/common/content/commandline.js
@@ -135,9 +135,25 @@ const CommandWidgets = Class("CommandWidgets", {
getGroup: function (value) {
if (this.command && !options.get("guioptions").has("M"))
return this.statusbar;
+
let statusElem = this.statusbar.message;
- if (value && statusElem.inputField.editor.rootElement.scrollWidth > statusElem.scrollWidth)
- return this.commandbar;
+ if (!statusElem.editor) {
+ util.dump(commandline == window.dactyl.modules.commandline,
+ window.dactyl.modules.commandline.widgets == this,
+ commandline.widgets == this);
+ util.dumpStack();
+
+ for (let i=0, e = statusElem; e; e = e.parentNode)
+ util.dump(i++, e == statusline._statusLine.firstChild,
+ e == statusline.widgets.container,
+ e);
+ util.dump(statusElem == statusline.widgets.message);
+ util.dump(statusline._statusLine.firstChild == statusline.widgets.container);
+ }
+ else {
+ if (value && statusElem.editor.rootElement.scrollWidth > statusElem.scrollWidth)
+ return this.commandbar;
+ }
return this.activeGroup.mode;
}
});
@@ -165,13 +181,13 @@ const CommandWidgets = Class("CommandWidgets", {
const self = this;
this.elements[obj.name] = obj;
- function get(id) obj.getElement ? obj.getElement(id) : document.getElementById(id);
+ function get(prefix, map, id) (obj.getElement || util.identity)(map[id] || document.getElementById(prefix + id));
this.active.__defineGetter__(obj.name, function () self.activeGroup[obj.name][obj.name]);
this.activeGroup.__defineGetter__(obj.name, function () self.getGroup(obj.name));
- memoize(this.statusbar, obj.name, function () get("dactyl-statusline-field-" + (obj.id || obj.name)));
- memoize(this.commandbar, obj.name, function () get("dactyl-" + (obj.id || obj.name)));
+ memoize(this.statusbar, obj.name, function () get("dactyl-statusline-field-", statusline.widgets, (obj.id || obj.name)));
+ memoize(this.commandbar, obj.name, function () get("dactyl-", {}, (obj.id || obj.name)));
if (!(obj.noValue || obj.getValue))
Object.defineProperty(this, obj.name, Modes.boundProperty({
@@ -259,8 +275,7 @@ const CommandWidgets = Class("CommandWidgets", {
multilineInput: Class.memoize(function () document.getElementById("dactyl-multiline-input")),
mowContainer: Class.memoize(function () this.multilineOutput.parentNode)
}, {
- getEditor: function (id) {
- let elem = document.getElementById(id);
+ getEditor: function (elem) {
elem.inputField.QueryInterface(Ci.nsIDOMNSEditableElement);
return elem;
}
diff --git a/common/content/dactyl.js b/common/content/dactyl.js
index b5e04249..eaeaa7fc 100644
--- a/common/content/dactyl.js
+++ b/common/content/dactyl.js
@@ -53,13 +53,15 @@ const Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase),
observe: {
"dactyl-cleanup": function () {
- for (let [, mod] in iter(array(values(modules)).reverse()))
+ for (let name in values(Object.getOwnPropertyNames(modules).reverse())) {
+ let mod = modules[name];
if (mod instanceof ModuleBase) {
if ("cleanup" in mod)
mod.cleanup();
if ("destroy" in mod)
mod.destroy();
}
+ }
}
},
diff --git a/common/content/statusline.js b/common/content/statusline.js
index 44dc84b9..22541a22 100644
--- a/common/content/statusline.js
+++ b/common/content/statusline.js
@@ -10,6 +10,19 @@
const StatusLine = Module("statusline", {
init: function () {
+ this._statusLine = document.getElementById("status-bar");
+ this.statusBar = document.getElementById("addon-bar") || this._statusLine;
+ this.statusBar.collapsed = true; // it is later restored unless the user sets laststatus=0
+
+ if (this.statusBar.localName == "toolbar") {
+ styles.system.add("addon-bar", config.styleableChrome, <css><![CDATA[
+ #status-bar { margin-top: 0 !important; }
+ #addon-bar { padding: 0 !important; min-height: 18px !important; }
+ #addon-bar > statusbar { -moz-box-flex: 1 }
+ #addon-bar > #addonbar-closebutton { visibility: collapse; }
+ #addon-bar > xul|toolbarspring { visibility: collapse; }
+ ]]></css>);
+ }
let _commandline = "if (window.dactyl) return dactyl.modules.commandline";
let prepend = <e4x xmlns={XUL} xmlns:dactyl={NS}>
@@ -21,8 +34,8 @@ const StatusLine = Module("statusline", {
<hbox class="dactyl-container" dactyl:highlight="CmdLine StatusCmdLine">
<label class="plain" key="mode" crop="end" collapsed="true"/>
<stack flex="1" class="dactyl-container" dactyl:highlight="CmdLine StatusCmdLine">
- <textbox class="plain" key="url" crop="end" flex="1" readonly="true"/>
- <textbox class="plain" key="message" crop="end" flex="1" readonly="true" dactyl:highlight="Normal StatusNormal"/>
+ <textbox key="url" crop="end" flex="1" readonly="true" class="plain dactyl-status-field-url"/>
+ <textbox key="message" crop="end" flex="1" readonly="true" class="plain" dactyl:highlight="Normal StatusNormal"/>
</stack>
</hbox>
@@ -45,31 +58,11 @@ const StatusLine = Module("statusline", {
</statusbar>
</e4x>;
- for each (let attr in prepend..@key)
- attr.parent().@id = "dactyl-statusline-field-" + attr;
-
+ util.dump("statusbar: load overlay");
util.overlayWindow(window, {
objects: this.widgets = { get status() this.container },
prepend: prepend.elements()
});
-
- this._statusLine = document.getElementById("status-bar");
- this.statusBar = document.getElementById("addon-bar") || this._statusLine;
- this.statusBar.collapsed = true; // it is later restored unless the user sets laststatus=0
-
-
- if (this.statusBar.localName == "toolbar") {
- styles.system.add("addon-bar", config.styleableChrome, <css><![CDATA[
- #status-bar { margin-top: 0 !important; }
- #addon-bar { padding: 0 !important; min-height: 18px !important; }
- #addon-bar > statusbar { -moz-box-flex: 1 }
- #addon-bar > #addonbar-closebutton { visibility: collapse; }
- #addon-bar > xul|toolbarspring { visibility: collapse; }
- ]]></css>);
- let parent = this.widgets.status.parentNode;
- parent.removeChild(this.widgets.status);
- parent.insertBefore(this.widgets.status, parent.firstChild);
- }
},
get visible() !this.statusBar.collapsed && !this.statusBar.hidden,
diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm
index 730e3dde..6e06377b 100644
--- a/common/modules/storage.jsm
+++ b/common/modules/storage.jsm
@@ -142,25 +142,39 @@ const ObjectStore = Class("ObjectStore", StoreBase, {
__iterator__: function () Iterator(this._object),
});
-var keys = {};
-var observers = {};
-
const Storage = Module("Storage", {
alwaysReload: {},
+ init: function () {
+ this.cleanup();
+ },
+
+ cleanup: function () {
+ for (let key in keys(this.keys))
+ delete this[key];
+ for (let ary in values(this.observers))
+ for (let obj in values(ary))
+ if (obj.ref && obj.ref.get())
+ delete obj.ref.get().dactylStorageRefs;
+
+ this.keys = {};
+ this.observers = {};
+ },
+
newObject: function newObject(key, constructor, params) {
if (params == null || !isObject(params))
throw Error("Invalid argument type");
- if (!(key in keys) || params.reload || this.alwaysReload[key]) {
+ if (!(key in this.keys) || params.reload || this.alwaysReload[key]) {
if (key in this && !(params.reload || this.alwaysReload[key]))
throw Error();
let load = function () loadData(key, params.store, params.type || myObject);
- keys[key] = new constructor(key, params.store, load, params);
- keys[key].timer = new Timer(1000, 10000, function () storage.save(key));
- this.__defineGetter__(key, function () keys[key]);
+
+ this.keys[key] = new constructor(key, params.store, load, params);
+ this.keys[key].timer = new Timer(1000, 10000, function () storage.save(key));
+ this.__defineGetter__(key, function () this.keys[key]);
}
- return keys[key];
+ return this.keys[key];
},
newMap: function newMap(key, options) {
@@ -182,38 +196,36 @@ const Storage = Module("Storage", {
callbackRef = { get: function () callback };
}
this.removeDeadObservers();
- if (!(key in observers))
- observers[key] = [];
- if (!observers[key].some(function (o) o.callback.get() == callback))
- observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
+ if (!(key in this.observers))
+ this.observers[key] = [];
+ if (!this.observers[key].some(function (o) o.callback.get() == callback))
+ this.observers[key].push({ ref: ref && Cu.getWeakReference(ref), callback: callbackRef });
},
removeObserver: function (key, callback) {
this.removeDeadObservers();
- if (!(key in observers))
+ if (!(key in this.observers))
return;
- observers[key] = observers[key].filter(function (elem) elem.callback.get() != callback);
- if (observers[key].length == 0)
+ this.observers[key] = this.observers[key].filter(function (elem) elem.callback.get() != callback);
+ if (this.observers[key].length == 0)
delete obsevers[key];
},
removeDeadObservers: function () {
- for (let [key, ary] in Iterator(observers)) {
- observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().dactylStorageRefs));
+ for (let [key, ary] in Iterator(this.observers)) {
+ this.observers[key] = ary = ary.filter(function (o) o.callback.get() && (!o.ref || o.ref.get() && o.ref.get().dactylStorageRefs));
if (!ary.length)
- delete observers[key];
+ delete this.observers[key];
}
},
- get observers() observers,
-
fireEvent: function fireEvent(key, event, arg) {
this.removeDeadObservers();
- if (key in observers)
+ if (key in this.observers)
// Safe, since we have our own Array object here.
- for each (let observer in observers[key])
+ for each (let observer in this.observers[key])
observer.callback.get()(key, event, arg);
- if (key in keys)
+ if (key in this.keys)
this[key].timer.tell();
},
@@ -223,11 +235,11 @@ const Storage = Module("Storage", {
},
save: function save(key) {
- saveData(keys[key]);
+ saveData(this.keys[key]);
},
saveAll: function storeAll() {
- for each (let obj in keys)
+ for each (let obj in this.keys)
saveData(obj);
},
@@ -237,7 +249,7 @@ const Storage = Module("Storage", {
if (val && !this._privateMode)
this.saveAll();
if (!val && this._privateMode)
- for (let key in keys)
+ for (let key in this.keys)
this.load(key);
return this._privateMode = Boolean(val);
}
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index be16ed9e..4acf60b7 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -57,8 +57,8 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
cleanup: function cleanup() {
for (let win in iter(services.windowMediator.getEnumerator(null))) {
for (let elem in values(win.document.dactylOverlayElements || []))
- if (elem.get() && elem.get().parentNode)
- elem.get().parentNode.removeChild(elem.get());
+ if (elem.parentNode)
+ elem.parentNode.removeChild(elem);
delete win.document.dactylOverlayElements;
delete win.document.dactylOverlays;
}
@@ -849,7 +849,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
let tag = "<" + [namespaced(elem)].concat(
[namespaced(a) + "=" + template.highlight(a.value, true)
for ([i, a] in array.iterItems(elem.attributes))]).join(" ");
- return tag + (hasChildren ? "/>" : ">...</" + namespaced(elem) + ">");
+ return tag + (!hasChildren ? "/>" : ">...</" + namespaced(elem) + ">");
}
catch (e) {
return {}.toString.call(elem);
@@ -907,6 +907,47 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
return color ? string : [s for each (s in string)].join("");
},
+ observe: {
+ "dactyl-cleanup": function () {
+ util.dump("dactyl: util: observe: dactyl-cleanup");
+ // Let window cleanup functions run synchronously before we
+ // destroy modules.
+ util.timeout(function () {
+ for (let module in values(defineModule.modules))
+ if (module.cleanup)
+ module.cleanup();
+
+ services.observer.addObserver(this, "dactyl-rehash", true);
+
+ /*
+ let getOwnPropertyNames = Object.getOwnPropertyNames;
+ for each (let global in defineModule.globals.reverse())
+ for each (let k in getOwnPropertyNames(global))
+ try {
+ delete global[k];
+ }
+ catch (e) {}
+ */
+ });
+ },
+ "dactyl-rehash": function () {
+ util.dump("dactyl: util: observe: dactyl-rehash");
+ for (let module in values(defineModule.modules))
+ if (module.reinit)
+ module.reinit();
+ else
+ module.init();
+ },
+ "toplevel-window-ready": function (window, data) {
+ window.addEventListener("DOMContentLoaded", wrapCallback(function listener(event) {
+ if (event.originalTarget === window.document) {
+ window.removeEventListener("DOMContentLoaded", listener.wrapper, true);
+ util._loadOverlays(window);
+ }
+ }), true)
+ }
+ },
+
_loadOverlays: function _loadOverlays(window) {
if (!window.dactylOverlays)
window.dactylOverlays = [];
@@ -925,17 +966,19 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
if (!doc.dactylOverlayElements)
doc.dactylOverlayElements = [];
+ util.dump("load overlay", doc.documentURI, String(obj).substr(0, 60));
+
function overlay(key, fn) {
if (obj[key]) {
let iterator = Iterator(obj[key]);
if (!isObject(obj[key]))
- iterator = ([elem.@id, elem.*, elem.@*::*] for each (elem in obj[key]));
+ iterator = ([elem.@id, elem.elements(), elem.@*::*.(function::name() != "id")] for each (elem in obj[key]));
for (let [elem, xml, attr] in iterator) {
if (elem = doc.getElementById(elem)) {
let node = util.xmlToDom(xml, doc, obj.objects);
for (let n in array.iterValues(node.childNodes))
- doc.dactylOverlayElements.push(Cu.getWeakReference(n));
+ doc.dactylOverlayElements.push(n);
fn(elem, node);
for each (let attr in attr || []) // FIXME: Cleanup...
elem.setAttributeNS(attr.namespace(), attr.localName(), attr);
@@ -963,47 +1006,6 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference])
}), true);
},
- observe: {
- "dactyl-cleanup": function () {
- util.dump("dactyl: util: observe: dactyl-cleanup");
- // Let window cleanup functions run synchronously before we
- // destroy modules.
- util.timeout(function () {
- for (let module in values(defineModule.modules))
- if (module.cleanup)
- module.cleanup();
-
- services.observer.addObserver(this, "dactyl-rehash", true);
-
- /*
- let getOwnPropertyNames = Object.getOwnPropertyNames;
- for each (let global in defineModule.globals.reverse())
- for each (let k in getOwnPropertyNames(global))
- try {
- delete global[k];
- }
- catch (e) {}
- */
- });
- },
- "dactyl-rehash": function () {
- util.dump("dactyl: util: observe: dactyl-rehash");
- for (let module in values(defineModule.modules))
- if (module.reinit)
- module.reinit();
- else
- module.init();
- },
- "toplevel-window-ready": function (window, data) {
- window.addEventListener("DOMContentLoaded", wrapCallback(function listener(event) {
- if (event.originalTarget === window.document) {
- window.removeEventListener("DOMContentLoaded", listener.wrapper, true);
- util._loadOverlays(window);
- }
- }), true)
- }
- },
-
overlayWindow: function (url, fn) {
if (url instanceof Ci.nsIDOMWindow)
util._loadOverlay(url, fn);
diff --git a/common/skin/dactyl.css b/common/skin/dactyl.css
index 200c3500..f145dacd 100644
--- a/common/skin/dactyl.css
+++ b/common/skin/dactyl.css
@@ -122,7 +122,7 @@ statusbarpanel {
background: transparent;
}
-#dactyl-statusline-field-url {
+.dactyl-status-field-url {
background-color: inherit !important;
color: inherit !important;
}