[Pkg-mozext-commits] [firetray] 149/399: * extract FiretrayPopupMenu.jsm from FiretrayStatusIcon.jsm * fix visibilityRate * fix: have only one prefListener * refactor PopupMenu functions * clean

David Prévot taffit at alioth.debian.org
Tue Oct 29 18:23:31 UTC 2013


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch dfsg-clean
in repository firetray.

commit eb8ce310f4049bcd2ce1fe3cd14f0558b7085bcc
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Jan 23 04:04:05 2012 +0100

    * extract FiretrayPopupMenu.jsm from FiretrayStatusIcon.jsm
    * fix visibilityRate
    * fix: have only one prefListener
    * refactor PopupMenu functions
    * clean
---
 src/chrome/content/overlay.js           |   44 +-----
 src/modules/FiretrayHandler.jsm         |   21 +++
 src/modules/FiretrayPrefListener.jsm    |   50 +++++++
 src/modules/gtk2/FiretrayPopupMenu.jsm  |  221 +++++++++++++++++++++++++++++++
 src/modules/gtk2/FiretrayStatusIcon.jsm |  209 +++--------------------------
 src/modules/gtk2/FiretrayWindow.jsm     |   62 ++++-----
 6 files changed, 341 insertions(+), 266 deletions(-)

diff --git a/src/chrome/content/overlay.js b/src/chrome/content/overlay.js
index 934f86d..f93652e 100644
--- a/src/chrome/content/overlay.js
+++ b/src/chrome/content/overlay.js
@@ -8,20 +8,10 @@ if ("undefined" == typeof(Ci)) var Ci = Components.interfaces;
 if ("undefined" == typeof(Cu)) var Cu = Components.utils;
 
 // https://groups.google.com/group/mozilla.dev.extensions/browse_thread/thread/e89e9c2a834ff2b6#
