[Pkg-mozext-commits] [firetray] 292/399: Merge branch 'im'

David Prévot taffit at alioth.debian.org
Tue Oct 29 18:24:01 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 ae0f41e1e482b7db1cccf3bb1c6cf5adb47f297f
Merge: 1e4d51f c7b23ad
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Tue Sep 4 00:25:29 2012 +0200

    Merge branch 'im'
    
    Conflicts:
    	src/defaults/preferences/prefs.js
    	src/modules/FiretrayHandler.jsm
    	src/modules/FiretrayMessaging.jsm
    	src/modules/VersionChange.jsm
    	src/modules/commons.js
    	src/modules/linux/FiretrayStatusIcon.jsm
    	src/modules/linux/FiretrayWindow.jsm

 README.md                                          |    2 +-
 src/chrome/content/options.js                      |    9 +
 src/chrome/content/options.xul                     |   45 +++--
 src/chrome/locale/en-US/options.dtd                |   36 ++--
 .../icons/gnome/22x22/status/user-available.png    |    1 +
 .../linux/icons/gnome/22x22/status/user-away.png   |    1 +
 .../linux/icons/gnome/22x22/status/user-busy.png   |    1 +
 .../icons/gnome/22x22/status/user-offline.png      |    1 +
 src/chrome/skin/pidgin-tray-available.png          |  Bin 0 -> 1050 bytes
 src/chrome/skin/pidgin-tray-away.png               |  Bin 0 -> 1066 bytes
 src/chrome/skin/pidgin-tray-busy.png               |  Bin 0 -> 1052 bytes
 src/chrome/skin/pidgin-tray-offline.png            |  Bin 0 -> 1115 bytes
 src/defaults/preferences/prefs.js                  |    3 +-
 src/install.rdf                                    |    8 +-
 src/modules/FiretrayChat.jsm                       |  169 ++++++++++++++++
 src/modules/FiretrayHandler.jsm                    |  204 +++++++++++---------
 src/modules/FiretrayMessaging.jsm                  |   60 +++++-
 src/modules/VersionChange.jsm                      |   85 +++++---
 src/modules/commons.js                             |   59 ++++--
 src/modules/ctypes/ctypes-utils.jsm                |    2 +
 src/modules/ctypes/linux/gdk.jsm                   |    6 +
 src/modules/ctypes/linux/gio.jsm                   |    1 +
 src/modules/ctypes/linux/gobject.jsm               |    5 +-
 src/modules/ctypes/linux/gtk.jsm                   |   10 +-
 src/modules/linux/FiretrayChatStatusIcon.jsm       |  117 +++++++++++
 src/modules/linux/FiretrayGtkIcons.jsm             |   49 +++++
 src/modules/linux/FiretrayPopupMenu.jsm            |    3 +-
 src/modules/linux/FiretrayStatusIcon.jsm           |   34 ++--
 src/modules/linux/FiretrayWindow.jsm               |   30 ++-
 29 files changed, 739 insertions(+), 202 deletions(-)

diff --cc src/chrome/content/options.js
index a42835d,2239b53..962a0db
--- a/src/chrome/content/options.js
+++ b/src/chrome/content/options.js
@@@ -640,6 -593,14 +641,14 @@@ var firetrayUIOptions = 
        if (!/\d/.test(charStr))
          event.preventDefault();
      }
+   },
+ 
+   toggleChat: function(enabled) {
 -    F.LOG("Chat icon enable="+enabled);
++    log.debug("Chat icon enable="+enabled);
+     if (enabled)
+       firetray.Chat.init();
+     else
+       firetray.Chat.shutdown();
    }
  
  };
diff --cc src/chrome/content/options.xul
index 6888676,3fea56b..9e284cb
--- a/src/chrome/content/options.xul
+++ b/src/chrome/content/options.xul
@@@ -30,9 -30,9 +30,10 @@@
        <preference id="pref_app_icon_filename" name="extensions.firetray.app_icon_filename" type="string"/>
        <preference id="pref_scroll_hides" name="extensions.firetray.scroll_hides" type="bool" />
        <preference id="pref_scroll_mode" name="extensions.firetray.scroll_mode" type="string" />
+       <preference id="pref_chat_icon_enable" name="extensions.firetray.chat_icon_enable" type="bool" />
        <preference id="pref_mail_notification_enabled" name="extensions.firetray.mail_notification_enabled" type="bool" />
        <preference id="pref_folder_count_recursive" name="extensions.firetray.folder_count_recursive" type="bool" />
 +      <preference id="pref_only_favorite_folders" name="extensions.firetray.only_favorite_folders" type="bool" />
        <preference id="pref_message_count_type" name="extensions.firetray.message_count_type" type="int" />
        <preference id="pref_icon_text_color" name="extensions.firetray.icon_text_color" type="string" />
        <preference id="pref_custom_mail_icon" name="extensions.firetray.custom_mail_icon" type="string" />
