mirror of
https://github.com/moparisthebest/FireTray
synced 2024-08-13 15:53:47 -04:00
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
This commit is contained in:
commit
ae0f41e1e4
@ -89,4 +89,4 @@ Acknowledgment
|
||||
[Nils Maier](https://addons.mozilla.org/fr/firefox/addon/minimizetotray-revived/
|
||||
"MinToTrayR addon page").
|
||||
* kind support from Neil Deaking, Bobby Holley
|
||||
|
||||
* default icons borrowed from Mozilla and Pidgin
|
||||
|
@ -5,6 +5,7 @@ const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://firetray/FiretrayHandler.jsm");
|
||||
Cu.import("resource://firetray/FiretrayChat.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
|
||||
const TREEROW_ACCOUNT_OR_SERVER_TYPE_NAME = 0;
|
||||
@ -640,6 +641,14 @@ var firetrayUIOptions = {
|
||||
if (!/\d/.test(charStr))
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
|
||||
toggleChat: function(enabled) {
|
||||
log.debug("Chat icon enable="+enabled);
|
||||
if (enabled)
|
||||
firetray.Chat.init();
|
||||
else
|
||||
firetray.Chat.shutdown();
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -30,6 +30,7 @@
|
||||
<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" />
|
||||
@ -45,6 +46,7 @@
|
||||
<tab label="&windows_options;"/>
|
||||
<tab label="&icon_options;"/>
|
||||
<tab label="&mail_options;" id="mail_tab" />
|
||||
<tab label="&chat_options;" />
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
|
||||
@ -52,27 +54,27 @@
|
||||
<vbox pack="start" align="left" flex="1">
|
||||
|
||||
<checkbox id="ui_hides_on_close" preference="pref_hides_on_close"
|
||||
label="&bool_hides_on_close.label;"
|
||||
accesskey="&bool_hides_on_close.accesskey;"
|
||||
label="&hides_on_close.label;"
|
||||
accesskey="&hides_on_close.accesskey;"
|
||||
oncommand="firetrayUIOptions.updateWindowAndIconOptions();"/>
|
||||
<checkbox id="ui_hides_on_minimize" preference="pref_hides_on_minimize"
|
||||
label="&bool_hides_on_minimize.label;"
|
||||
accesskey="&bool_hides_on_minimize.accesskey;"
|
||||
label="&hides_on_minimize.label;"
|
||||
accesskey="&hides_on_minimize.accesskey;"
|
||||
oncommand="firetrayUIOptions.updateWindowAndIconOptions();"/>
|
||||
<checkbox id="ui_hides_single_window" preference="pref_hides_single_window"
|
||||
label="&bool_hides_single_window.label;"
|
||||
accesskey="&bool_hides_single_window.accesskey;"
|
||||
tooltiptext="&bool_hides_single_window.tooltip;"/>
|
||||
label="&hides_single_window.label;"
|
||||
accesskey="&hides_single_window.accesskey;"
|
||||
tooltiptext="&hides_single_window.tooltip;"/>
|
||||
<checkbox id="ui_start_hidden" preference="pref_start_hidden"
|
||||
label="&bool_start_hidden.label;"
|
||||
accesskey="&bool_start_hidden.accesskey;"/>
|
||||
label="&start_hidden.label;"
|
||||
accesskey="&start_hidden.accesskey;"/>
|
||||
<checkbox id="ui_show_activates" preference="pref_show_activates"
|
||||
label="&bool_show_activates.label;"
|
||||
accesskey="&bool_show_activates.accesskey;"
|
||||
tooltiptext="&bool_show_activates.tooltip;"/>
|
||||
label="&show_activates.label;"
|
||||
accesskey="&show_activates.accesskey;"
|
||||
tooltiptext="&show_activates.tooltip;"/>
|
||||
<checkbox id="ui_remember_desktop" preference="pref_remember_desktop"
|
||||
label="&bool_remember_desktop.label;"
|
||||
accesskey="&bool_remember_desktop.accesskey;"/>
|
||||
label="&remember_desktop.label;"
|
||||
accesskey="&remember_desktop.accesskey;"/>
|
||||
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
@ -114,8 +116,8 @@
|
||||
</radiogroup>
|
||||
|
||||
<checkbox id="ui_show_icon_on_hide" preference="pref_show_icon_on_hide"
|
||||
label="&bool_show_icon_on_hide.label;"
|
||||
accesskey="&bool_show_icon_on_hide.accesskey;"/>
|
||||
label="&show_icon_on_hide.label;"
|
||||
accesskey="&show_icon_on_hide.accesskey;"/>
|
||||
|
||||
<checkbox id="ui_scroll_hides" preference="pref_scroll_hides"
|
||||
label="&enable_mouse_scroll.label;"
|
||||
@ -286,6 +288,17 @@
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="chat_tabpanel" flex="1">
|
||||
<vbox align="left" flex="1">
|
||||
|
||||
<checkbox id="ui_chat_icon_enable" preference="pref_chat_icon_enable"
|
||||
label="&chat_icon_enable.label;"
|
||||
accesskey="&chat_icon_enable.accesskey;"
|
||||
oncommand="firetrayUIOptions.toggleChat(this.checked);"/>
|
||||
|
||||
</vbox>
|
||||
</tabpanel>
|
||||
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
||||
|
@ -7,24 +7,25 @@
|
||||
<!ENTITY windows_options "Windows">
|
||||
<!ENTITY icon_options "Icon">
|
||||
<!ENTITY mail_options "Mail">
|
||||
<!ENTITY chat_options "Chat">
|
||||
|
||||
<!ENTITY bool_hides_on_close.label "Closing window hides to tray">
|
||||
<!ENTITY bool_hides_on_close.accesskey "C">
|
||||
<!ENTITY bool_hides_on_minimize.label "Minimizing window hides to tray">
|
||||
<!ENTITY bool_hides_on_minimize.accesskey "M">
|
||||
<!ENTITY bool_hides_single_window.label "Hide windows individually">
|
||||
<!ENTITY bool_hides_single_window.tooltip "not all windows at once">
|
||||
<!ENTITY bool_hides_single_window.accesskey "H">
|
||||
<!ENTITY bool_start_hidden.label "Start application hidden to tray">
|
||||
<!ENTITY bool_start_hidden.accesskey "S">
|
||||
<!ENTITY bool_show_activates.label "Activate restored windows">
|
||||
<!ENTITY bool_show_activates.accesskey "e">
|
||||
<!ENTITY bool_show_activates.tooltip "restored windows raise on top and get focus">
|
||||
<!ENTITY bool_remember_desktop.label "Remember desktop (per-window)">
|
||||
<!ENTITY bool_remember_desktop.accesskey "R">
|
||||
<!ENTITY hides_on_close.label "Closing window hides to tray">
|
||||
<!ENTITY hides_on_close.accesskey "C">
|
||||
<!ENTITY hides_on_minimize.label "Minimizing window hides to tray">
|
||||
<!ENTITY hides_on_minimize.accesskey "M">
|
||||
<!ENTITY hides_single_window.label "Hide windows individually">
|
||||
<!ENTITY hides_single_window.tooltip "not all windows at once">
|
||||
<!ENTITY hides_single_window.accesskey "H">
|
||||
<!ENTITY start_hidden.label "Start application hidden to tray">
|
||||
<!ENTITY start_hidden.accesskey "S">
|
||||
<!ENTITY show_activates.label "Activate restored windows">
|
||||
<!ENTITY show_activates.accesskey "e">
|
||||
<!ENTITY show_activates.tooltip "restored windows raise on top and get focus">
|
||||
<!ENTITY remember_desktop.label "Remember desktop (per-window)">
|
||||
<!ENTITY remember_desktop.accesskey "R">
|
||||
|
||||
<!ENTITY bool_show_icon_on_hide.label "Show tray icon only if a window is hidden">
|
||||
<!ENTITY bool_show_icon_on_hide.accesskey "w">
|
||||
<!ENTITY show_icon_on_hide.label "Show tray icon only if a window is hidden">
|
||||
<!ENTITY show_icon_on_hide.accesskey "w">
|
||||
<!ENTITY app_icon_type "Application icon type">
|
||||
<!ENTITY app_icon_themed.label "Default themed">
|
||||
<!ENTITY app_icon_themed.accesskey "D">
|
||||
@ -81,3 +82,6 @@
|
||||
<!ENTITY account_or_server_type_excluded.tooltip "Includes accounts or types into unread messages count">
|
||||
<!ENTITY account_or_server_type_order "Order">
|
||||
<!ENTITY account_or_server_type_order.tooltip "Order in which mail server types are displayed. Double-clic to edit.">
|
||||
|
||||
<!ENTITY chat_icon_enable.label "Enable chat icon">
|
||||
<!ENTITY chat_icon_enable.accesskey "E">
|
||||
|
@ -0,0 +1 @@
|
||||
../../../../../pidgin-tray-available.png
|
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-away.png
Symbolic link
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-away.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../../pidgin-tray-away.png
|
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-busy.png
Symbolic link
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-busy.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../../pidgin-tray-busy.png
|
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-offline.png
Symbolic link
1
src/chrome/skin/linux/icons/gnome/22x22/status/user-offline.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../../pidgin-tray-offline.png
|
BIN
src/chrome/skin/pidgin-tray-available.png
Normal file
BIN
src/chrome/skin/pidgin-tray-available.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
src/chrome/skin/pidgin-tray-away.png
Normal file
BIN
src/chrome/skin/pidgin-tray-away.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
src/chrome/skin/pidgin-tray-busy.png
Normal file
BIN
src/chrome/skin/pidgin-tray-busy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
src/chrome/skin/pidgin-tray-offline.png
Normal file
BIN
src/chrome/skin/pidgin-tray-offline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -20,6 +20,7 @@ pref("extensions.firetray.new_mail_icon_names", '["indicator-messages-new", "mai
|
||||
pref("extensions.firetray.show_icon_on_hide", false);
|
||||
pref("extensions.firetray.scroll_hides", true);
|
||||
pref("extensions.firetray.scroll_mode", "down_hides");
|
||||
pref("extensions.firetray.chat_icon_enable", true);
|
||||
|
||||
pref("extensions.firetray.message_count_type", 0);
|
||||
pref("extensions.firetray.mail_notification_enabled", true);
|
||||
@ -31,5 +32,5 @@ pref("extensions.firetray.folder_count_recursive", true);
|
||||
// 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);
|
||||
|
@ -5,7 +5,7 @@
|
||||
<em:unpack>true</em:unpack> <!-- needed for embedded icons -->
|
||||
<em:type>2</em:type>
|
||||
<em:name>FireTray</em:name>
|
||||
<em:version>0.4.2</em:version>
|
||||
<em:version>0.4.2</em:version> <!-- change FIRETRAY_VERSION accordingly ! -->
|
||||
<em:creator>Hua Luo, Francesco Solero, Foudil BRÉTEL</em:creator>
|
||||
<em:contributor>Hua Luo, Francesco Solero (Firetray original authors)</em:contributor>
|
||||
<em:homepageURL>https://github.com/foudfou/firetray</em:homepageURL>
|
||||
@ -18,7 +18,7 @@
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
||||
<em:minVersion>7.0</em:minVersion>
|
||||
<em:minVersion>13.0</em:minVersion>
|
||||
<em:maxVersion>15.0a1</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
@ -26,8 +26,8 @@
|
||||
<em:targetApplication> <!-- Thunderbird -->
|
||||
<Description>
|
||||
<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
|
||||
<em:minVersion>7.0</em:minVersion>
|
||||
<em:maxVersion>15.0a1</em:maxVersion>
|
||||
<em:minVersion>15.0</em:minVersion>
|
||||
<em:maxVersion>17.0a1</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
|
169
src/modules/FiretrayChat.jsm
Normal file
169
src/modules/FiretrayChat.jsm
Normal file
@ -0,0 +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) {
|
||||
log.warn("Chat already initialized");
|
||||
return;
|
||||
}
|
||||
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;
|
||||
log.debug("Disabling Chat");
|
||||
|
||||
firetray.ChatStatusIcon.shutdown();
|
||||
firetray.Utils.removeAllObservers(firetray.Chat);
|
||||
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
observe: function(subject, topic, 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;
|
||||
log.debug("conversation name="+conv.name); // normalizedName shouldn't be necessary
|
||||
|
||||
let convIsActiveTabInActiveWin = this.isConvActiveTabInActiveWindow(conv);
|
||||
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:
|
||||
log.warn("unhandled topic: "+topic);
|
||||
}
|
||||
},
|
||||
|
||||
stopIconBlinkingMaybe: function() {
|
||||
log.debug("acknowledgeOnFocus.must="+this.acknowledgeOnFocus.must);
|
||||
if (!this.acknowledgeOnFocus.must) return;
|
||||
|
||||
let convIsActiveTabInActiveWin = this.isConvActiveTabInActiveWindow(
|
||||
this.acknowledgeOnFocus.conv);
|
||||
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;
|
||||
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
|
||||
}
|
||||
|
||||
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);
|
||||
log.debug("account="+account+" STATUS="+account.statusInfo.statusType+" connected="+account.connected);
|
||||
globalConnected = globalConnected || account.connected;
|
||||
}
|
||||
log.debug("globalConnected="+globalConnected);
|
||||
return globalConnected;
|
||||
}
|
||||
|
||||
};
|
@ -29,21 +29,20 @@ let log = firetray.Logger.getLogger("firetray.Handler");
|
||||
// other global functions
|
||||
// (https://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management)
|
||||
firetray.Handler = {
|
||||
FILENAME_DEFAULT: null,
|
||||
FILENAME_SUFFIX: "32.png",
|
||||
FILENAME_BLANK: null,
|
||||
FILENAME_NEWMAIL: null,
|
||||
|
||||
initialized: false,
|
||||
inMailApp: false,
|
||||
inBrowserApp: false,
|
||||
inMailApp: false,
|
||||
appStarted: false,
|
||||
windows: {},
|
||||
windowsCount: 0,
|
||||
visibleWindowsCount: 0,
|
||||
observedTopics: {},
|
||||
ctypesLibs: {}, // {"lib1": lib1, "lib2": lib2}
|
||||
|
||||
appId: (function(){return Services.appinfo.ID;})(),
|
||||
appName: (function(){return Services.appinfo.name;})(),
|
||||
appStartupTopic: null,
|
||||
runtimeABI: (function(){return Services.appinfo.XPCOMABI;})(),
|
||||
runtimeOS: (function(){return Services.appinfo.OS;})(), // "WINNT", "Linux", "Darwin"
|
||||
addonRootDir: (function(){
|
||||
@ -79,12 +78,14 @@ firetray.Handler = {
|
||||
this.inBrowserApp = true;
|
||||
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();
|
||||
@ -103,19 +104,8 @@ firetray.Handler = {
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, this.getAppStartupTopic(this.appId), false);
|
||||
Services.obs.addObserver(this, "xpcom-will-shutdown", false);
|
||||
Services.obs.addObserver(this, "profile-change-teardown", false);
|
||||
|
||||
let welcome = function(ver) {
|
||||
firetray.Handler.openTab(FIRETRAY_SPLASH_PAGE+"#v"+ver);
|
||||
firetray.Handler.tryEraseOldOptions();
|
||||
firetray.Handler.correctMailNotificationType();
|
||||
};
|
||||
VersionChange.setInstallHook(welcome);
|
||||
VersionChange.setUpgradeHook(welcome);
|
||||
VersionChange.setReinstallHook(welcome);
|
||||
VersionChange.watch();
|
||||
firetray.Utils.addObservers(firetray.Handler, [ this.appStartupTopic,
|
||||
"xpcom-will-shutdown", "profile-change-teardown" ]);
|
||||
|
||||
this.preventWarnOnClose();
|
||||
|
||||
@ -124,23 +114,40 @@ firetray.Handler = {
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
log.debug("Disabling Handler");
|
||||
firetray.PrefListener.unregister();
|
||||
|
||||
if (this.inMailApp)
|
||||
firetray.Messaging.shutdown();
|
||||
firetray.StatusIcon.shutdown();
|
||||
firetray.Window.shutdown();
|
||||
// watchout order and sufficiency of lib closings (tryCloseLibs())
|
||||
this.tryCloseLibs();
|
||||
|
||||
Services.obs.removeObserver(this, this.getAppStartupTopic(this.appId), false);
|
||||
Services.obs.removeObserver(this, "xpcom-will-shutdown", false);
|
||||
Services.obs.removeObserver(this, "profile-change-teardown", false);
|
||||
firetray.Utils.removeAllObservers(this);
|
||||
|
||||
this.appStarted = false;
|
||||
this.initialized = false;
|
||||
return true;
|
||||
},
|
||||
|
||||
tryCloseLibs: function() {
|
||||
try {
|
||||
for (libName in this.ctypesLibs) {
|
||||
let lib = this.ctypesLibs[libName];
|
||||
if (lib.available())
|
||||
lib.close();
|
||||
};
|
||||
} 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,6 +201,7 @@ firetray.Handler = {
|
||||
showWindow: function(winId) {},
|
||||
showHideAllWindows: function() {},
|
||||
activateLastWindow: function(gtkStatusIcon, gdkEvent, userData) {},
|
||||
findActiveWindow: function() {},
|
||||
|
||||
showAllWindows: function() {
|
||||
log.debug("showAllWindows");
|
||||
@ -294,75 +302,6 @@ firetray.Handler = {
|
||||
} catch (x) { log.error(x); }
|
||||
},
|
||||
|
||||
openTab: function(url) {
|
||||
if (this.appId === FIRETRAY_THUNDERBIRD_ID)
|
||||
this.openMailTab(url);
|
||||
else if (this.appId === FIRETRAY_FIREFOX_ID || this.appId === FIRETRAY_SEAMONKEY_ID)
|
||||
this.openBrowserTab(url);
|
||||
else
|
||||
log.error("unsupported application");
|
||||
},
|
||||
|
||||
openMailTab: function(url) {
|
||||
let mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
|
||||
if (mail3PaneWindow) {
|
||||
var tabmail = mail3PaneWindow.document.getElementById("tabmail");
|
||||
mail3PaneWindow.focus();
|
||||
}
|
||||
|
||||
if (tabmail) {
|
||||
firetray.Utils.timer(function() {
|
||||
log.debug("openMailTab");
|
||||
tabmail.openTab("contentTab", {contentPage: url});
|
||||
}, FIRETRAY_DELAY_BROWSER_STARTUP_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
},
|
||||
|
||||
openBrowserTab: function(url) {
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
log.debug("WIN="+win);
|
||||
if (win) {
|
||||
var mainWindow = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
|
||||
mainWindow.setTimeout(function(win){
|
||||
log.debug("openBrowser");
|
||||
mainWindow.gBrowser.selectedTab = mainWindow.gBrowser.addTab(url);
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
tryEraseOldOptions: function() {
|
||||
let v03Options = [
|
||||
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
||||
"restore_to_next_unread", "mail_count_type", "show_mail_count",
|
||||
"dont_count_spam", "dont_count_archive", "dont_count_drafts",
|
||||
"dont_count_sent", "dont_count_templates", "show_mail_notification",
|
||||
"show_icon_only_minimized", "use_custom_normal_icon",
|
||||
"use_custom_special_icon", "custom_normal_icon", "custom_special_icon",
|
||||
"text_color", "scroll_to_hide", "scroll_action", "grab_multimedia_keys",
|
||||
"hide_show_mm_key", "accounts_to_exclude" ];
|
||||
let v040b2Options = [ 'mail_notification' ];
|
||||
let oldOptions = v03Options.concat(v040b2Options);
|
||||
|
||||
for (let i = 0, length = oldOptions.length; i<length; ++i) {
|
||||
try {
|
||||
firetray.Utils.prefService.clearUserPref(oldOptions[i]);
|
||||
} catch (x) {}
|
||||
}
|
||||
},
|
||||
|
||||
correctMailNotificationType: function() {
|
||||
if (firetray.Utils.prefService.getIntPref('message_count_type') ===
|
||||
FIRETRAY_MESSAGE_COUNT_TYPE_NEW)
|
||||
firetray.Utils.prefService.setIntPref('mail_notification_type',
|
||||
FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
|
||||
},
|
||||
|
||||
quitApplication: function() {
|
||||
try {
|
||||
firetray.Utils.timer(function() {
|
||||
@ -421,3 +360,94 @@ firetray.PrefListener = new PrefListener(
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
firetray.VersionChangeHandler = {
|
||||
|
||||
showReleaseNotes: function() {
|
||||
firetray.VersionChangeHandler.openTab(FIRETRAY_SPLASH_PAGE+"#v"+FIRETRAY_VERSION);
|
||||
},
|
||||
|
||||
openTab: function(url) {
|
||||
if (this.appId === FIRETRAY_THUNDERBIRD_ID)
|
||||
this.openMailTab(url);
|
||||
else if (this.appId === FIRETRAY_FIREFOX_ID || this.appId === FIRETRAY_SEAMONKEY_ID)
|
||||
this.openBrowserTab(url);
|
||||
else
|
||||
log.error("unsupported application");
|
||||
},
|
||||
|
||||
openMailTab: function(url) {
|
||||
let mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
|
||||
if (mail3PaneWindow) {
|
||||
var tabmail = mail3PaneWindow.document.getElementById("tabmail");
|
||||
mail3PaneWindow.focus();
|
||||
}
|
||||
|
||||
if (tabmail) {
|
||||
firetray.Utils.timer(function() {
|
||||
log.debug("openMailTab");
|
||||
tabmail.openTab("contentTab", {contentPage: url});
|
||||
}, FIRETRAY_DELAY_BROWSER_STARTUP_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
},
|
||||
|
||||
openBrowserTab: function(url) {
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
log.debug("WIN="+win);
|
||||
if (win) {
|
||||
var mainWindow = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
|
||||
mainWindow.setTimeout(function(win){
|
||||
log.debug("openBrowser");
|
||||
mainWindow.gBrowser.selectedTab = mainWindow.gBrowser.addTab(url);
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
tryEraseOldOptions: function() {
|
||||
let v03Options = [
|
||||
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
||||
"restore_to_next_unread", "mail_count_type", "show_mail_count",
|
||||
"dont_count_spam", "dont_count_archive", "dont_count_drafts",
|
||||
"dont_count_sent", "dont_count_templates", "show_mail_notification",
|
||||
"show_icon_only_minimized", "use_custom_normal_icon",
|
||||
"use_custom_special_icon", "custom_normal_icon", "custom_special_icon",
|
||||
"text_color", "scroll_to_hide", "scroll_action", "grab_multimedia_keys",
|
||||
"hide_show_mm_key", "accounts_to_exclude" ];
|
||||
let v040b2Options = [ 'mail_notification' ];
|
||||
let oldOptions = v03Options.concat(v040b2Options);
|
||||
|
||||
for (let i = 0, length = oldOptions.length; i<length; ++i) {
|
||||
try {
|
||||
let option = oldOptions[i];
|
||||
firetray.Utils.prefService.clearUserPref(option);
|
||||
} catch (x) {}
|
||||
}
|
||||
},
|
||||
|
||||
correctMailNotificationType: function() {
|
||||
if (firetray.Utils.prefService.getIntPref('message_count_type') ===
|
||||
FIRETRAY_MESSAGE_COUNT_TYPE_NEW) {
|
||||
firetray.Utils.prefService.setIntPref('mail_notification_type',
|
||||
FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
|
||||
log.warn("mail notification type set to newmail icon.");
|
||||
}
|
||||
},
|
||||
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);
|
||||
log.warn("mail server types corrected");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -7,8 +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,
|
||||
@ -29,6 +31,7 @@ firetray.Messaging = {
|
||||
cleaningTimer: null,
|
||||
currentMsgCount: null,
|
||||
newMsgCount: null,
|
||||
observedTopics: {},
|
||||
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
@ -37,15 +40,18 @@ firetray.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,
|
||||
that.mailSessionListener.notificationFlags);
|
||||
|
||||
if (Services.prefs.getBoolPref("mail.chat.enabled") &&
|
||||
firetray.Utils.prefService.getBoolPref("chat_icon_enable") &&
|
||||
this.existsChatAccount())
|
||||
firetray.Chat.init();
|
||||
|
||||
this.initialized = true;
|
||||
},
|
||||
|
||||
@ -53,14 +59,48 @@ firetray.Messaging = {
|
||||
if (!this.initialized) return;
|
||||
log.debug("Disabling Messaging");
|
||||
|
||||
this.cleaningTimer.cancel();
|
||||
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') {
|
||||
log.debug("found im server: "+accountServer.prettyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
observe: function(subject, topic, 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:
|
||||
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() {
|
||||
@ -92,6 +132,8 @@ firetray.Messaging = {
|
||||
}
|
||||
},
|
||||
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=715799 for TB15+
|
||||
// mozINewMailNotificationService (alternative message counting)
|
||||
/* http://mxr.mozilla.org/comm-central/source/mailnews/base/public/nsIFolderListener.idl */
|
||||
mailSessionListener: {
|
||||
notificationFlags:
|
||||
@ -236,10 +278,14 @@ firetray.Messaging = {
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
|
@ -5,25 +5,38 @@ 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.
|
||||
* use setInstallHook(), setUpgradeHook(), setReinstallHook()
|
||||
* http://mike.kaply.com/2011/02/02/running-add-on-code-at-first-run-and-upgrade/
|
||||
*/
|
||||
var VersionChange = {
|
||||
|
||||
curVersion: null,
|
||||
initialized: false,
|
||||
addonId: null,
|
||||
addonVersion: null,
|
||||
addOnPrefs: null,
|
||||
|
||||
init: function(id, version, 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));
|
||||
log.debug("version change watching enabled");
|
||||
},
|
||||
|
||||
@ -31,56 +44,74 @@ var VersionChange = {
|
||||
// detect reinstall later
|
||||
uninstallListener: {
|
||||
onUninstalling: function(addon) {
|
||||
if (addon.id !== FIRETRAY_ID) return;
|
||||
firetray.Utils.prefService.clearUserPref("installedVersion");
|
||||
if (addon.id !== this.addonId) return;
|
||||
this.addOnPrefs.clearUserPref("installedVersion");
|
||||
},
|
||||
onOperationCancelled: function(addon) {
|
||||
if (addon.id !== FIRETRAY_ID) return;
|
||||
if (addon.id !== this.addonId) return;
|
||||
let beingUninstalled = (addon.pendingOperations & AddonManager.PENDING_UNINSTALL) != 0;
|
||||
if (beingUninstalled)
|
||||
firetray.Utils.prefService.clearUserPref("installedVersion");
|
||||
this.addOnPrefs.clearUserPref("installedVersion");
|
||||
}
|
||||
},
|
||||
|
||||
onVersionChange: function(addon) {
|
||||
log.debug("VERSION: "+addon.version);
|
||||
onVersionChange: function() {
|
||||
log.debug("VERSION: "+this.addonVersion);
|
||||
|
||||
this.curVersion = addon.version;
|
||||
var firstrun = firetray.Utils.prefService.getBoolPref("firstrun");
|
||||
var firstrun = this.addOnPrefs.getBoolPref("firstrun");
|
||||
|
||||
if (firstrun) {
|
||||
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);
|
||||
log.debug("UPGRADE");
|
||||
this.upgradeHook(this.curVersion);
|
||||
this._applyHooks("upgrade");
|
||||
}
|
||||
|
||||
} catch (ex) {
|
||||
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);
|
||||
},
|
||||
|
||||
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;}
|
||||
_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;
|
||||
},
|
||||
|
||||
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 {
|
||||
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 log.debug("cb id="+cb.id+" not in category: "+cb.categories+"\n"+cb.fun);
|
||||
}
|
||||
} catch(x){log.error(x);}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,13 +1,15 @@
|
||||
/* -*- 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", "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",
|
||||
"FIRETRAY_IM_STATUS_AVAILABLE", "FIRETRAY_IM_STATUS_AWAY",
|
||||
"FIRETRAY_IM_STATUS_BUSY", "FIRETRAY_IM_STATUS_OFFLINE",
|
||||
"FIRETRAY_DELAY_BROWSER_STARTUP_MILLISECONDS",
|
||||
"FIRETRAY_DELAY_NOWAIT_MILLISECONDS",
|
||||
"FIRETRAY_DELAY_PREF_CLEANING_MILLISECONDS",
|
||||
@ -22,23 +24,30 @@ const Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://firetray/logging.jsm");
|
||||
|
||||
const FIRETRAY_VERSION = "0.4.2"; // needed for sync call of onVersionChange() :(
|
||||
const FIRETRAY_PREF_BRANCH = "extensions.firetray.";
|
||||
const FIRETRAY_ID = "{9533f794-00b4-4354-aa15-c2bbda6989f8}";
|
||||
const FIRETRAY_SPLASH_PAGE = "http://foudfou.github.com/FireTray/";
|
||||
|
||||
const FIRETRAY_APPLICATION_ICON_TYPE_THEMED = 0;
|
||||
const FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM = 1;
|
||||
const FIRETRAY_APPLICATION_ICON_TYPE_THEMED = 0;
|
||||
const FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM = 1;
|
||||
|
||||
const FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD = 0;
|
||||
const FIRETRAY_MESSAGE_COUNT_TYPE_NEW = 1;
|
||||
|
||||
const FIRETRAY_NOTIFICATION_UNREAD_MESSAGE_COUNT = 0;
|
||||
const FIRETRAY_NOTIFICATION_NEWMAIL_ICON = 1;
|
||||
const FIRETRAY_NOTIFICATION_CUSTOM_ICON = 2;
|
||||
|
||||
const FIRETRAY_IM_STATUS_AVAILABLE = "user-available";
|
||||
const FIRETRAY_IM_STATUS_AWAY = "user-away";
|
||||
const FIRETRAY_IM_STATUS_BUSY = "user-busy";
|
||||
const FIRETRAY_IM_STATUS_OFFLINE = "user-offline";
|
||||
|
||||
const FIRETRAY_DELAY_BROWSER_STARTUP_MILLISECONDS = 500;
|
||||
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;
|
||||
|
||||
const FIRETRAY_FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
|
||||
const FIRETRAY_THUNDERBIRD_ID = "{3550f703-e582-4d05-9a08-453d09bdfdc6}";
|
||||
const FIRETRAY_SONGBIRD_ID = "songbird@songbirdnest.com";
|
||||
@ -56,9 +65,30 @@ if ("undefined" == typeof(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;
|
||||
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(
|
||||
@ -191,15 +221,6 @@ firetray.Utils = {
|
||||
timer.initWithCallback({ notify: callback },
|
||||
delay, timerType);
|
||||
return timer;
|
||||
},
|
||||
|
||||
tryCloseLibs: function(libs) {
|
||||
try {
|
||||
libs.forEach(function(lib) {
|
||||
if (lib.available())
|
||||
lib.close();
|
||||
});
|
||||
} catch(x) { log.error(x); }
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -123,6 +123,8 @@ function ctypes_library(aName, aABIs, aDefines, aGlobal) {
|
||||
}
|
||||
}
|
||||
|
||||
this.name = aName;
|
||||
|
||||
this.close = function() {
|
||||
log.debug("Closing library " + aName);
|
||||
library.close();
|
||||
|
@ -237,6 +237,12 @@ function gdk_defines(lib) {
|
||||
{ "x_root": gobject.gdouble },
|
||||
{ "y_root": gobject.gdouble }
|
||||
]);
|
||||
this.GdkEventFocus = ctypes.StructType("GdkEventFocus", [
|
||||
{ "type": this.GdkEventType },
|
||||
{ "window": this.GdkWindow.ptr },
|
||||
{ "send_event": gobject.gint8 },
|
||||
{ "in": gobject.gint16 },
|
||||
]);
|
||||
|
||||
this.GdkFilterFunc_t = ctypes.FunctionType(
|
||||
ctypes.default_abi, this.GdkFilterReturn,
|
||||
|
@ -16,6 +16,7 @@ function gio_defines(lib) {
|
||||
this.GIcon = ctypes.StructType("GIcon");
|
||||
this.GThemedIcon = ctypes.StructType("GThemedIcon");
|
||||
|
||||
lib.lazy_bind("g_themed_icon_new", this.GIcon.ptr, ctypes.char.ptr);
|
||||
lib.lazy_bind("g_themed_icon_new_from_names", this.GIcon.ptr, ctypes.char.ptr.ptr, ctypes.int);
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -89,6 +89,7 @@ function gobject_defines(lib) {
|
||||
this.guint16 = ctypes.uint16_t;
|
||||
this.gint = ctypes.int;
|
||||
this.gint8 = ctypes.int8_t;
|
||||
this.gint16 = ctypes.int16_t;
|
||||
this.gchar = ctypes.char;
|
||||
this.guchar = ctypes.unsigned_char;
|
||||
this.gboolean = this.gint;
|
||||
@ -151,6 +152,8 @@ function gobject_defines(lib) {
|
||||
lib.lazy_bind("g_signal_handler_block", ctypes.void_t, this.gpointer, this.gulong);
|
||||
lib.lazy_bind("g_signal_handler_unblock", ctypes.void_t, this.gpointer, this.gulong);
|
||||
|
||||
/* NOTE: we can't easily work with g_object_get_property() because it uses
|
||||
GValue, which is an opaque struct, and thus can't be initialized by ctypes */
|
||||
}
|
||||
|
||||
new ctypes_library(GOBJECT_LIBNAME, GOBJECT_ABIS, gobject_defines, this);
|
||||
|
@ -74,6 +74,10 @@ function gtk_defines(lib) {
|
||||
this.GCallbackWindowStateEvent_t = ctypes.FunctionType(
|
||||
ctypes.default_abi, gobject.gboolean,
|
||||
[this.GtkWidget.ptr, gdk.GdkEventWindowState.ptr, gobject.gpointer]).ptr;
|
||||
this.GCallbackWidgetFocuEvent_t = ctypes.FunctionType(
|
||||
ctypes.default_abi, gobject.gboolean,
|
||||
[this.GtkWidget.ptr, gdk.GdkEventFocus.ptr, gobject.gpointer]).ptr;
|
||||
|
||||
|
||||
lib.lazy_bind("gtk_icon_theme_get_default", this.GtkIconTheme.ptr);
|
||||
lib.lazy_bind("gtk_icon_theme_get_for_screen", this.GtkIconTheme.ptr, gdk.GdkScreen.ptr);
|
||||
@ -85,6 +89,7 @@ function gtk_defines(lib) {
|
||||
lib.lazy_bind("gtk_status_icon_set_from_icon_name", ctypes.void_t, this.GtkStatusIcon.ptr, gobject.gchar.ptr);
|
||||
lib.lazy_bind("gtk_status_icon_set_from_gicon", ctypes.void_t, this.GtkStatusIcon.ptr, gio.GIcon.ptr);
|
||||
lib.lazy_bind("gtk_status_icon_set_tooltip_text", ctypes.void_t, this.GtkStatusIcon.ptr, ctypes.char.ptr);
|
||||
lib.lazy_bind("gtk_status_icon_set_blinking", ctypes.void_t, this.GtkStatusIcon.ptr, gobject.gboolean); // deprecated in gtk3
|
||||
lib.lazy_bind("gtk_status_icon_set_visible", ctypes.void_t, this.GtkStatusIcon.ptr, gobject.gboolean);
|
||||
lib.lazy_bind("gtk_menu_new", this.GtkMenu.ptr);
|
||||
lib.lazy_bind("gtk_menu_item_set_label", ctypes.void_t, this.GtkMenuItem.ptr, gobject.gchar.ptr);
|
||||
@ -104,12 +109,15 @@ function gtk_defines(lib) {
|
||||
lib.lazy_bind("gtk_status_icon_set_from_pixbuf", ctypes.void_t, this.GtkStatusIcon.ptr, gdk.GdkPixbuf.ptr);
|
||||
lib.lazy_bind("gtk_window_list_toplevels", gobject.GList.ptr);
|
||||
lib.lazy_bind("gtk_window_get_title", gobject.gchar.ptr, this.GtkWindow.ptr);
|
||||
|
||||
lib.lazy_bind("gtk_window_is_active", gobject.gboolean, this.GtkWindow.ptr);
|
||||
lib.lazy_bind("gtk_window_has_toplevel_focus", gobject.gboolean, this.GtkWindow.ptr);
|
||||
lib.lazy_bind("gtk_widget_get_has_window", gobject.gboolean, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_get_window", gdk.GdkWindow.ptr, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_get_parent_window", gdk.GdkWindow.ptr, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_window_set_decorated", ctypes.void_t, this.GtkWindow.ptr, gobject.gboolean);
|
||||
|
||||
lib.lazy_bind("gtk_widget_is_focus", gobject.gboolean, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_has_focus", gobject.gboolean, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_hide_on_delete", gobject.gboolean, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_hide", ctypes.void_t, this.GtkWidget.ptr);
|
||||
lib.lazy_bind("gtk_widget_show", ctypes.void_t, this.GtkWidget.ptr);
|
||||
|
117
src/modules/linux/FiretrayChatStatusIcon.jsm
Normal file
117
src/modules/linux/FiretrayChatStatusIcon.jsm
Normal file
@ -0,0 +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))
|
||||
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)
|
||||
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) {
|
||||
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) {
|
||||
log.debug("onFocusIn");
|
||||
// let gdkEventFocus = ctypes.cast(event, gdk.GdkEventFocus.ptr);
|
||||
// let gdkWin = gdkEventFocus.contents.window;
|
||||
// let xid = firetray.Window.getXIDFromGdkWindow(gdkWin);
|
||||
// log.debug("xid="+xid+" in="+gdkEventFocus.contents["in"]);
|
||||
firetray.Chat.stopIconBlinkingMaybe();
|
||||
}
|
||||
|
||||
// FIXME: TODO: onclick/activate -> chatHandler.showCurrentConversation()
|
||||
|
||||
}; // firetray.ChatStatusIcon
|
49
src/modules/linux/FiretrayGtkIcons.jsm
Normal file
49
src/modules/linux/FiretrayGtkIcons.jsm
Normal file
@ -0,0 +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))
|
||||
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) {
|
||||
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");
|
||||
log.debug(this.GTK_THEME_ICON_PATH);
|
||||
let gtkIconTheme = gtk.gtk_icon_theme_get_default();
|
||||
log.debug("gtkIconTheme="+gtkIconTheme);
|
||||
gtk.gtk_icon_theme_append_search_path(gtkIconTheme, this.GTK_THEME_ICON_PATH);
|
||||
}
|
||||
|
||||
};
|
@ -12,6 +12,7 @@ Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
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");
|
||||
|
||||
@ -62,7 +63,7 @@ firetray.PopupMenu = {
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
firetray.Utils.tryCloseLibs([gobject, gtk]);
|
||||
log.debug("Disabling PopupMenu");
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
|
@ -17,6 +17,7 @@ Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
|
||||
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");
|
||||
|
||||
@ -25,7 +26,7 @@ if ("undefined" == typeof(firetray.Handler))
|
||||
|
||||
|
||||
firetray.StatusIcon = {
|
||||
GTK_THEME_ICON_PATH: null,
|
||||
FILENAME_BLANK: null,
|
||||
|
||||
initialized: false,
|
||||
callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
|
||||
@ -38,26 +39,16 @@ firetray.StatusIcon = {
|
||||
defaultNewMailIconName: null,
|
||||
|
||||
init: function() {
|
||||
this.FILENAME_BLANK = firetray.Utils.chromeToPath(
|
||||
"chrome://firetray/skin/blank-icon.png");
|
||||
|
||||
Cu.import("resource://firetray/linux/FiretrayGtkIcons.jsm");
|
||||
firetray.GtkIcons.init();
|
||||
this.defineIconNames();
|
||||
this.loadThemedIcons();
|
||||
|
||||
try {
|
||||
this.GTK_THEME_ICON_PATH = firetray.Utils.chromeToPath("chrome://firetray/skin/linux/icons");
|
||||
log.debug(this.GTK_THEME_ICON_PATH);
|
||||
let gtkIconTheme = gtk.gtk_icon_theme_get_default();
|
||||
log.debug("gtkIconTheme="+gtkIconTheme);
|
||||
gtk.gtk_icon_theme_append_search_path(gtkIconTheme, this.GTK_THEME_ICON_PATH);
|
||||
|
||||
this.loadThemedIcons();
|
||||
|
||||
this.trayIcon = gtk.gtk_status_icon_new();
|
||||
|
||||
} catch (x) {
|
||||
log.error(x);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.trayIcon = gtk.gtk_status_icon_new();
|
||||
firetray.Handler.setIconImageDefault();
|
||||
|
||||
firetray.Handler.setIconTooltipDefault();
|
||||
|
||||
Cu.import("resource://firetray/linux/FiretrayPopupMenu.jsm");
|
||||
@ -71,8 +62,10 @@ firetray.StatusIcon = {
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
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;
|
||||
},
|
||||
|
||||
@ -245,7 +238,8 @@ firetray.Handler.setIconText = function(text, color) { // FIXME: function too lo
|
||||
|
||||
try {
|
||||
// build background from image
|
||||
let specialIcon = gdk.gdk_pixbuf_new_from_file(this.FILENAME_BLANK, null); // GError **error);
|
||||
let specialIcon = gdk.gdk_pixbuf_new_from_file(
|
||||
firetray.StatusIcon.FILENAME_BLANK, null); // GError **error);
|
||||
let dest = gdk.gdk_pixbuf_copy(specialIcon);
|
||||
let w = gdk.gdk_pixbuf_get_width(specialIcon);
|
||||
let h = gdk.gdk_pixbuf_get_height(specialIcon);
|
||||
|
@ -23,6 +23,7 @@ Cu.import("resource://firetray/ctypes/linux/gtk.jsm");
|
||||
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");
|
||||
|
||||
@ -63,7 +64,6 @@ firetray.Window = {
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
firetray.Utils.tryCloseLibs([gobject, gdk, gtk, libc, x11, glib]);
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
@ -588,6 +588,11 @@ firetray.Handler.registerWindow = function(win) {
|
||||
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);
|
||||
log.error(x);
|
||||
@ -649,6 +654,29 @@ firetray.Handler.activateLastWindow = function(gtkStatusIcon, gdkEvent, userData
|
||||
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);
|
||||
|
||||
log.debug("ACTIVE_WINDOW propsFound, nitems="+propsFound+", "+nitems);
|
||||
if (!propsFound) return null;
|
||||
|
||||
let activeWin = null;
|
||||
if (firetray.js.strEquals(nitems.value, 0))
|
||||
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);
|
||||
|
||||
log.debug("ACTIVE_WINDOW="+activeWin);
|
||||
return activeWin;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init X11 Display and handled XAtoms.
|
||||
|
Loading…
Reference in New Issue
Block a user