-var firetrayChrome = {
+var firetrayChrome = { // each new window gets a new firetrayChrome !
 
   onLoad: function(win) {
-    // strings a chrome-specific
-    this.strings = document.getElementById("firetray-strings");
-
-    try {
-      // Set up preference change observer
-      firetray.Utils.prefService.QueryInterface(Ci.nsIPrefBranch2);
-      firetray.Utils.prefService.addObserver("", firetrayChrome, false);
-    } catch (x) {
-      ERROR(x);
-      return false;
-    }
+    this.strings = document.getElementById("firetray-strings"); // chrome-specific
 
     LOG("Handler initialized: "+firetray.Handler.initialized);
     let init = firetray.Handler.initialized || firetray.Handler.init();
@@ -35,8 +25,6 @@ var firetrayChrome = {
 
     // prevent window closing.
     win.addEventListener('close', firetrayChrome.onClose, true);
-    // NOTE: each new window gets a new firetrayChrome, and hence listens to
-    // pref changes
 
     if (!firetray.Handler.appStarted
         && firetray.Utils.prefService.getBoolPref('start_hidden')) {
@@ -51,13 +39,10 @@ var firetrayChrome = {
   },
 
   onQuit: function(win) {
-    // Remove observer
-    firetray.Utils.prefService.removeObserver("", firetrayChrome);
-
     firetray.Handler.unregisterWindow(win);
 
-    /* NOTE: don't firetray.Handler.initialized=false here, otherwise after a
-     window close, a new window will create a new handler (and hence, a new
+    /* NOTE: don't do firetray.Handler.initialized=false here, otherwise after
+     a window close, a new window will create a new handler (and hence, a new
      tray icon) */
     LOG('Firetray UNLOADED !');
   },
@@ -80,28 +65,7 @@ var firetrayChrome = {
         firetray.Handler.hideAllWindows();
       event && event.preventDefault(); // no event when called directly (xul)
     }
-  },
-
-  // the chosen design is not to destroy/re-create existing objects, but
-  // show/hide (Gtk objects) and apply/not (callbacks) them instead
-  observe: function(subject, topic, data) {
-    switch (topic) {
-    case "nsPref:changed":
-      LOG('Pref changed: '+data);
-      switch (data) {
-      case 'hides_single_window':
-        firetray.Handler.updatePopupMenu();
-        break;
-      case 'show_icon_on_hide':
-        firetray.Handler.showHideIcon();
-        break;
-      default:
-      }
-      break;
-    default:
-    }
   }
-
 };
 
 // should be sufficient for a delayed Startup (no need for window.setTimeout())
diff --git a/src/modules/FiretrayHandler.jsm b/src/modules/FiretrayHandler.jsm
index dcafdc3..25aea8d 100644
--- a/src/modules/FiretrayHandler.jsm
+++ b/src/modules/FiretrayHandler.jsm
@@ -11,6 +11,7 @@ Cu.import("resource://gre/modules/ctypes.jsm");
 Cu.import("resource://firetray/ctypes/gobject.jsm");
 Cu.import("resource://firetray/ctypes/gtk.jsm");
 Cu.import("resource://firetray/commons.js");
+Cu.import("resource://firetray/FiretrayPrefListener.jsm");
 Cu.import("resource://firetray/FiretrayVersionChange.jsm");
 
 /**
@@ -45,6 +46,8 @@ firetray.Handler = {
   visibleWindowsCount: 0,
 
   init: function() {            // does creates icon
+    firetray.PrefListener.register(false);
+
     this.appNameOriginal = Services.appinfo.name;
     this.FILENAME_DEFAULT = firetray.Utils.chromeToPath(
       "chrome://firetray/skin/" +  this.appNameOriginal.toLowerCase() + this.FILENAME_SUFFIX);
@@ -105,6 +108,8 @@ firetray.Handler = {
   },
 
   shutdown: function() {
+    firetray.PrefListener.unregister();
+
     if (this.inMailApp)
       firetray.Messaging.shutdown();
     firetray.StatusIcon.shutdown();
@@ -272,3 +277,19 @@ firetray.Handler = {
   }
 
 }; // firetray.Handler
+
+
+firetray.PrefListener = new PrefListener(
+  "extensions.firetray.",
+  function(branch, name) {
+    LOG('Pref changed: '+name);
+    switch (name) {
+    case 'hides_single_window':
+      firetray.Handler.updatePopupMenu();
+      break;
+    case 'show_icon_on_hide':
+      firetray.Handler.showHideIcon();
+      break;
+    default:
+    }
+  });
diff --git a/src/modules/FiretrayPrefListener.jsm b/src/modules/FiretrayPrefListener.jsm
new file mode 100644
index 0000000..670ee68
--- /dev/null
+++ b/src/modules/FiretrayPrefListener.jsm
@@ -0,0 +1,50 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// https://developer.mozilla.org/en/Code_snippets/Preferences
+
+var EXPORTED_SYMBOLS = [ "PrefListener" ];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+
+/**
+ * @constructor
+ *
+ * @param {string} branch_name
+ * @param {Function} callback must have the following arguments:
+ *   branch, pref_leaf_name
+ */
+function PrefListener(branch_name, callback) {
+  // Keeping a reference to the observed preference branch or it will get
+  // garbage collected.
+  var prefService = Components.classes["@mozilla.org/preferences-service;1"]
+        .getService(Components.interfaces.nsIPrefService);
+  this._branch = prefService.getBranch(branch_name);
+  this._branch.QueryInterface(Components.interfaces.nsIPrefBranch2);
+  this._callback = callback;
+}
+
+PrefListener.prototype.observe = function(subject, topic, data) {
+  if (topic == 'nsPref:changed')
+    this._callback(this._branch, data);
+};
+
+/**
+ * @param {boolean=} trigger if true triggers the registered function
+ *   on registration, that is, when this method is called.
+ */
+PrefListener.prototype.register = function(trigger) {
+  this._branch.addObserver('', this, false);
+  if (trigger) {
+    let that = this;
+    this._branch.getChildList('', {}).
+      forEach(function (pref_leaf_name)
+              { that._callback(that._branch, pref_leaf_name); });
+  }
+};
+
+PrefListener.prototype.unregister = function() {
+  if (this._branch)
+    this._branch.removeObserver('', this);
+};
diff --git a/src/modules/gtk2/FiretrayPopupMenu.jsm b/src/modules/gtk2/FiretrayPopupMenu.jsm
new file mode 100644
index 0000000..207bf82
--- /dev/null
+++ b/src/modules/gtk2/FiretrayPopupMenu.jsm
@@ -0,0 +1,221 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+var EXPORTED_SYMBOLS = [ "firetray" ];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://firetray/ctypes/gobject.jsm");
+Cu.import("resource://firetray/ctypes/gtk.jsm");
+Cu.import("resource://firetray/commons.js");
+
+if ("undefined" == typeof(firetray.StatusIcon))
+  ERROR("This module MUST be imported from/after StatusIcon !");
+
+
+firetray.PopupMenu = {
+  initialized: false,
+  // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
+  callbacks: {menuItemWindowActivate: {}},
+  menu: null,
+  menuSeparatorWindows: null,
+  MIN_FONT_SIZE: 4,
+
+  init: function() { // FIXME: function too long
+    this.menu = gtk.gtk_menu_new();
+    var menuShell = ctypes.cast(this.menu, gtk.GtkMenuShell.ptr);
+    var addMenuSeparator = false;
+
+    if (firetray.Handler.inBrowserApp) {
+		  var menuItemNewWindowLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.NewWindow");
+      var menuItemNewWindow = gtk.gtk_image_menu_item_new_with_label(
+        menuItemNewWindowLabel);
+      var menuItemNewWindowIcon = gtk.gtk_image_new_from_stock(
+        "gtk-new", gtk.GTK_ICON_SIZE_MENU);
+      gtk.gtk_image_menu_item_set_image(menuItemNewWindow, menuItemNewWindowIcon);
+      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemNewWindow, gtk.GtkWidget.ptr));
+
+      this.callbacks.menuItemNewWindowActivate = gobject.GCallback_t(
+        firetray.Handler.openBrowserWindow);
+      gobject.g_signal_connect(menuItemNewWindow, "activate",
+        firetray.PopupMenu.callbacks.menuItemNewWindowActivate, null);
+
+      addMenuSeparator = true;
+    }
+
+    if (firetray.Handler.inMailApp) {
+		  var menuItemNewMessageLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.NewMessage");
+      var menuItemNewMessage = gtk.gtk_image_menu_item_new_with_label(
+        menuItemNewMessageLabel);
+      var menuItemNewMessageIcon = gtk.gtk_image_new_from_stock(
+        "gtk-edit", gtk.GTK_ICON_SIZE_MENU);
+      gtk.gtk_image_menu_item_set_image(menuItemNewMessage, menuItemNewMessageIcon);
+      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemNewMessage, gtk.GtkWidget.ptr));
+
+      this.callbacks.menuItemNewMessageActivate = gobject.GCallback_t(
+        firetray.Handler.openMailMessage);
+      gobject.g_signal_connect(menuItemNewMessage, "activate",
+        firetray.PopupMenu.callbacks.menuItemNewMessageActivate, null);
+
+      addMenuSeparator = true;
+    }
+
+    if (addMenuSeparator) {
+      var menuSeparator = gtk.gtk_separator_menu_item_new();
+      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuSeparator, gtk.GtkWidget.ptr));
+    }
+
+    // shouldn't need to convert to utf8 thank to js-ctypes
+		var menuItemQuitLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.Quit");
+    var menuItemQuit = gtk.gtk_image_menu_item_new_with_label(
+      menuItemQuitLabel);
+    var menuItemQuitIcon = gtk.gtk_image_new_from_stock(
+      "gtk-quit", gtk.GTK_ICON_SIZE_MENU);
+    gtk.gtk_image_menu_item_set_image(menuItemQuit, menuItemQuitIcon);
+    gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemQuit, gtk.GtkWidget.ptr));
+
+    this.callbacks.menuItemQuitActivate = gobject.GCallback_t(
+      firetray.Handler.quitApplication);
+    gobject.g_signal_connect(menuItemQuit, "activate",
+      firetray.PopupMenu.callbacks.menuItemQuitActivate, null);
+
+    var menuWidget = ctypes.cast(this.menu, gtk.GtkWidget.ptr);
+    gtk.gtk_widget_show_all(menuWidget);
+
+    var menuSeparatorWindows = gtk.gtk_separator_menu_item_new();
+    gtk.gtk_menu_shell_prepend(menuShell, ctypes.cast(menuSeparatorWindows, gtk.GtkWidget.ptr));
+    this.menuSeparatorWindows = menuSeparatorWindows;
+
+    this.initialized = true;
+    return true;
+  },
+
+  shutdown: function() {
+    firetray.Utils.tryCloseLibs([gobject, gtk]);
+    this.initialized = false;
+  },
+
+  popup: function(icon, button, activateTime, menu) {
+    LOG("menu-popup");
+    LOG("ARGS="+icon+", "+button+", "+activateTime+", "+menu);
+
+    try {
+      var gtkMenuPtr = ctypes.cast(menu, gtk.GtkMenu.ptr);
+      var iconGpointer = ctypes.cast(icon, gobject.gpointer);
+      gtk.gtk_menu_popup(
+        gtkMenuPtr, null, null, gtk.gtk_status_icon_position_menu,
+        iconGpointer, button, activateTime);
+    } catch (x) { ERROR(x); }
+  },
+
+  // we'll be creating menuItems for windows (and not showing them) even if
+  // hides_single_window is false, because if hides_single_window becomes true,
+  // we'll just have to show the menuItems
+  addWindowItem: function(xid) { // on registerWindow
+    var menuItemWindow = this.addItem();
+    firetray.Handler.gtkPopupMenuWindowItems.insert(xid, menuItemWindow);
+
+    this.callbacks.menuItemWindowActivate[xid] = gobject.GCallback_t(
+      function(){firetray.Handler.showSingleWindow(xid);});
+    gobject.g_signal_connect(menuItemWindow, "activate",
+      firetray.PopupMenu.callbacks.menuItemWindowActivate[xid], null);
+    this.setWindowItemLabel(menuItemWindow, xid); // default to xid
+
+    LOG("add gtkPopupMenuWindowItems: "+firetray.Handler.gtkPopupMenuWindowItems.count);
+  },
+
+  addItem: function() {
+    var menuItem = gtk.gtk_image_menu_item_new();
+    var menuShell = ctypes.cast(this.menu, gtk.GtkMenuShell.ptr);
+    gtk.gtk_menu_shell_prepend(menuShell, ctypes.cast(menuItem, gtk.GtkWidget.ptr));
+    return menuItem;
+  },
+
+  removeWindowItem: function(xid) { // on unregisterWindow
+    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
+    firetray.Handler.gtkPopupMenuWindowItems.remove(xid);
+    this.removeItem(menuItemWindow);
+    LOG("remove gtkPopupMenuWindowItems: "+firetray.Handler.gtkPopupMenuWindowItems.count);
+  },
+  removeItem: function(item) {
+    gtk.gtk_widget_destroy(ctypes.cast(item, gtk.GtkWidget.ptr));
+  },
+
+  showAllWindowItemsOnlyVisibleWindows: function() {
+    for (let xid in firetray.Handler.windows)
+      if (!firetray.Handler.windows[xid].visibility)
+        this.showSingleWindowItem(xid);
+  },
+
+  showSingleWindowItem: function(xid) {
+    LOG("showSingleWindowItem");
+    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
+    this.showItem(menuItemWindow);
+    this.setWindowItemLabel(menuItemWindow, firetray.Window.getWindowTitle(xid));
+    this.showWindowSeparator();
+  },
+
+  showItem: function(menuItem) {
+    gtk.gtk_widget_show(ctypes.cast(menuItem, gtk.GtkWidget.ptr));
+  },
+
+  setWindowItemLabel: function(menuItem, label) {
+    LOG("about to set title: "+label);
+    if (label)
+      gtk.gtk_menu_item_set_label(ctypes.cast(menuItem, gtk.GtkMenuItem.ptr), label);
+  },
+
+  hideAllWindowItems: function() {
+    for (let xid in firetray.Handler.windows)
+      this.hideSingleWindowItemAndSeparator(xid);
+  },
+
+  // PopupMenu.hideItem(firetray.Handler.gtkPopupMenuWindowItems.get(xid))
+  hideSingleWindowItemAndSeparator: function(xid) {
+    this.hideSingleWindowItem(xid);
+    this.hideWindowSeparator();
+  },
+
+  hideSingleWindowItemAndSeparatorMaybe: function(xid) {
+    this.hideSingleWindowItem(xid);
+    if (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount)
+      this.hideWindowSeparator();
+  },
+
+  hideSingleWindowItem: function(xid) {
+    LOG("hideSingleWindowItem");
+    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
+    this.hideItem(menuItemWindow);
+  },
+
+  hideItem: function(menuItem) {
+    gtk.gtk_widget_hide(ctypes.cast(menuItem, gtk.GtkWidget.ptr));
+  },
+
+  showWindowSeparator: function() {
+    LOG("showing menuSeparatorWindows");
+    gtk.gtk_widget_show(ctypes.cast(this.menuSeparatorWindows, gtk.GtkWidget.ptr));
+  },
+  hideWindowSeparator: function() {
+    LOG("hiding menuSeparatorWindows");
+    gtk.gtk_widget_hide(ctypes.cast(this.menuSeparatorWindows, gtk.GtkWidget.ptr));
+  }
+
+}; // firetray.PopupMenu
+
+
+firetray.Handler.popupMenuWindowItemsHandled = function() {
+  return (firetray.Handler.inBrowserApp &&
+          firetray.Utils.prefService.getBoolPref('hides_single_window'));
+};
+
+firetray.Handler.updatePopupMenu = function() {
+  if (firetray.Handler.popupMenuWindowItemsHandled())
+    firetray.PopupMenu.showAllWindowItemsOnlyVisibleWindows();
+  else
+    firetray.PopupMenu.hideAllWindowItems();
+};
diff --git a/src/modules/gtk2/FiretrayStatusIcon.jsm b/src/modules/gtk2/FiretrayStatusIcon.jsm
index 5541a01..7174ac8 100644
--- a/src/modules/gtk2/FiretrayStatusIcon.jsm
+++ b/src/modules/gtk2/FiretrayStatusIcon.jsm
@@ -13,10 +13,8 @@ Cu.import("resource://firetray/ctypes/cairo.jsm");
 Cu.import("resource://firetray/ctypes/gobject.jsm");
 Cu.import("resource://firetray/ctypes/gdk.jsm");
 Cu.import("resource://firetray/ctypes/gtk.jsm");
