summaryrefslogtreecommitdiff
path: root/chrome/content/topmenuservice.js
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/content/topmenuservice.js')
-rw-r--r--chrome/content/topmenuservice.js98
1 files changed, 64 insertions, 34 deletions
diff --git a/chrome/content/topmenuservice.js b/chrome/content/topmenuservice.js
index 494ea3e..96d0e6c 100644
--- a/chrome/content/topmenuservice.js
+++ b/chrome/content/topmenuservice.js
@@ -1,3 +1,5 @@
+"use strict";
+
var EXPORTED_SYMBOLS = ["TopMenuService"];
var Cu = Components.utils;
@@ -42,13 +44,23 @@ function getTopLevelGdkWindow(w) {
function createMutationObserver(window, proxy)
{
return new window.MutationObserver(function(mutations) {
- mutations.forEach(function(mutation) {
- proxy.handleMutation(mutation);
- });
+ try {
+ mutations.forEach(function(mutation) {
+ proxy.handleMutation(mutation);
+ });
+ } catch (ex) {
+ log.warn("Exception processing menubar changes: " + ex);
+ }
});
}
function WindowProxy(window) {
+ var menubars = window.document.getElementsByTagNameNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'menubar');
+ if (menubars.length === 0) {
+ // No menubars, give up constructing the object
+ return;
+ }
+
this.srcWindow = window;
this.srcMenuBar = null;
this.observer = null;
@@ -106,6 +118,7 @@ function WindowProxy(window) {
}
}
+ // Initialize the Gtk widgets for this window
this.accelGroup = gobject.ref_sink(gtk.gtk_accel_group_new());
this.appMenuBar = gobject.ref_sink(topmenu_client.topmenu_app_menu_bar_new());
@@ -113,48 +126,57 @@ function WindowProxy(window) {
topmenu_client.topmenu_client_connect_window_widget(this.gdkWindow, this.appMenuBar);
- var menubars = window.document.getElementsByTagNameNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'menubar');
- if (menubars.length > 0) {
- this.srcMenuBar = menubars[0];
- this.observer = createMutationObserver(window, this);
- this.observer.observe(this.srcMenuBar, {
- childList: true,
- attributes: true,
- subtree: true
- });
-
- // Let's find currently added menu items and proxy them
- this.srcMenuBar.topmenuData = {
- gtkMenu: this.appMenuBar
- }
+ // Connect to the first available menu bar
+ this.srcMenuBar = menubars[0];
+ this.observer = createMutationObserver(window, this);
+ this.observer.observe(this.srcMenuBar, {
+ childList: true,
+ attributes: true,
+ subtree: true
+ });
- for (var item = this.srcMenuBar.firstChild; item; item = item.nextSibling) {
- this.addItem(item, this.srcMenuBar, -1);
- }
+ // Let's find currently added menu items and proxy them
+ this.srcMenuBar.topmenuData = {
+ gtkMenu: this.appMenuBar
+ }
- this.appMenu = this.buildAppMenu();
- if (this.appMenu) {
- topmenu_client.topmenu_app_menu_bar_set_app_menu(this.appMenuBar, this.appMenu);
- }
+ for (var item = this.srcMenuBar.firstChild; item; item = item.nextSibling) {
+ this.addItem(item, this.srcMenuBar, -1);
+ }
- window.document.addEventListener("keypress", this.callbacks.keypress);
+ this.appMenu = this.buildAppMenu();
+ if (this.appMenu) {
+ topmenu_client.topmenu_app_menu_bar_set_app_menu(this.appMenuBar, this.appMenu);
}
+ window.document.addEventListener("keypress", this.callbacks.keypress);
+
+ // Connect to the appmenu monitor
this.monitor = topmenu_client.topmenu_monitor_get_instance();
this.monitorConnectionId = gobject.signal_connect(this.monitor, "notify::available",
this.callbacks.monitor_available, null);
+
+ // This will hide the source menu bar if everything's OK.
this.updateMenuBarVisibility();
}
-WindowProxy.prototype.updateMenuBarVisibility = function() {
- var topmenuAvailable = topmenu_client.topmenu_monitor_is_topmenu_available(this.monitor);
+WindowProxy.prototype.setMenuBarVisibility = function(visible) {
if (this.srcMenuBar) {
- this.srcMenuBar.parentNode.parentNode.hidden = topmenuAvailable;
+ this.srcMenuBar.hidden = !visible;
+ // A hack for windows containing the menubar in a toolbar.
+ var toolbar = this.srcMenuBar.parentNode.parentNode;
+ if (toolbar && toolbar.tagName === 'toolbar') {
+ toolbar.hidden = !visible;
+ }
}
}
-WindowProxy.prototype.buildAppMenuItem = function(itemId, stockId)
-{
+WindowProxy.prototype.updateMenuBarVisibility = function() {
+ var topmenuAvailable = topmenu_client.topmenu_monitor_is_topmenu_available(this.monitor);
+ this.setMenuBarVisibility(!topmenuAvailable);
+}
+
+WindowProxy.prototype.buildAppMenuItem = function(itemId, stockId) {
var item = this.srcWindow.document.getElementById(itemId);
if (item) {
@@ -377,7 +399,7 @@ WindowProxy.prototype.addAccelerator = function(gtkItem, item) {
if (keyItemMods) {
keyItemMods = keyItemMods.split(/[\s,]+/);
- for (i in keyItemMods) {
+ for (var i in keyItemMods) {
var mod = keyItemMods[i];
if (mod === "accel") {
/* Read platform default accelerator key from prefs */
@@ -496,9 +518,12 @@ WindowProxy.prototype.addItem = function(item, menu, position) {
try {
this.addAccelerator(gtkItem, item);
} catch (ex) {
- log.warn(ex);
+ log.warn("Exception during accelerator computation: " + ex);
}
}
+ } else if (item.tagName === "spacer") {
+ // Nothing to do
+ return;
} else {
log.warn("Unknown tagName: " + item.tagName);
return;
@@ -624,7 +649,7 @@ WindowProxy.prototype.updateItem = function(item, changedAttr) {
}
WindowProxy.prototype.updateMenu = function(menu, prevItem, removedItems, addedItems) {
- var position, i, node;
+ var position, i;
var popup = menu.firstChild;
if (removedItems.length > 0) {
@@ -637,7 +662,7 @@ WindowProxy.prototype.updateMenu = function(menu, prevItem, removedItems, addedI
if (prevItem) {
position = -1;
i = 2;
- for (node = popup.firstChild; node; node = node.nextSibling, i++) {
+ for (var node = popup.firstChild; node; node = node.nextSibling, i++) {
if (node === prevItem) {
position = i;
break;
@@ -753,6 +778,11 @@ WindowProxy.prototype.fakeCommandEvent = function(item) {
item.dispatchEvent(commandEvent);
}
+WindowProxy.prototype.unload = function() {
+ this.setMenuBarVisibility(true);
+ topmenu_client.topmenu_client_disconnect_window(this.gdkWindow);
+}
+
WindowProxy.prototype.dispose = function() {
window.document.removeEventListener("keypress", this.callbacks.keypress);
if (this.monitor) {