diff --cc src/defaults/preferences/prefs.js
index d233117,13386fe..e7ad22d
--- a/src/defaults/preferences/prefs.js
+++ b/src/defaults/preferences/prefs.js
@@@ -31,5 -32,4 +32,5 @@@ pref("extensions.firetray.folder_count_
  // Ci.nsMsgFolderFlags.Archive|Drafts|Junk|Queue|SentMail|Trash|Virtual
  pref("extensions.firetray.excluded_folders_flags", 1077956384);
  // exposed in 1 tree, hence 2 branches: serverTypes, excludedAccounts
- pref("extensions.firetray.mail_accounts", '{ "serverTypes": {"pop3":{"order":1,"excluded":false}, "imap":{"order":1,"excluded":false}, "movemail":{"order":2,"excluded":true}, "none":{"order":3,"excluded":false}, "rss":{"order":4,"excluded":true}, "nntp":{"order":5,"excluded":true}}, "excludedAccounts": [] }'); // JSON
+ pref("extensions.firetray.mail_accounts", '{ "serverTypes": {"pop3":{"order":1,"excluded":false}, "imap":{"order":1,"excluded":false}, "movemail":{"order":2,"excluded":true}, "none":{"order":3,"excluded":false}, "rss":{"order":4,"excluded":true}, "nntp":{"order":5,"excluded":true}, "exquilla":{"order":6,"excluded":true}}, "excludedAccounts": [] }'); // JSON
 +pref("extensions.firetray.only_favorite_folders", false);
diff --cc src/modules/FiretrayChat.jsm
index 0000000,0f7d756..968174c
mode 000000,100644..100644
--- a/src/modules/FiretrayChat.jsm
+++ b/src/modules/FiretrayChat.jsm
@@@ -1,0 -1,167 +1,169 @@@
+ /* -*- 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:///modules/imServices.jsm");
+ Cu.import("resource://firetray/commons.js");
+ Cu.import("resource://firetray/linux/FiretrayChatStatusIcon.jsm");
+ 
++let log = firetray.Logger.getLogger("firetray.Chat");
++
+ firetray.Chat = {
+   initialized: false,
+   observedTopics: {},
+   acknowledgeOnFocus: {},
+ 
+   init: function() {
+     if (this.initialized) {
 -      F.WARN("Chat already initialized");
++      log.warn("Chat already initialized");
+       return;
+     }
 -    F.LOG("Enabling Chat");
++    log.debug("Enabling Chat");
+ 
+     firetray.Utils.addObservers(firetray.Chat, [
+       // "*" // debugging
+       "account-connected", "account-disconnected", "idle-time-changed",
+       "new-directed-incoming-message", "status-changed",
+       "unread-im-count-changed"
+     ]);
+     firetray.ChatStatusIcon.init();
+ 
+     this.initialized = true;
+   },
+ 
+   shutdown: function() {
+     if (!this.initialized) return;
 -    F.LOG("Disabling Chat");
++    log.debug("Disabling Chat");
+ 
+     firetray.ChatStatusIcon.shutdown();
+     firetray.Utils.removeAllObservers(firetray.Chat);
+ 
+     this.initialized = false;
+   },
+ 
+   observe: function(subject, topic, data) {
 -    F.LOG("RECEIVED Chat: "+topic+" subject="+subject+" data="+data);
++    log.debug("RECEIVED Chat: "+topic+" subject="+subject+" data="+data);
+     switch (topic) {
+     case "account-connected":
+     case "account-disconnected":
+     case "idle-time-changed":
+     case "status-changed":
+       this.updateIcon();
+       break;
+ 
+     case "new-directed-incoming-message": // when PM or cited in channel
+       let conv = subject.QueryInterface(Ci.prplIMessage).conversation;
 -      F.LOG("conversation name="+conv.name); // normalizedName shouldn't be necessary
++      log.debug("conversation name="+conv.name); // normalizedName shouldn't be necessary
+ 
+       let convIsActiveTabInActiveWin = this.isConvActiveTabInActiveWindow(conv);
 -      F.LOG("convIsActiveTabInActiveWin="+convIsActiveTabInActiveWin);
++      log.debug("convIsActiveTabInActiveWin="+convIsActiveTabInActiveWin);
+       if (!convIsActiveTabInActiveWin) { // don't blink when conv tab already on top
+         this.acknowledgeOnFocus.must = true;
+         this.acknowledgeOnFocus.conv = conv;
+         firetray.ChatStatusIcon.setIconBlinking(true);
+       }
+       break;
+ 
+     case "unread-im-count-changed":
+       let unreadMsgCount = data;
+       if (unreadMsgCount == 0)
+         this.stopIconBlinkingMaybe();
+ 
+       let localizedTooltip = PluralForm.get(
+         unreadMsgCount,
+         firetray.Utils.strings.GetStringFromName("tooltip.unread_messages"))
+         .replace("#1", unreadMsgCount);
+       firetray.ChatStatusIcon.setIconTooltip(localizedTooltip);
+       break;
+ 
+     default:
 -      F.WARN("unhandled topic: "+topic);
++      log.warn("unhandled topic: "+topic);
+     }
+   },
+ 
+   stopIconBlinkingMaybe: function() {
 -    F.LOG("acknowledgeOnFocus.must="+this.acknowledgeOnFocus.must);
++    log.debug("acknowledgeOnFocus.must="+this.acknowledgeOnFocus.must);
+     if (!this.acknowledgeOnFocus.must) return;
+ 
+     let convIsActiveTabInActiveWin = this.isConvActiveTabInActiveWindow(
+       this.acknowledgeOnFocus.conv);
 -    F.LOG("convIsActiveTabInActiveWin="+convIsActiveTabInActiveWin);
++    log.debug("convIsActiveTabInActiveWin="+convIsActiveTabInActiveWin);
+ 
+     if (this.acknowledgeOnFocus.must && convIsActiveTabInActiveWin) {
+       firetray.ChatStatusIcon.setIconBlinking(false);
+       this.acknowledgeOnFocus.must = false;
+     }
+   },
+ 
+   isConvActiveTabInActiveWindow: function(conv) {
+     let activeWin = firetray.Handler.findActiveWindow(),
+         activeChatTab = null;
+     if (!firetray.Handler.windows[activeWin]) return false;
+ 
+     activeChatTab = this.findActiveChatTab(activeWin);
+     let convNameRegex = new RegExp(" - "+conv.name+"$");
+     return activeChatTab ? convNameRegex.test(activeChatTab.title) : false;
+   },
+ 
+   findActiveChatTab: function(xid) {
+     let win = firetray.Handler.windows[xid].chromeWin;
+     let tabmail = win.document.getElementById("tabmail");
+     let chatTabs = tabmail.tabModes.chat.tabs;
+     for each (let tab in chatTabs)
+       if (tab.tabNode.selected) return tab;
+     return null;
+   },
+ 
+   updateIcon: function() {
+     let globalConnectedStatus = this.globalConnectedStatus();
+     let userStatus;
+     if (globalConnectedStatus)
+       userStatus = Services.core.globalUserStatus.statusType;
+     else
+       userStatus = Ci.imIStatusInfo.STATUS_OFFLINE;
 -    F.LOG("IM status="+userStatus);
++    log.debug("IM status="+userStatus);
+ 
+     let iconName;
+     switch (userStatus) {
+     case Ci.imIStatusInfo.STATUS_OFFLINE: // 1
+       iconName = FIRETRAY_IM_STATUS_OFFLINE;
+       break;
+     case Ci.imIStatusInfo.STATUS_IDLE: // 4
+     case Ci.imIStatusInfo.STATUS_AWAY: // 5
+       iconName = FIRETRAY_IM_STATUS_AWAY;
+       break;
+     case Ci.imIStatusInfo.STATUS_AVAILABLE: // 7
+       iconName = FIRETRAY_IM_STATUS_AVAILABLE;
+       break;
+     case Ci.imIStatusInfo.STATUS_UNAVAILABLE: // 6
+       iconName = FIRETRAY_IM_STATUS_BUSY;
+       break;
+     case Ci.imIStatusInfo.STATUS_UNKNOWN: // 0
+     case Ci.imIStatusInfo.STATUS_INVISIBLE: // 2
+     case Ci.imIStatusInfo.STATUS_MOBILE:    // 3
+     default:
+         // ignore
+     }
+ 
 -    F.LOG("IM status changed="+iconName);
++    log.debug("IM status changed="+iconName);
+     if (iconName)
+       firetray.ChatStatusIcon.setIconImage(iconName);
+   },
+ 
+   globalConnectedStatus: function() {
+     let accounts = Services.accounts.getAccounts();
+     let globalConnected = false;
+     while (accounts.hasMoreElements()) {
+       let account = accounts.getNext().QueryInterface(Ci.imIAccount);
 -      F.LOG("account="+account+" STATUS="+account.statusInfo.statusType+" connected="+account.connected);
++      log.debug("account="+account+" STATUS="+account.statusInfo.statusType+" connected="+account.connected);
+       globalConnected = globalConnected || account.connected;
+     }
 -    F.LOG("globalConnected="+globalConnected);
++    log.debug("globalConnected="+globalConnected);
+     return globalConnected;
+   }
+ 
+ };
diff --cc src/modules/FiretrayHandler.jsm
index 701fe98,7529512..af7226d
--- a/src/modules/FiretrayHandler.jsm
+++ b/src/modules/FiretrayHandler.jsm
@@@ -73,18 -70,20 +72,20 @@@ firetray.Handler = 
        return false;
      }
  
 -    if (this.appId === F.THUNDERBIRD_ID || this.appId === F.SEAMONKEY_ID)
 +    if (this.appId === FIRETRAY_THUNDERBIRD_ID || this.appId === FIRETRAY_SEAMONKEY_ID)
        this.inMailApp = true;
 -    if (this.appId === F.FIREFOX_ID || this.appId === F.SEAMONKEY_ID)
 +    if (this.appId === FIRETRAY_FIREFOX_ID || this.appId === FIRETRAY_SEAMONKEY_ID)
        this.inBrowserApp = true;
 -    F.LOG('inMailApp: '+this.inMailApp+', inBrowserApp: '+this.inBrowserApp);
 +    log.debug('inMailApp: '+this.inMailApp+', inBrowserApp: '+this.inBrowserApp);
  
-     this.FILENAME_DEFAULT = firetray.Utils.chromeToPath(
-       "chrome://firetray/skin/" +  this.appName.toLowerCase() + this.FILENAME_SUFFIX);
-     this.FILENAME_BLANK = firetray.Utils.chromeToPath(
-       "chrome://firetray/skin/blank-icon.png");
-     this.FILENAME_NEWMAIL = firetray.Utils.chromeToPath(
-       "chrome://firetray/skin/message-mail-new.png");
+     this.appStartupTopic = this.getAppStartupTopic(this.appId);
+ 
+     VersionChange.init(FIRETRAY_ID, FIRETRAY_VERSION, FIRETRAY_PREF_BRANCH);
+     VersionChange.addHook(["install", "upgrade", "reinstall"], firetray.VersionChangeHandler.showReleaseNotes);
+     VersionChange.addHook(["upgrade", "reinstall"], firetray.VersionChangeHandler.tryEraseOldOptions);
+     VersionChange.addHook(["upgrade", "reinstall"], firetray.VersionChangeHandler.correctMailNotificationType);
+     VersionChange.addHook(["upgrade", "reinstall"], firetray.VersionChangeHandler.correctMailServerTypes);
+     VersionChange.applyHooksAndWatchUninstall();
  
      firetray.StatusIcon.init();
      firetray.Handler.showHideIcon();
@@@ -124,6 -112,7 +114,7 @@@
    },
  
    shutdown: function() {
 -    F.LOG("Disabling Handler");
++    log.debug("Disabling Handler");
      firetray.PrefListener.unregister();
  
      if (this.inMailApp)
@@@ -141,6 -128,24 +130,24 @@@
      return true;
    },
  
+   tryCloseLibs: function() {
+     try {
+       for (libName in this.ctypesLibs) {
+         let lib = this.ctypesLibs[libName];
+         if (lib.available())
+           lib.close();
+       };
 -    } catch(x) { F.ERROR(x); }
++    } catch(x) { log.error(x); }
+   },
+ 
+   subscribeLibsForClosing: function(libs) {
+     for (let i=0, len=libs.length; i<len; ++i) {
+       let lib = libs[i];
+       if (!this.ctypesLibs.hasOwnProperty(lib.name))
+         this.ctypesLibs[lib.name] = lib;
+     }
+   },
+ 
    observe: function(subject, topic, data) {
      switch (topic) {
      case "sessionstore-windows-restored":
@@@ -194,9 -200,10 +201,10 @@@
    showWindow: function(winId) {},
    showHideAllWindows: function() {},
    activateLastWindow: function(gtkStatusIcon, gdkEvent, userData) {},
+   findActiveWindow: function() {},
  
    showAllWindows: function() {
 -    F.LOG("showAllWindows");
 +    log.debug("showAllWindows");
      for (let winId in firetray.Handler.windows) {
        if (!firetray.Handler.windows[winId].visible)
          firetray.Handler.showWindow(winId);
@@@ -291,16 -298,82 +299,82 @@@
        var msgComposeService = Cc["@mozilla.org/messengercompose;1"]
          .getService(Ci.nsIMsgComposeService);
        msgComposeService.OpenComposeWindowWithURI(null, aURI);
 -    } catch (x) { F.ERROR(x); }
 +    } catch (x) { log.error(x); }
    },
  
+   quitApplication: function() {
+     try {
+       firetray.Utils.timer(function() {
+         let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
+           .getService(Ci.nsIAppStartup);
+         appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);
+       }, FIRETRAY_DELAY_NOWAIT_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
 -    } catch (x) { F.ERROR(x); }
++    } catch (x) { log.error(x); }
+   },
+ 
+   preventWarnOnClose: function() {
+     if (!this.inBrowserApp) return;
+     let generalTabsPrefs = Services.prefs.getBranch("browser.tabs.");
+     this.warnOnCloseTmp = generalTabsPrefs.getBoolPref('warnOnClose');
 -    F.LOG("warnOnClose saved. was: "+this.warnOnCloseTmp);
++    log.debug("warnOnClose saved. was: "+this.warnOnCloseTmp);
+     generalTabsPrefs.setBoolPref('warnOnClose', false);
+   },
+   restoreWarnOnClose: function() {
+     if (!this.inBrowserApp && !this.warnOnCloseTmp) return;
+     let generalTabsPrefs = Services.prefs.getBranch("browser.tabs.");
+     generalTabsPrefs.setBoolPref('warnOnClose', this.warnOnCloseTmp);
 -    F.LOG("warnOnClose restored to: "+this.warnOnCloseTmp);
++    log.debug("warnOnClose restored to: "+this.warnOnCloseTmp);
+   }
+ 
+ }; // firetray.Handler
+ 
+ 
+ firetray.PrefListener = new PrefListener(
+   "extensions.firetray.",
+   function(branch, name) {
 -    F.LOG('Pref changed: '+name);
++    log.debug('Pref changed: '+name);
+     switch (name) {
+     case 'hides_single_window':
+       firetray.Handler.showHidePopupMenuItems();
+       break;
+     case 'show_icon_on_hide':
+       firetray.Handler.showHideIcon();
+       break;
+     case 'new_mail_icon_names':
+       firetray.StatusIcon.loadThemedIcons();
++    case 'only_favorite_folders':
+     case 'message_count_type':
+     case 'folder_count_recursive':
+       firetray.Messaging.updateMsgCountWithCb();
+       break;
+     case 'app_mail_icon_names':
+     case 'app_browser_icon_names':
+     case 'app_default_icon_names':
+       firetray.StatusIcon.loadThemedIcons();
+     case 'app_icon_type':
+       if (firetray.Handler.inMailApp)
+         firetray.Messaging.updateMsgCountWithCb();
+       else
+         firetray.Handler.setIconImageDefault();
+       break;
+     default:
+     }
+   });
+ 
+ 
+ firetray.VersionChangeHandler = {
+ 
+   showReleaseNotes: function() {
+     firetray.VersionChangeHandler.openTab(FIRETRAY_SPLASH_PAGE+"#v"+FIRETRAY_VERSION);
+   },
+ 
    openTab: function(url) {
 -    if (firetray.Handler.appId === F.THUNDERBIRD_ID)
 +    if (this.appId === FIRETRAY_THUNDERBIRD_ID)
        this.openMailTab(url);
 -    else if (firetray.Handler.appId === F.FIREFOX_ID ||
 -             firetray.Handler.appId === F.SEAMONKEY_ID)
 +    else if (this.appId === FIRETRAY_FIREFOX_ID || this.appId === FIRETRAY_SEAMONKEY_ID)
        this.openBrowserTab(url);
      else
 -      F.ERROR("unsupported application");
 +      log.error("unsupported application");
    },
  
    openMailTab: function(url) {
@@@ -358,66 -432,22 +433,21 @@@
  
    correctMailNotificationType: function() {
      if (firetray.Utils.prefService.getIntPref('message_count_type') ===
-         FIRETRAY_MESSAGE_COUNT_TYPE_NEW)
+         FIRETRAY_MESSAGE_COUNT_TYPE_NEW) {
        firetray.Utils.prefService.setIntPref('mail_notification_type',
          FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
 -      F.WARN("mail notification type set to newmail icon.");
++      log.warn("mail notification type set to newmail icon.");
+     }
    },
--
-   quitApplication: function() {
-     try {
-       firetray.Utils.timer(function() {
-         let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
-           .getService(Ci.nsIAppStartup);
-         appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);
-       }, FIRETRAY_DELAY_NOWAIT_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
-     } catch (x) { log.error(x); }
-   },
- 
-   preventWarnOnClose: function() {
-     if (!this.inBrowserApp) return;
-     let generalTabsPrefs = Services.prefs.getBranch("browser.tabs.");
-     this.warnOnCloseTmp = generalTabsPrefs.getBoolPref('warnOnClose');
-     log.debug("warnOnClose saved. was: "+this.warnOnCloseTmp);
-     generalTabsPrefs.setBoolPref('warnOnClose', false);
-   },
-   restoreWarnOnClose: function() {
-     if (!this.inBrowserApp && !this.warnOnCloseTmp) return;
-     let generalTabsPrefs = Services.prefs.getBranch("browser.tabs.");
-     generalTabsPrefs.setBoolPref('warnOnClose', this.warnOnCloseTmp);
-     log.debug("warnOnClose restored to: "+this.warnOnCloseTmp);
+   correctMailServerTypes: function() {
+     let mailAccounts = firetray.Utils.getObjPref('mail_accounts');
+     let serverTypes = mailAccounts["serverTypes"];
+     if (!serverTypes["exquilla"]) {
+       serverTypes["exquilla"] = {"order":6,"excluded":true};
+       let prefObj = {"serverTypes":serverTypes, "excludedAccounts":mailAccounts["excludedAccounts"]};
+       firetray.Utils.setObjPref('mail_accounts', prefObj);
 -      F.WARN("mail server types corrected");
++      log.warn("mail server types corrected");
+     }
    }
  
- }; // firetray.Handler
- 
- 
- firetray.PrefListener = new PrefListener(
-   "extensions.firetray.",
-   function(branch, name) {
-     log.debug('Pref changed: '+name);
-     switch (name) {
-     case 'hides_single_window':
-       firetray.Handler.showHidePopupMenuItems();
-       break;
-     case 'show_icon_on_hide':
-       firetray.Handler.showHideIcon();
-       break;
-     case 'new_mail_icon_names':
-       firetray.StatusIcon.loadThemedIcons();
-     case 'only_favorite_folders':
-     case 'message_count_type':
-     case 'folder_count_recursive':
-       firetray.Messaging.updateMsgCountWithCb();
-       break;
-     case 'app_mail_icon_names':
-     case 'app_browser_icon_names':
-     case 'app_default_icon_names':
-       firetray.StatusIcon.loadThemedIcons();
-     case 'app_icon_type':
-       if (firetray.Handler.inMailApp)
-         firetray.Messaging.updateMsgCountWithCb();
-       else
-         firetray.Handler.setIconImageDefault();
-       break;
-     default:
-     }
-   });
+ };
diff --cc src/modules/FiretrayMessaging.jsm
index 6af8214,b5199eb..742e131
--- a/src/modules/FiretrayMessaging.jsm
+++ b/src/modules/FiretrayMessaging.jsm
@@@ -7,8 -7,9 +7,10 @@@ const Ci = Components.interfaces
  const Cu = Components.utils;
  
  Cu.import("resource:///modules/mailServices.js");
++Cu.import("resource://gre/modules/Services.jsm");
  Cu.import("resource://gre/modules/PluralForm.jsm");
  Cu.import("resource://firetray/commons.js");
+ Cu.import("resource://firetray/FiretrayChat.jsm");
  
  const FLDRS_UNINTERESTING = {
    Archive:   Ci.nsMsgFolderFlags.Archive,
@@@ -28,19 -27,17 +30,18 @@@ firetray.Messaging = 
    initialized: false,
    cleaningTimer: null,
    currentMsgCount: null,
 +  newMsgCount: null,
+   observedTopics: {},
  
    init: function() {
      if (this.initialized) {
 -      F.WARN("Messaging already initialized");
 +      log.warn("Messaging already initialized");
        return;
      }
 -    F.LOG("Enabling Messaging");
 +    log.debug("Enabling Messaging");
  
-     // there is no means to detect account-removed event
-     this.cleaningTimer = firetray.Utils.timer(firetray.Messaging.cleanExcludedAccounts,
-       FIRETRAY_DELAY_PREF_CLEANING_MILLISECONDS, Ci.nsITimer.TYPE_REPEATING_SLACK);
-     log.debug(this.cleaningTimer+"="+FIRETRAY_DELAY_PREF_CLEANING_MILLISECONDS);
+     firetray.Utils.addObservers(firetray.Messaging, [ "account-added",
+       "account-removed"]);
  
      let that = this;
      MailServices.mailSession.AddFolderListener(that.mailSessionListener,
@@@ -51,16 -53,50 +57,50 @@@
  
    shutdown: function() {
      if (!this.initialized) return;
 -    F.LOG("Disabling Messaging");
 +    log.debug("Disabling Messaging");
  
-     this.cleaningTimer.cancel();
 -    firetray.Chat.shutdown();
++    if (firetray.hasOwnProperty('Chat')) firetray.Chat.shutdown();
  
      MailServices.mailSession.RemoveFolderListener(this.mailSessionListener);
-     firetray.Handler.setIconImageDefault();
+ 
+     firetray.Utils.removeAllObservers(firetray.Messaging);
  
      this.initialized = false;
    },
  
+   // FIXME: this should definetely be done in Chat, but IM accounts
+   // seem not be initialized at this stage (Exception... "'TypeError:
+   // this._items is undefined' when calling method:
+   // [nsISimpleEnumerator::hasMoreElements]"), and we're unsure if we should
+   // initAccounts() ourselves...
+   existsChatAccount: function() {
+     let accounts = new this.Accounts();
+     for (let accountServer in accounts)
+       if (accountServer.type === 'im')  {
 -        F.LOG("found im server: "+accountServer.prettyName);
++        log.debug("found im server: "+accountServer.prettyName);
+         return true;
+       }
+ 
+     return false;
+   },
+ 
+   observe: function(subject, topic, data) {
 -    F.LOG("RECEIVED Messaging: "+topic+" subject="+subject+" data="+data);
++    log.debug("RECEIVED Messaging: "+topic+" subject="+subject+" data="+data);
+     switch (topic) {
+     case "account-removed":
+       this.cleanExcludedAccounts();
+       if (subject.QueryInterface(Ci.imIAccount) && !this.existsChatAccount())
+         firetray.Chat.shutdown();
+       break;
+     case "account-added":
+       if (subject.QueryInterface(Ci.imIAccount) && !firetray.Chat.initialized)
+         firetray.Chat.init();
+       break;
+     default:
 -      F.WARN("unhandled topic: "+topic);
++      log.warn("unhandled topic: "+topic);
+     }
+   },
+ 
    /* removes removed accounts from excludedAccounts pref. NOTE: Can't be called
      at shutdown because MailServices.accounts no longer available */
    cleanExcludedAccounts: function() {
@@@ -227,41 -262,58 +269,45 @@@
    /**
     * computes total unread or new message count.
     */
 -  countMessages: function(folderCountFunction) {
 +  countMessages: function(countType) {
      let mailAccounts = firetray.Utils.getObjPref('mail_accounts');
 -    F.LOG("mail accounts from pref: "+JSON.stringify(mailAccounts));
 +    log.debug("mail accounts from pref: "+JSON.stringify(mailAccounts));
      let serverTypes = mailAccounts["serverTypes"];
      let excludedAccounts = mailAccounts["excludedAccounts"];
 -    let excludedFoldersFlags = firetray.Utils.prefService
 -      .getIntPref("excluded_folders_flags");
  
 -    let msgCount = 0;
 -    try {
 -      let accounts = new this.Accounts();
 -      for (let accountServer in accounts) {
 -        if (accountServer.type === 'im') {
 -          continue;             // IM messages are counted elsewhere
 -        } else if (!serverTypes[accountServer.type]) {
 -          F.WARN("'"+accountServer.type+"' server type is not handled");
 -          continue;
 -        }
 -        F.LOG("is servertype excluded: "+serverTypes[accountServer.type].excluded+", account exclusion index: "+excludedAccounts.indexOf(accountServer.key));
 -        if (serverTypes[accountServer.type].excluded ||
 -            (excludedAccounts.indexOf(accountServer.key) >= 0))
 -          continue;
 -
 -        let rootFolder = accountServer.rootFolder; // nsIMsgFolder
 -        if (rootFolder.hasSubFolders) {
 -          let subFolders = rootFolder.subFolders;
 -          while (subFolders.hasMoreElements()) {
 -            let folder = subFolders.getNext().QueryInterface(Ci.nsIMsgFolder);
 -            if (!(folder.flags & excludedFoldersFlags)) {
 -              msgCount = folderCountFunction(folder, msgCount);
 -            }
 -          }
 -        }
 +    this.newMsgCount = 0;
 +    let accounts = new this.Accounts();
 +    for (let accountServer in accounts) { // nsIMsgAccount
-       if (!serverTypes[accountServer.type]) {
++
++      if (accountServer.type === 'im') {
++        continue;               // IM messages are counted elsewhere
++      } else if (!serverTypes[accountServer.type]) {
 +        log.warn("'"+accountServer.type+"' server type is not handled");
 +        continue;
        }
 -    } catch (x) {
 -      F.ERROR(x);
 -    }
 -    F.LOG("Total New="+msgCount);
 -    return msgCount;
 -  },
+ 
 -  unreadMsgCountIterate: function(folder, accumulator) {
 -    let folderCountFunctionName = 'getNumUnread';
 -    let folderUnreadMsgCount = folder[folderCountFunctionName](
 -      firetray.Utils.prefService.getBoolPref("folder_count_recursive"));
 -    F.LOG(folder.prettyName+" "+folderCountFunctionName+"="+folderUnreadMsgCount);
 -    return accumulator + folderUnreadMsgCount;
 +      log.debug("is servertype excluded: "+serverTypes[accountServer.type].excluded+", account exclusion index: "+excludedAccounts.indexOf(accountServer.key));
 +      if ((serverTypes[accountServer.type].excluded) ||
 +          (excludedAccounts.indexOf(accountServer.key) >= 0))
 +        continue;
 +
 +      this.applyToSubfolders(
 +        accountServer.rootFolder,
 +        firetray.Utils.prefService.getBoolPref("folder_count_recursive"),
 +        function(folder){this.msgCountIterate(countType, folder);}
 +      );
 +
 +    }
 +    log.debug("Total "+countType+"="+this.newMsgCount);
    },
  
 -  newMsgCountIterate: function(folder, accumulator) {
 -    if (folder.hasSubFolders && firetray.Utils.prefService.getBoolPref("folder_count_recursive")) {
 -      F.LOG("hasSubFolders");
 +  /**
 +   * @param folder: a nsIMsgFolder
 +   * @param recursive: if we should look into nested folders
 +   * @param fun: a function to apply to all folders
 +   */
 +  applyToSubfolders: function(folder, recursive, fun) {
 +    if (folder.hasSubFolders) {
        let subFolders = folder.subFolders;
        while(subFolders.hasMoreElements()) {
          let subFolder = subFolders.getNext().QueryInterface(Ci.nsIMsgFolder);
diff --cc src/modules/VersionChange.jsm
index 2891d40,04fd1b7..95c1136
--- a/src/modules/VersionChange.jsm
+++ b/src/modules/VersionChange.jsm
@@@ -5,9 -5,9 +5,10 @@@ const Ci = Components.interfaces
  const Cu = Components.utils;
  
  Cu.import("resource://gre/modules/AddonManager.jsm");
- Cu.import("resource://firetray/commons.js");
+ Cu.import("resource://gre/modules/Services.jsm");
+ Cu.import("resource://firetray/logging.jsm");
  
 +let log = firetray.Logger.getLogger("VersionChange");
  
  /**
   * handles version changes.
@@@ -16,15 -15,28 +16,28 @@@
   */
  var VersionChange = {
  
-   curVersion: null,
+   initialized:  false,
+   addonId:      null,
+   addonVersion: null,
+   addOnPrefs: null,
+ 
+   init: function(id, version, prefBranch) {
 -    F.LOG("VersionChange got: id="+id+" ver="+version+" prefBranch="+prefBranch);
++    log.debug("VersionChange got: id="+id+" ver="+version+" prefBranch="+prefBranch);
+     this.addOnId = id;
+     this.addonVersion = version;
+     this.addOnPrefs = Services.prefs.getBranch(prefBranch);
+ 
+     this.initialized = true;
+   },
  
    versionComparator: Cc["@mozilla.org/xpcom/version-comparator;1"]
      .getService(Ci.nsIVersionComparator),
  
-   watch: function() {
+   applyHooksAndWatchUninstall: function() {
+     if (!this.initialized) throw "VersionChange not initialized";
+     this.onVersionChange(this.addonVersion); // AddonManager.getAddonByID() async, whereas we need sync call
      AddonManager.addAddonListener(this.uninstallListener);
-     AddonManager.getAddonByID(FIRETRAY_ID, this.onVersionChange.bind(this));
 -    F.LOG("version change watching enabled");
 +    log.debug("version change watching enabled");
    },
  
    // we need to remove pref 'installedVersion' on uninstalling to be able to
@@@ -42,45 -54,63 +55,63 @@@
      }
    },
  
-   onVersionChange: function(addon) {
-     log.debug("VERSION: "+addon.version);
+   onVersionChange: function() {
 -    F.LOG("VERSION: "+this.addonVersion);
++    log.debug("VERSION: "+this.addonVersion);
  
-     this.curVersion = addon.version;
-     var firstrun = firetray.Utils.prefService.getBoolPref("firstrun");
+     var firstrun = this.addOnPrefs.getBoolPref("firstrun");
  
      if (firstrun) {
 -      F.LOG("FIRST RUN");
 +      log.debug("FIRST RUN");
        this.initPrefs();
-       this.installHook(this.curVersion);
+       this._applyHooks("install");
  
      } else {
        try {
-         var installedVersion = firetray.Utils.prefService.getCharPref("installedVersion");
-         var versionDelta = this.versionComparator.compare(this.curVersion, installedVersion);
+         var installedVersion = this.addOnPrefs.getCharPref("installedVersion");
+         var versionDelta = this.versionComparator.compare(this.addonVersion, installedVersion);
          if (versionDelta > 0) {
-           firetray.Utils.prefService.setCharPref("installedVersion", this.curVersion);
+           this.addOnPrefs.setCharPref("installedVersion", this.addonVersion);
 -          F.LOG("UPGRADE");
 +          log.debug("UPGRADE");
-           this.upgradeHook(this.curVersion);
+           this._applyHooks("upgrade");
          }
  
        } catch (ex) {
 -        F.LOG("REINSTALL");
 +        log.debug("REINSTALL");
          this.initPrefs();
-         this.reinstallHook(this.curVersion);
+         this._applyHooks("reinstall");
        }
      }
+ 
    },
  
    initPrefs: function() {
-     firetray.Utils.prefService.setBoolPref("firstrun", false);
-     firetray.Utils.prefService.setCharPref("installedVersion", VersionChange.curVersion);
+     this.addOnPrefs.setBoolPref("firstrun", false);
+     this.addOnPrefs.setCharPref("installedVersion", VersionChange.addonVersion);
+   },
+ 
+   _hooks: [], // collection of callbacks {id: 1, categories: [], fun: function}
+ 
+   addHook: function(categories, fun) {
+     if (Object.prototype.toString.call(categories) !== "[object Array]") throw new TypeError();
+     let id = this._hooks.push({})-1;
+     this._hooks[id] = {id: id, categories: categories, fun: fun};
+     return id;
    },
  
-   installHook: function(ver){},
-   upgradeHook: function(ver){},
-   reinstallHook: function(ver){},
-   setInstallHook: function(fun) {this.installHook = fun;},
-   setUpgradeHook: function(fun) {this.upgradeHook = fun;},
-   setReinstallHook: function(fun) {this.reinstallHook = fun;}
+   removeHook: function(id) {return this._hooks[id].splice(id-1, 1);},
+   removeCategoryFromHook: function(category, id) {
+     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+   },
+ 
+   _applyHooks: function(category) {
+     try {
 -      F.LOG("_hooks.len="+this._hooks.length+" category="+category);
++      log.debug("_hooks.len="+this._hooks.length+" category="+category);
+       for (let i=0,len=this._hooks.length; i<len; ++i) {
+         let cb = this._hooks[i];
+         if (cb.categories.indexOf(category) > -1) cb.fun();
 -        else F.LOG("cb id="+cb.id+" not in category: "+cb.categories+"\n"+cb.fun);
++        else log.debug("cb id="+cb.id+" not in category: "+cb.categories+"\n"+cb.fun);
+       }
 -    } catch(x){F.ERROR(x);}
++    } catch(x){log.error(x);}
+   }
  
  };
diff --cc src/modules/commons.js
index 746de6f,14a3dd3..102ddef
--- a/src/modules/commons.js
+++ b/src/modules/commons.js
@@@ -1,10 -1,11 +1,10 @@@
  /* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  
- /* for now, logging facilities (imported from logging.jsm) are automatically
-    provided by this module */
+ /* for now, logging facilities (imported from logging.jsm) and Services are
+    automatically provided by this module */
  var EXPORTED_SYMBOLS =
-   [ "firetray", "FIRETRAY_ID", "FIRETRAY_SPLASH_PAGE",
-     "FIRETRAY_APPLICATION_ICON_TYPE_THEMED",
 -  [ "firetray", "F", "Services", "FIRETRAY_ID", "FIRETRAY_VERSION",
 -    "FIRETRAY_PREF_BRANCH", "FIRETRAY_SPLASH_PAGE",
 -    "FIRETRAY_APPLICATION_ICON_TYPE_THEMED",
++  [ "firetray", "FIRETRAY_ID", "FIRETRAY_VERSION", "FIRETRAY_PREF_BRANCH",
++    "FIRETRAY_SPLASH_PAGE", "FIRETRAY_APPLICATION_ICON_TYPE_THEMED",
      "FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM",
      "FIRETRAY_NOTIFICATION_UNREAD_MESSAGE_COUNT",
      "FIRETRAY_NOTIFICATION_NEWMAIL_ICON", "FIRETRAY_NOTIFICATION_CUSTOM_ICON",
@@@ -36,15 -47,17 +48,12 @@@ const FIRETRAY_DELAY_BROWSER_STARTUP_MI
  const FIRETRAY_DELAY_NOWAIT_MILLISECONDS          = 0;
  const FIRETRAY_DELAY_PREF_CLEANING_MILLISECONDS   = 15*60*1000;
  
- const FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD = 0;
- const FIRETRAY_MESSAGE_COUNT_TYPE_NEW    = 1;
- 
 -if ("undefined" == typeof(F)) {
 -  var F = {};                   // helper wrapper
 -};
 -
 -F.FIREFOX_ID     = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 -F.THUNDERBIRD_ID = "{3550f703-e582-4d05-9a08-453d09bdfdc6}";
 -F.SONGBIRD_ID    = "songbird at songbirdnest.com";
 -F.SUNBIRD_ID     = "{718e30fb-e89b-41dd-9da7-e25a45638b28}";
 -F.SEAMONKEY_ID   = "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}";
 -F.CHATZILLA_ID   = "{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}";
 -
 +const FIRETRAY_FIREFOX_ID     = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 +const FIRETRAY_THUNDERBIRD_ID = "{3550f703-e582-4d05-9a08-453d09bdfdc6}";
 +const FIRETRAY_SONGBIRD_ID    = "songbird at songbirdnest.com";
 +const FIRETRAY_SUNBIRD_ID     = "{718e30fb-e89b-41dd-9da7-e25a45638b28}";
 +const FIRETRAY_SEAMONKEY_ID   = "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}";
 +const FIRETRAY_CHATZILLA_ID   = "{59c81df5-4b7a-477b-912d-4e0fdf64e5f2}";
  
  /**
   * firetray namespace.
@@@ -53,12 -66,31 +62,33 @@@ if ("undefined" == typeof(firetray)) 
    var firetray = {};
  };
  
 +let log = firetray.Logger.getLogger("firetray.commons");
 +
  firetray.Utils = {
-   prefService: Services.prefs.getBranch("extensions.firetray."),
+   prefService: Services.prefs.getBranch(FIRETRAY_PREF_BRANCH),
    strings: Services.strings.createBundle("chrome://firetray/locale/overlay.properties"),
  
+   addObservers: function(handler, topics){
+     topics.forEach(function(topic){
+       Services.obs.addObserver(this, topic, false);
+       this.observedTopics[topic] = true;
 -      F.LOG("registred "+topic+" for "+handler);
++      log.debug("registred "+topic+" for "+handler);
+     }, handler);
+   },
+ 
+   removeObservers: function(handler, topics) {
+     topics.forEach(function(topic){
+       Services.obs.removeObserver(this, topic);
+       delete this.observedTopics[topic];
+     }, handler);
+   },
+ 
+   removeAllObservers: function(handler) {
+     for (let topic in handler.observedTopics)
+       Services.obs.removeObserver(handler, topic);
+     handler.observedTopics = {};
+   },
+ 
    getObjPref: function(prefStr) {
      try {
        var objPref = JSON.parse(
diff --cc src/modules/ctypes/ctypes-utils.jsm
index 13cd9bb,1b7f788..3fa4fad
--- a/src/modules/ctypes/ctypes-utils.jsm
+++ b/src/modules/ctypes/ctypes-utils.jsm
@@@ -123,8 -121,10 +123,10 @@@ function ctypes_library(aName, aABIs, a
        }
      }
  
+     this.name = aName;
+ 
      this.close = function() {
 -      F.LOG("Closing library " + aName);
 +      log.debug("Closing library " + aName);
        library.close();
        this.ABI = -1;
  
diff --cc src/modules/linux/FiretrayChatStatusIcon.jsm
index 0000000,83d57f6..7a86e6c
mode 000000,100644..100644
--- a/src/modules/linux/FiretrayChatStatusIcon.jsm
+++ b/src/modules/linux/FiretrayChatStatusIcon.jsm
@@@ -1,0 -1,115 +1,117 @@@
+ /* -*- 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/linux/gobject.jsm");
+ Cu.import("resource://firetray/ctypes/linux/gio.jsm");
+ Cu.import("resource://firetray/ctypes/linux/gdk.jsm");
+ Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
+ Cu.import("resource://firetray/linux/FiretrayWindow.jsm");
+ Cu.import("resource://firetray/commons.js");
+ firetray.Handler.subscribeLibsForClosing([gobject, gio, gtk]);
+ 
+ if ("undefined" == typeof(firetray.Handler))
 -  F.ERROR("This module MUST be imported from/after FiretrayHandler !");
++  log.error("This module MUST be imported from/after FiretrayHandler !");
++
++let log = firetray.Logger.getLogger("firetray.ChatStatusIcon");
+ 
+ 
+ firetray.ChatStatusIcon = {
+   GTK_THEME_ICON_PATH: null,
+ 
+   initialized: false,
+   trayIcon: null,
+   appId:      (function(){return Services.appinfo.ID;})(),
+   themedIcons: (function(){let o = {};
+     o[FIRETRAY_IM_STATUS_AVAILABLE] = null;
+     o[FIRETRAY_IM_STATUS_AWAY] = null;
+     o[FIRETRAY_IM_STATUS_BUSY] = null;
+     o[FIRETRAY_IM_STATUS_OFFLINE] = null;
+     return o;
+   })(),
+   callbacks: {onFocusIn: {}},
+ 
+   init: function() {
+     if (!firetray.Handler.inMailApp) throw "ChatStatusIcon for mail app only";
+     if (!firetray.GtkIcons.initialized) throw "GtkIcons should have been initialized by StatusIcon";
+ 
+     this.trayIcon = gtk.gtk_status_icon_new();
+     this.loadThemedIcons();
+     this.setIconImage(FIRETRAY_IM_STATUS_OFFLINE);
+     this.setIconTooltipDefault();
+ 
+     this.initialized = true;
+     return true;
+   },
+ 
+   shutdown: function() {
+     this.destroyIcons();
+     this.initialized = false;
+   },
+ 
+   loadThemedIcons: function() {
+     for (let name in this.themedIcons)
+       this.themedIcons[name] = gio.g_themed_icon_new(name);
+   },
+ 
+   destroyIcons: function() {
+     for (let name in this.themedIcons) {
+       let gicon = this.themedIcons[name];
+       gicon = gobject.g_object_unref(gicon);
+     }
+     gobject.g_object_unref(this.trayIcon);
+   },
+ 
+   setIconImageFromGIcon: function(gicon) {
+     if (!firetray.ChatStatusIcon.trayIcon || !gicon)
 -      F.ERROR("Icon missing");
 -    F.LOG(gicon);
++      log.error("Icon missing");
++    log.debug(gicon);
+     gtk.gtk_status_icon_set_from_gicon(firetray.ChatStatusIcon.trayIcon, gicon);
+   },
+ 
+   setIconImage: function(name) {
+     this.setIconImageFromGIcon(this.themedIcons[name]);
+   },
+ 
+   setIconBlinking: function(blink) {
+     gtk.gtk_status_icon_set_blinking(this.trayIcon, blink);
+   },
+ 
+   setIconTooltip: function(txt) {
+     if (!this.trayIcon) return false;
+     gtk.gtk_status_icon_set_tooltip_text(this.trayIcon, txt);
+     return true;
+   },
+ 
+   setIconTooltipDefault: function() {
+     this.setIconTooltip(firetray.Handler.appName+" Chat");
+   },
+ 
+   attachOnFocusInCallback: function(xid) {
 -    F.LOG("attachOnFocusInCallback xid="+xid);
++    log.debug("attachOnFocusInCallback xid="+xid);
+     this.callbacks.onFocusIn[xid] = gtk.GCallbackWidgetFocuEvent_t(firetray.ChatStatusIcon.onFocusIn);
+     gobject.g_signal_connect(firetray.Handler.gtkWindows.get(xid),
+       "focus-in-event", firetray.ChatStatusIcon.callbacks.onFocusIn[xid], null);
+   },
+ 
+   // NOTE: fluxbox issues a FocusIn event when switching workspace by hotkey :(
+   // (http://sourceforge.net/tracker/index.php?func=detail&aid=3190205&group_id=35398&atid=413960)
+   onFocusIn: function(widget, event, data) {
 -    F.LOG("onFocusIn");
++    log.debug("onFocusIn");
+     // let gdkEventFocus = ctypes.cast(event, gdk.GdkEventFocus.ptr);
+     // let gdkWin = gdkEventFocus.contents.window;
+     // let xid = firetray.Window.getXIDFromGdkWindow(gdkWin);
 -    // F.LOG("xid="+xid+" in="+gdkEventFocus.contents["in"]);
++    // log.debug("xid="+xid+" in="+gdkEventFocus.contents["in"]);
+     firetray.Chat.stopIconBlinkingMaybe();
+   }
+ 
+   // FIXME: TODO: onclick/activate -> chatHandler.showCurrentConversation()
+ 
+ }; // firetray.ChatStatusIcon
diff --cc src/modules/linux/FiretrayGtkIcons.jsm
index 0000000,0d47664..7605a50
mode 000000,100644..100644
--- a/src/modules/linux/FiretrayGtkIcons.jsm
+++ b/src/modules/linux/FiretrayGtkIcons.jsm
@@@ -1,0 -1,47 +1,49 @@@
+ /* -*- 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://firetray/ctypes/linux/gtk.jsm");
+ Cu.import("resource://firetray/commons.js");
+ firetray.Handler.subscribeLibsForClosing([gtk]);
+ 
+ if ("undefined" == typeof(firetray.StatusIcon))
 -  F.ERROR("This module MUST be imported from/after StatusIcon !");
++  log.error("This module MUST be imported from/after StatusIcon !");
++
++let log = firetray.Logger.getLogger("firetray.GtkIcons");
+ 
+ 
+ firetray.GtkIcons = {
+   initialized: false,
+ 
+   GTK_THEME_ICON_PATH: null,
+ 
+   init: function() {
+     try {
+       if (this.initialized) return true;
+ 
+       this.loadDefaultTheme();
+       this.initialized = true;
+       return true;
+     } catch (x) {
 -      F.ERROR(x);
++      log.error(x);
+       return false;
+     }
+   },
+ 
+   shutdown: function() {
+     this.initialized = false;
+   },
+ 
+   loadDefaultTheme: function() {
+     this.GTK_THEME_ICON_PATH = firetray.Utils.chromeToPath("chrome://firetray/skin/linux/icons");
 -    F.LOG(this.GTK_THEME_ICON_PATH);
++    log.debug(this.GTK_THEME_ICON_PATH);
+     let gtkIconTheme = gtk.gtk_icon_theme_get_default();
 -    F.LOG("gtkIconTheme="+gtkIconTheme);
++    log.debug("gtkIconTheme="+gtkIconTheme);
+     gtk.gtk_icon_theme_append_search_path(gtkIconTheme, this.GTK_THEME_ICON_PATH);
+   }
+ 
+ };
diff --cc src/modules/linux/FiretrayPopupMenu.jsm
index 9050edd,60fb564..74401ee
--- a/src/modules/linux/FiretrayPopupMenu.jsm
+++ b/src/modules/linux/FiretrayPopupMenu.jsm
@@@ -12,11 -12,10 +12,12 @@@ Cu.import("resource://gre/modules/ctype
  Cu.import("resource://firetray/ctypes/linux/gobject.jsm");
  Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
  Cu.import("resource://firetray/commons.js");
+ firetray.Handler.subscribeLibsForClosing([gobject, gtk]);
  
 +let log = firetray.Logger.getLogger("firetray.PopupMenu");
 +
  if ("undefined" == typeof(firetray.StatusIcon))
 -  F.ERROR("This module MUST be imported from/after StatusIcon !");
 +  log.error("This module MUST be imported from/after StatusIcon !");
  
  
  firetray.PopupMenu = {
@@@ -62,7 -61,7 +63,7 @@@
    },
  
    shutdown: function() {
-     firetray.Utils.tryCloseLibs([gobject, gtk]);
 -    F.LOG("Disabling PopupMenu");
++    log.debug("Disabling PopupMenu");
      this.initialized = false;
    },
  
diff --cc src/modules/linux/FiretrayStatusIcon.jsm
index b657cc8,eaacc72..8d8e8ff
--- a/src/modules/linux/FiretrayStatusIcon.jsm
+++ b/src/modules/linux/FiretrayStatusIcon.jsm
@@@ -17,11 -17,10 +17,12 @@@ Cu.import("resource://firetray/ctypes/l
  Cu.import("resource://firetray/ctypes/linux/pango.jsm");
  Cu.import("resource://firetray/ctypes/linux/pangocairo.jsm");
  Cu.import("resource://firetray/commons.js");
+ firetray.Handler.subscribeLibsForClosing([cairo, gobject, gdk, gio, gtk, pango, pangocairo]);
  
 +let log = firetray.Logger.getLogger("firetray.StatusIcon");
 +
  if ("undefined" == typeof(firetray.Handler))
 -  F.ERROR("This module MUST be imported from/after FiretrayHandler !");
 +  log.error("This module MUST be imported from/after FiretrayHandler !");
  
  
  firetray.StatusIcon = {
@@@ -71,8 -60,10 +62,10 @@@
    },
  
    shutdown: function() {
 -    F.LOG("Disabling StatusIcon");
++    log.debug("Disabling StatusIcon");
      firetray.PopupMenu.shutdown();
-     firetray.Utils.tryCloseLibs([cairo, gobject, gdk, gio, gtk, pango, pangocairo]);
+     // FIXME: should destroy/hide icon here
+     firetray.GtkIcons.shutdown();
      this.initialized = false;
    },
  
diff --cc src/modules/linux/FiretrayWindow.jsm
index f2ea64b,c6424f0..6c43ac3
--- a/src/modules/linux/FiretrayWindow.jsm
+++ b/src/modules/linux/FiretrayWindow.jsm
@@@ -23,11 -23,10 +23,12 @@@ Cu.import("resource://firetray/ctypes/l
  Cu.import("resource://firetray/ctypes/linux/libc.jsm");
  Cu.import("resource://firetray/ctypes/linux/x11.jsm");
  Cu.import("resource://firetray/commons.js");
+ firetray.Handler.subscribeLibsForClosing([gobject, gdk, gtk, libc, x11, glib]);
  
 +let log = firetray.Logger.getLogger("firetray.Window");
 +
  if ("undefined" == typeof(firetray.Handler))
 -  F.ERROR("This module MUST be imported from/after FiretrayHandler !");
 +  log.error("This module MUST be imported from/after FiretrayHandler !");
  
  const Services2 = {};
  XPCOMUtils.defineLazyServiceGetter(
@@@ -588,9 -595,14 +588,14 @@@ firetray.Handler.registerWindow = funct
      this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow);
      gdk.gdk_window_add_filter(gdkWin, this.windows[xid].filterWindowCb, null);
  
+     if (firetray.Handler.inMailApp && firetray.Chat.initialized) { // missing import ok
+       Cu.import("resource://firetray/linux/FiretrayChatStatusIcon.jsm");
+       firetray.ChatStatusIcon.attachOnFocusInCallback(xid);
+     }
+ 
    } catch (x) {
      firetray.Window.unregisterWindowByXID(xid);
 -    F.ERROR(x);
 +    log.error(x);
      return null;
    }
  
@@@ -649,6 -661,29 +654,29 @@@ firetray.Handler.activateLastWindow = f
    return stopPropagation;
  };
  
+ /* gtk_window_is_active() not reliable */
+ firetray.Handler.findActiveWindow = function() {
+   let rootWin = x11.XDefaultRootWindow(x11.current.Display);
+   let [propsFound, nitems] =
+     firetray.Window.getXWindowProperties(rootWin, x11.current.Atoms._NET_ACTIVE_WINDOW);
+ 
 -  F.LOG("ACTIVE_WINDOW propsFound, nitems="+propsFound+", "+nitems);
++  log.debug("ACTIVE_WINDOW propsFound, nitems="+propsFound+", "+nitems);
+   if (!propsFound) return null;
+ 
+   let activeWin = null;
+   if (firetray.js.strEquals(nitems.value, 0))
 -    F.WARN("active window not found");
++    log.warn("active window not found");
+   else if (firetray.js.strEquals(nitems.value, 1))
+     activeWin = propsFound.contents[0];
+   else
+     throw new RangeError("more than one active window found");
+ 
+   x11.XFree(propsFound);
+ 
 -  F.LOG("ACTIVE_WINDOW="+activeWin);
++  log.debug("ACTIVE_WINDOW="+activeWin);
+   return activeWin;
+ };
+ 
  
  /**
   * init X11 Display and handled XAtoms.

-- 
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