-Cu.import("resource://firetray/ctypes/libc.jsm");
 Cu.import("resource://firetray/ctypes/pango.jsm");
 Cu.import("resource://firetray/ctypes/pangocairo.jsm");
-Cu.import("resource://firetray/ctypes/x11.jsm");
 Cu.import("resource://firetray/commons.js");
 
 if ("undefined" == typeof(firetray.Handler))
@@ -26,11 +24,8 @@ if ("undefined" == typeof(firetray.Handler))
 firetray.StatusIcon = {
   initialized: false,
   // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
-  callbacks: {menuItemWindowActivate: {}},
+  callbacks: {},
   trayIcon: null,
-  menu: null,
-  menuSeparatorWindows: null,
-  MIN_FONT_SIZE: 4,
 
   init: function() {
     try {
@@ -43,16 +38,13 @@ firetray.StatusIcon = {
 
     firetray.Handler.setIconImageDefault();
 
-    this._buildPopupMenu();
-
     firetray.Handler.setIconTooltipDefault();
 
-    LOG("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows"));
-    this.callbacks.iconActivate = gtk.GCallbackStatusIconActivate_t(
-      firetray.Handler.showHideAllWindows);
-    let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon,
-      "activate", firetray.StatusIcon.callbacks.iconActivate, null);
-    LOG("g_connect activate="+handlerId);
+    Cu.import("resource://firetray/gtk2/FiretrayPopupMenu.jsm");
+    if (!firetray.PopupMenu.init())
+      return false;
+
+    this.addCallbacks();
 
     this.initialized = true;
     return true;
@@ -63,179 +55,23 @@ firetray.StatusIcon = {
     this.initialized = false;
   },
 
-  _buildPopupMenu: function() { // FIXME: function too long
-    this.menu = gtk.gtk_menu_new();
-    var menuShell = ctypes.cast(this.menu, gtk.GtkMenuShell.ptr);
-    var addMenuSeparator = false;
-
-    if (firetray.Handler.inBrowserApp) {
-		  var menuItemNewWindowLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.NewWindow");
-      var menuItemNewWindow = gtk.gtk_image_menu_item_new_with_label(
-        menuItemNewWindowLabel);
-      var menuItemNewWindowIcon = gtk.gtk_image_new_from_stock(
-        "gtk-new", gtk.GTK_ICON_SIZE_MENU);
-      gtk.gtk_image_menu_item_set_image(menuItemNewWindow, menuItemNewWindowIcon);
-      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemNewWindow, gtk.GtkWidget.ptr));
-
-      this.callbacks.menuItemNewWindowActivate = gobject.GCallback_t(
-        firetray.Handler.openBrowserWindow);
-      gobject.g_signal_connect(menuItemNewWindow, "activate",
-        firetray.StatusIcon.callbacks.menuItemNewWindowActivate, null);
-
-      addMenuSeparator = true;
-    }
-
-    if (firetray.Handler.inMailApp) {
-		  var menuItemNewMessageLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.NewMessage");
-      var menuItemNewMessage = gtk.gtk_image_menu_item_new_with_label(
-        menuItemNewMessageLabel);
-      var menuItemNewMessageIcon = gtk.gtk_image_new_from_stock(
-        "gtk-edit", gtk.GTK_ICON_SIZE_MENU);
-      gtk.gtk_image_menu_item_set_image(menuItemNewMessage, menuItemNewMessageIcon);
-      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemNewMessage, gtk.GtkWidget.ptr));
-
-      this.callbacks.menuItemNewMessageActivate = gobject.GCallback_t(
-        firetray.Handler.openMailMessage);
-      gobject.g_signal_connect(menuItemNewMessage, "activate",
-        firetray.StatusIcon.callbacks.menuItemNewMessageActivate, null);
-
-      addMenuSeparator = true;
-    }
-
-    if (addMenuSeparator) {
-      var menuSeparator = gtk.gtk_separator_menu_item_new();
-      gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuSeparator, gtk.GtkWidget.ptr));
-    }
-
-    // shouldn't need to convert to utf8 thank to js-ctypes
-		var menuItemQuitLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel.Quit");
-    var menuItemQuit = gtk.gtk_image_menu_item_new_with_label(
-      menuItemQuitLabel);
-    var menuItemQuitIcon = gtk.gtk_image_new_from_stock(
-      "gtk-quit", gtk.GTK_ICON_SIZE_MENU);
-    gtk.gtk_image_menu_item_set_image(menuItemQuit, menuItemQuitIcon);
-    gtk.gtk_menu_shell_append(menuShell, ctypes.cast(menuItemQuit, gtk.GtkWidget.ptr));
-
-    this.callbacks.menuItemQuitActivate = gobject.GCallback_t(
-      firetray.Handler.quitApplication);
-    gobject.g_signal_connect(menuItemQuit, "activate",
-      firetray.StatusIcon.callbacks.menuItemQuitActivate, null);
-
-    var menuWidget = ctypes.cast(this.menu, gtk.GtkWidget.ptr);
-    gtk.gtk_widget_show_all(menuWidget);
-
+  addCallbacks: function() {
     /* NOTE: here we do use a function handler (instead of a function
-       definition) because we need the args passed to it ! As a consequence, we
-       need to abandon 'this' in popupMenu() */
-    let that = this;
-    this.callbacks.popupMenu = gtk.GCallbackMenuPopup_t(that.popupMenu);
+     definition) because we need the args passed to it ! As a consequence, we
+     need to abandon 'this' in PopupMenu.popup() */
+    this.callbacks.menuPopup = gtk.GCallbackMenuPopup_t(firetray.PopupMenu.popup);
     gobject.g_signal_connect(this.trayIcon, "popup-menu",
-      firetray.StatusIcon.callbacks.popupMenu, this.menu);
-    this.callbacks.onScroll = gtk.GCallbackOnScroll_t(that.onScroll);
+                             firetray.StatusIcon.callbacks.menuPopup, firetray.PopupMenu.menu);
+    this.callbacks.onScroll = gtk.GCallbackOnScroll_t(firetray.StatusIcon.onScroll);
     gobject.g_signal_connect(this.trayIcon, "scroll-event",
-      firetray.StatusIcon.callbacks.onScroll, null);
-
-    var menuSeparatorWindows = gtk.gtk_separator_menu_item_new();
-    gtk.gtk_menu_shell_prepend(menuShell, ctypes.cast(menuSeparatorWindows, gtk.GtkWidget.ptr));
-    firetray.StatusIcon.menuSeparatorWindows = menuSeparatorWindows;
-
-  },
-
-  popupMenu: function(icon, button, activateTime, menu) {
-    LOG("menu-popup");
-    LOG("ARGS="+icon+", "+button+", "+activateTime+", "+menu);
-
-    try {
-      var gtkMenuPtr = ctypes.cast(menu, gtk.GtkMenu.ptr);
-      var iconGpointer = ctypes.cast(icon, gobject.gpointer);
-      gtk.gtk_menu_popup(
-        gtkMenuPtr, null, null, gtk.gtk_status_icon_position_menu,
-        iconGpointer, button, activateTime);
-    } catch (x) {
-      ERROR(x);
-    }
-  },
-
-  // we keep the definition here, as it is(?) specific to the
-  // platform-dependant StatusIcon (there might be no popup menu in other
-  // platforms)
-  popupMenuWindowItemsHandled: function() {
-    return (firetray.Handler.inBrowserApp &&
-            firetray.Utils.prefService.getBoolPref('hides_single_window'));
-  },
+                             firetray.StatusIcon.callbacks.onScroll, null);
 
-  // we'll be creating menuItems for windows (and not showing them) even if
-  // hides_single_window is false, because if hides_single_window becomes true,
-  // we'll just have to show the menuItems
-  addPopupMenuWindowItem: function(xid) { // on registerWindow
-    var menuItemWindow = gtk.gtk_image_menu_item_new();
-    firetray.Handler.gtkPopupMenuWindowItems.insert(xid, menuItemWindow);
-
-    var menuShell = ctypes.cast(firetray.StatusIcon.menu, gtk.GtkMenuShell.ptr);
-    gtk.gtk_menu_shell_prepend(menuShell,
-                               ctypes.cast(menuItemWindow, gtk.GtkWidget.ptr));
-
-    this.callbacks.menuItemWindowActivate[xid] = gobject.GCallback_t(
-      function(){firetray.Handler.showSingleWindow(xid);});
-    gobject.g_signal_connect(menuItemWindow, "activate",
-      firetray.StatusIcon.callbacks.menuItemWindowActivate[xid], null);
-
-    LOG("add gtkPopupMenuWindowItems: "+firetray.Handler.gtkPopupMenuWindowItems.count);
-  },
-
-  setPopupMenuWindowItemLabel: function(menuItem, xid) {
-    let title = firetray.Handler.windows[xid].baseWin.title;
-    let tailIndex = title.indexOf(" - Mozilla "+firetray.Handler.appNameOriginal);
-    if (tailIndex !== -1)
-      title = title.substring(0, tailIndex);
-    gtk.gtk_menu_item_set_label(ctypes.cast(menuItem, gtk.GtkMenuItem.ptr), title);
-  },
-
-  removePopupMenuWindowItem: function(xid) { // on unregisterWindow
-    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
-    firetray.Handler.gtkPopupMenuWindowItems.remove(xid);
-    gtk.gtk_widget_destroy(ctypes.cast(menuItemWindow, gtk.GtkWidget.ptr));
-
-    LOG("remove gtkPopupMenuWindowItems: "+firetray.Handler.gtkPopupMenuWindowItems.count);
-  },
-
-  showAllPopupMenuWindowItems: function(filterVisibleWindows) {
-    for (let xid in firetray.Handler.windows)
-      if (!filterVisibleWindows || !firetray.Handler.windows[xid].visibility)
-        this.showSinglePopupMenuWindowItem(xid);
-  },
-
-  showSinglePopupMenuWindowItem: function(xid) {
-    LOG("showSinglePopupMenuWindowItem");
-    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
-    gtk.gtk_widget_show(ctypes.cast(menuItemWindow, gtk.GtkWidget.ptr));
-    this.setPopupMenuWindowItemLabel(menuItemWindow, xid); // not when creating item !
-    this.showPopupMenuWindowSeparator();
-  },
-
-  hideAllPopupMenuWindowItems: function(forceHideSeparator) {
-    for (let xid in firetray.Handler.windows)
-      this.hideSinglePopupMenuWindowItem(xid, forceHideSeparator);
-  },
-
-  // PopupMenu.hideItem(firetray.Handler.gtkPopupMenuWindowItems.get(xid))
-  hideSinglePopupMenuWindowItem: function(xid, forceHideSeparator) {
-    LOG("hideSinglePopupMenuWindowItem");
-    let menuItemWindow = firetray.Handler.gtkPopupMenuWindowItems.get(xid);
-    gtk.gtk_widget_hide(ctypes.cast(menuItemWindow, gtk.GtkWidget.ptr)); // on hideSingleWindow
-
-    if (forceHideSeparator || (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount)) {
-      this.hidePopupMenuWindowSeparator();
-    }
-  },
-
-  showPopupMenuWindowSeparator: function() {
-    LOG("showing menuSeparatorWindows");
-    gtk.gtk_widget_show(ctypes.cast(firetray.StatusIcon.menuSeparatorWindows, gtk.GtkWidget.ptr));
-  },
-  hidePopupMenuWindowSeparator: function() {
-    LOG("hiding menuSeparatorWindows");
-    gtk.gtk_widget_hide(ctypes.cast(firetray.StatusIcon.menuSeparatorWindows, gtk.GtkWidget.ptr));
+    LOG("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows"));
+    this.callbacks.iconActivate = gtk.GCallbackStatusIconActivate_t(
+      firetray.Handler.showHideAllWindows);
+    let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon,
+                                             "activate", firetray.StatusIcon.callbacks.iconActivate, null);
+    LOG("g_connect activate="+handlerId);
   },
 
   onScroll: function(icon, event, data) {
@@ -421,10 +257,3 @@ firetray.Handler.setIconVisibility = function(visible) {
   gtk.gtk_status_icon_set_visible(firetray.StatusIcon.trayIcon, visible);
   return true;
 };
-
-firetray.Handler.updatePopupMenu = function() {
-  if (firetray.StatusIcon.popupMenuWindowItemsHandled())
-    firetray.StatusIcon.showAllPopupMenuWindowItems(true);
-  else
-    firetray.StatusIcon.hideAllPopupMenuWindowItems(true);
-};
diff --git a/src/modules/gtk2/FiretrayWindow.jsm b/src/modules/gtk2/FiretrayWindow.jsm
index 5336599..22a4e76 100644
--- a/src/modules/gtk2/FiretrayWindow.jsm
+++ b/src/modules/gtk2/FiretrayWindow.jsm
@@ -46,6 +46,13 @@ var _find_data_t = ctypes.StructType("_find_data_t", [
   { outWindow: gtk.GtkWindow.ptr }
 ]);
 
+// NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
+// "evolving" after a while (maybe due to back and forth conversion). So we
+// need to store them into a real ctypes array !
+firetray.Handler.gtkWindows              = new ctypesMap(gtk.GtkWindow.ptr),
+firetray.Handler.gdkWindows              = new ctypesMap(gdk.GdkWindow.ptr),
+firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr),
+
 
 firetray.Window = {
 
@@ -172,7 +179,7 @@ firetray.Window = {
         throw new DeleteError();
       firetray.Handler.gtkWindows.remove(xid);
       firetray.Handler.gdkWindows.remove(xid);
-      firetray.StatusIcon.removePopupMenuWindowItem(xid);
+      firetray.PopupMenu.removeWindowItem(xid);
     } else {
       ERROR("can't unregister unknown window "+xid);
       return false;
@@ -368,6 +375,15 @@ firetray.Window = {
     return desktop;
   },
 
+  getWindowTitle: function(xid) {
+    let title = firetray.Handler.windows[xid].baseWin.title;
+    let tailIndex = title.indexOf(" - Mozilla "+firetray.Handler.appNameOriginal);
+    if (tailIndex !== -1)
+      return title.substring(0, tailIndex)
+    else
+      return null;
+  },
+
   filterWindow: function(xev, gdkEv, data) {
     if (!xev)
       return gdk.GDK_FILTER_CONTINUE;
@@ -395,19 +411,6 @@ firetray.Window = {
         }
         break;
 
-      case x11.ClientMessage:   // not very useful
-        LOG("ClientMessage");
-/* KEPT FOR LATER USE
-        let xclient = ctypes.cast(xev, x11.XClientMessageEvent.ptr);
-        LOG("xclient.data="+xclient.contents.data);
-        LOG("message_type="+xclient.contents.message_type+", format="+xclient.contents.format);
-        if (strEquals(xclient.contents.data[0], x11.current.Atoms.WM_DELETE_WINDOW)) {
-          LOG("Delete Window prevented");
-          return gdk.GDK_FILTER_REMOVE;
-        }
-*/
-        break;
-
       default:
         // LOG("xany.type="+xany.contents.type);
         break;
@@ -424,13 +427,6 @@ firetray.Window = {
 
 ///////////////////////// firetray.Handler overriding /////////////////////////
 
-// NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
-// "evolving" after a while (maybe due to back and forth conversion). So we
-// need to store them into a real ctypes array !
-firetray.Handler.gtkWindows = new ctypesMap(gtk.GtkWindow.ptr),
-firetray.Handler.gdkWindows = new ctypesMap(gdk.GdkWindow.ptr),
-firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr),
-
 /** debug facility */
 firetray.Handler.dumpWindows = function() {
   LOG(firetray.Handler.windowsCount);
@@ -450,7 +446,7 @@ firetray.Handler.registerWindow = function(win) {
   try {
     this.gtkWindows.insert(xid, gtkWin);
     this.gdkWindows.insert(xid, gdkWin);
-    firetray.StatusIcon.addPopupMenuWindowItem(xid);
+    firetray.PopupMenu.addWindowItem(xid);
   } catch (x) {
     if (x.name === "RangeError") // instanceof not working :-(
       win.alert(x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
@@ -470,12 +466,6 @@ firetray.Handler.registerWindow = function(win) {
      // delete_event_cb (in gtk2/nsWindow.cpp), but we prefer to use the
      // provided 'close' JS event
 
-/* KEPT FOR LATER USE
-    this.windows[xid].onWindowStateCb = gtk.GCallbackWindowStateEvent_t(firetray.Window.onWindowState);
-    this.windows[xid].onWindowStateCbId = gobject.g_signal_connect(gtkWin, "window-state-event", this.windows[xid].onWindowStateCb, null);
-    LOG("g_connect window-state-event="+this.windows[xid].onWindowStateCbId);
-*/
-
     this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow);
     gdk.gdk_window_add_filter(gdkWin, this.windows[xid].filterWindowCb, null);
 
@@ -492,7 +482,6 @@ firetray.Handler.registerWindow = function(win) {
 
 firetray.Handler.unregisterWindow = function(win) {
   LOG("unregister window");
-
   let xid = firetray.Window.getXIDFromChromeWindow(win);
   return firetray.Window.unregisterWindowByXID(xid);
 };
@@ -510,8 +499,8 @@ firetray.Handler.showSingleWindow = function(xid) {
   firetray.Handler.windows[xid].visibility = true;
   firetray.Handler.visibleWindowsCount += 1;
 
-  if (firetray.StatusIcon.popupMenuWindowItemsHandled())
-    firetray.StatusIcon.hideSinglePopupMenuWindowItem(xid);
+  if (firetray.Handler.popupMenuWindowItemsHandled())
+    firetray.PopupMenu.hideSingleWindowItemAndSeparatorMaybe(xid);
   firetray.Handler.showHideIcon();
 };
 
@@ -529,8 +518,8 @@ firetray.Handler.hideSingleWindow = function(xid) {
   firetray.Handler.windows[xid].visibility = false;
   firetray.Handler.visibleWindowsCount -= 1;
 
-  if (firetray.StatusIcon.popupMenuWindowItemsHandled())
-    firetray.StatusIcon.showSinglePopupMenuWindowItem(xid);
+  if (firetray.Handler.popupMenuWindowItemsHandled())
+    firetray.PopupMenu.showSingleWindowItem(xid);
   firetray.Handler.showHideIcon();
 };
 
@@ -543,10 +532,11 @@ firetray.Handler.showHideAllWindows = function(gtkStatusIcon, userData) {
   LOG("windowsCount="+firetray.Handler.windowsCount);
   let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
   LOG("visibilityRate="+visibilityRate);
-  if (visibilityRate > 0.5)     // TODO: should be configurable
-    firetray.Handler.hideAllWindows();
-  else
+  if ((0.5 < visibilityRate) && (visibilityRate < 1)
+      || visibilityRate === 0) // TODO: should be configurable
     firetray.Handler.showAllWindows();
+  else
+    firetray.Handler.hideAllWindows();
 
   let stopPropagation = true;
   return stopPropagation;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list