Merge branch 'winnt'
@ -111,7 +111,9 @@ modules_sources := $(wildcard $(modules_dir)/*.js) \
|
|||||||
$(wildcard $(modules_dir)/*.jsm) \
|
$(wildcard $(modules_dir)/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/ctypes/*.jsm) \
|
$(wildcard $(modules_dir)/ctypes/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/ctypes/linux/*.jsm) \
|
$(wildcard $(modules_dir)/ctypes/linux/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/linux/*.jsm)
|
$(wildcard $(modules_dir)/ctypes/winnt/*.jsm) \
|
||||||
|
$(wildcard $(modules_dir)/linux/*.jsm) \
|
||||||
|
$(wildcard $(modules_dir)/winnt/*.jsm)
|
||||||
|
|
||||||
# The components (JSM) dir.
|
# The components (JSM) dir.
|
||||||
components_dir := components
|
components_dir := components
|
||||||
@ -142,7 +144,7 @@ $(xpi_built): check_version check_loglevel $(build_dir) $(build_includes)
|
|||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(xpi_built)
|
build: $(xpi_built)
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished successfully."
|
@echo "Build finished successfully in $(build_dir)."
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
# This cleans all temporary files and directories created by 'make'.
|
# This cleans all temporary files and directories created by 'make'.
|
||||||
|
@ -15,14 +15,15 @@ const TREELEVEL_EXCLUDED_ACCOUNTS = 1;
|
|||||||
|
|
||||||
const PREF_DEFAULT_PANE = "pref-pane-windows";
|
const PREF_DEFAULT_PANE = "pref-pane-windows";
|
||||||
|
|
||||||
|
|
||||||
let log = firetray.Logging.getLogger("firetray.UIOptions");
|
let log = firetray.Logging.getLogger("firetray.UIOptions");
|
||||||
|
|
||||||
var firetrayUIOptions = {
|
var firetrayUIOptions = {
|
||||||
strings: null,
|
strings: null,
|
||||||
prefwindow: null,
|
prefwindow: null,
|
||||||
|
listeners: {},
|
||||||
|
|
||||||
onLoad: function(e) {
|
onLoad: function(e) {
|
||||||
|
log.debug("FULL FEATURED="+firetray.Handler.support['full_feat']);
|
||||||
this.strings = document.getElementById("firetray-options-strings");
|
this.strings = document.getElementById("firetray-options-strings");
|
||||||
this.prefwindow = document.getElementById("firetray-preferences");
|
this.prefwindow = document.getElementById("firetray-preferences");
|
||||||
if (!this.prefwindow)
|
if (!this.prefwindow)
|
||||||
@ -36,40 +37,54 @@ var firetrayUIOptions = {
|
|||||||
this.hidePrefPane("pref-pane-mail");
|
this.hidePrefPane("pref-pane-mail");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firetray.Handler.isChatProvided()) {
|
if (firetray.Handler.isChatProvided() &&
|
||||||
Cu.import("resource://firetray/FiretrayChat.jsm");
|
FIRETRAY_CHAT_SUPPORTED_OS.indexOf(firetray.Handler.runtimeOS) > -1) {
|
||||||
|
Cu.import("resource://firetray/"+firetray.Handler.runtimeOS+"/FiretrayChat.jsm");
|
||||||
this.initChatControls();
|
this.initChatControls();
|
||||||
} else
|
} else {
|
||||||
this.hidePrefPane("pref-pane-chat");
|
this.hidePrefPane("pref-pane-chat");
|
||||||
|
};
|
||||||
|
|
||||||
this.updateWindowAndIconOptions();
|
this.updateWindowAndIconOptions();
|
||||||
this.updateScrollOptions();
|
this.updateScrollOptions();
|
||||||
this.initAppIconType();
|
this.initAppIconType();
|
||||||
this.initAppIconNames();
|
if (firetray.Handler.support['full_feat']) {
|
||||||
if (firetray.Handler.inMailApp)
|
this.initAppIconNames();
|
||||||
this.initNewMailIconNames();
|
if (firetray.Handler.inMailApp)
|
||||||
|
this.initNewMailIconNames();
|
||||||
|
} else {
|
||||||
|
this.hideUnsupportedOptions();
|
||||||
|
};
|
||||||
|
|
||||||
window.sizeToContent();
|
window.sizeToContent();
|
||||||
},
|
},
|
||||||
|
|
||||||
onQuit: function(e) {
|
onQuit: function(e) {
|
||||||
// cleaning: removeEventListener on cells
|
if (firetray.Handler.inMailApp) {
|
||||||
// NOTE: not sure this is necessary on window close
|
this.removeListeners();
|
||||||
let tree = document.getElementById("ui_tree_mail_accounts");
|
this.removeMailAccountsObserver();
|
||||||
let that = this;
|
}
|
||||||
for (let i=0, len=tree.view.rowCount; i<len ; ++i) {
|
},
|
||||||
let cells = tree.view.getItemAtIndex(i).getElementsByTagName("treecell");
|
|
||||||
if (tree.view.getLevel(i) === TREELEVEL_SERVER_TYPES) {
|
hideUnsupportedOptions: function() { // full_feat
|
||||||
// account_or_server_type_excluded, account_or_server_type_order
|
// windows prefs
|
||||||
[cells[1], cells[2]].map(
|
['ui_hides_last_only', 'ui_show_activates', 'ui_remember_desktop']
|
||||||
function(c) {
|
.forEach(function(id){
|
||||||
c.removeEventListener(
|
document.getElementById(id).hidden = true;
|
||||||
'DOMAttrModified', that._userChangeValueTreeServerTypes, true);
|
});
|
||||||
});
|
|
||||||
} else if (tree.view.getLevel(i) === TREELEVEL_EXCLUDED_ACCOUNTS) {
|
// icon prefs
|
||||||
cells[1].removeEventListener(
|
['app_icon_default', 'ui_show_icon_on_hide', 'ui_scroll_hides',
|
||||||
'DOMAttrModified', that._userChangeValueTree, true);
|
'ui_radiogroup_scroll'].forEach(function(id){
|
||||||
}
|
document.getElementById(id).hidden = true;
|
||||||
|
});
|
||||||
|
document.getElementById("ui_scroll_hides").setAttribute("oncommand", void(0));
|
||||||
|
|
||||||
|
// mail prefs
|
||||||
|
document.getElementById("newmail_icon_names").hidden = true;
|
||||||
|
for (let i=1; i<4; ++i) {
|
||||||
|
document.getElementById("radio_mail_notification_newmail_icon_name"+i).
|
||||||
|
setAttribute("observes", void(0));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -80,8 +95,10 @@ var firetrayUIOptions = {
|
|||||||
radio.hidden = true;
|
radio.hidden = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
hideElement: function(targetNode, hiddenval) {
|
hideChildren: function(group, hiddenval) {
|
||||||
targetNode.hidden = hiddenval;
|
let children = group.childNodes;
|
||||||
|
for (let i=0, len=children.length; i<len ; ++i)
|
||||||
|
children[i].hidden = hiddenval;
|
||||||
},
|
},
|
||||||
|
|
||||||
disableChildren: function(group, disableval) {
|
disableChildren: function(group, disableval) {
|
||||||
@ -119,8 +136,9 @@ var firetrayUIOptions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateScrollOptions: function() {
|
updateScrollOptions: function() {
|
||||||
let scroll_hides = document.getElementById("ui_scroll_hides").checked;
|
let ui_scroll_hides = document.getElementById("ui_scroll_hides");
|
||||||
this.disableChildren(document.getElementById("ui_radiogroup_scroll"), !scroll_hides);
|
this.disableChildren(document.getElementById("ui_radiogroup_scroll"),
|
||||||
|
!ui_scroll_hides.checked);
|
||||||
},
|
},
|
||||||
|
|
||||||
initAppIconType: function() {
|
initAppIconType: function() {
|
||||||
@ -174,26 +192,28 @@ var firetrayUIOptions = {
|
|||||||
if (val) iconNames.push(val);
|
if (val) iconNames.push(val);
|
||||||
}
|
}
|
||||||
log.debug("iconNames="+iconNames);
|
log.debug("iconNames="+iconNames);
|
||||||
firetray.Utils.setArrayPref(prefIconNames, iconNames);
|
firetray.Utils.setArrayPref(prefIconNames, iconNames); // FIXME: should be a <preference>
|
||||||
},
|
},
|
||||||
|
|
||||||
disableIconTypeMaybe: function(appIconType) {
|
disableIconTypeMaybe: function(appIconType) {
|
||||||
|
if (firetray.Handler.support['full_feat']) {
|
||||||
|
let appIconDefaultGroup = document.getElementById("app_icon_default");
|
||||||
|
this.disableNChildren(appIconDefaultGroup, 2,
|
||||||
|
(appIconType !== FIRETRAY_APPLICATION_ICON_TYPE_THEMED));
|
||||||
|
}
|
||||||
|
|
||||||
let appIconCustomGroup = document.getElementById("app_icon_custom");
|
let appIconCustomGroup = document.getElementById("app_icon_custom");
|
||||||
this.disableChildren(appIconCustomGroup,
|
this.disableChildren(appIconCustomGroup,
|
||||||
(appIconType !== FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM));
|
(appIconType !== FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM));
|
||||||
|
|
||||||
let appIconDefaultGroup = document.getElementById("app_icon_default");
|
|
||||||
this.disableNChildren(appIconDefaultGroup, 2,
|
|
||||||
(appIconType !== FIRETRAY_APPLICATION_ICON_TYPE_THEMED));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initMailControls: function() {
|
initMailControls: function() {
|
||||||
this.populateExcludedFoldersList();
|
this.populateExcludedFoldersList();
|
||||||
this.populateTreeAccountsOrServerTypes();
|
this.populateTreeAccountsOrServerTypes();
|
||||||
|
this.addMailAccountsObserver();
|
||||||
|
|
||||||
this.initMessageCountSettings();
|
this.initMessageCountSettings();
|
||||||
this.initNotificationSettings();
|
this.initNotificationSettings();
|
||||||
this.initMailTrigger();
|
|
||||||
|
|
||||||
this.toggleNotifications(firetray.Utils.prefService.getBoolPref("mail_notification_enabled"));
|
this.toggleNotifications(firetray.Utils.prefService.getBoolPref("mail_notification_enabled"));
|
||||||
},
|
},
|
||||||
@ -208,16 +228,20 @@ var firetrayUIOptions = {
|
|||||||
FIRETRAY_NOTIFICATION_MESSAGE_COUNT;
|
FIRETRAY_NOTIFICATION_MESSAGE_COUNT;
|
||||||
document.getElementById("ui_radio_mail_notification_newmail_icon").value =
|
document.getElementById("ui_radio_mail_notification_newmail_icon").value =
|
||||||
FIRETRAY_NOTIFICATION_NEWMAIL_ICON;
|
FIRETRAY_NOTIFICATION_NEWMAIL_ICON;
|
||||||
document.getElementById("ui_radio_mail_notification_custom_mail_icon").value =
|
document.getElementById("ui_radio_mail_notification_mail_icon_custom").value =
|
||||||
FIRETRAY_NOTIFICATION_CUSTOM_ICON;
|
FIRETRAY_NOTIFICATION_CUSTOM_ICON;
|
||||||
|
|
||||||
document.getElementById("ui_mail_notification_enabled").checked =
|
document.getElementById("ui_mail_notification_enabled").checked =
|
||||||
(firetray.Utils.prefService.getBoolPref("mail_notification_enabled"));
|
(firetray.Utils.prefService.getBoolPref("mail_notification_enabled"));
|
||||||
|
|
||||||
let radioMailNotify = document.getElementById("ui_radiogroup_mail_notification");
|
let mailNotifyRadio = document.getElementById("ui_radiogroup_mail_notification");
|
||||||
let prefMailNotificationType = firetray.Utils.prefService.getIntPref("mail_notification_type");
|
let prefMailNotificationType = firetray.Utils.prefService.getIntPref("mail_notification_type");
|
||||||
radioMailNotify.selectedIndex = this.radioGetIndexByValue(radioMailNotify, prefMailNotificationType);
|
mailNotifyRadio.selectedIndex = this.radioGetIndexByValue(mailNotifyRadio, prefMailNotificationType);
|
||||||
// this.disableNotificationMaybe(prefMailNotificationType); // done in toggleNotifications()
|
// this.disableNotificationMaybe(prefMailNotificationType); // done in toggleNotifications()
|
||||||
|
/* We need to ensure assigning selectedIndex in disableMessageCountMaybe()
|
||||||
|
does change the corresponding preference. */
|
||||||
|
let listener = {evt:'select', fn:firetrayUIOptions.userChangedValue, cap:true};
|
||||||
|
this.addListener(mailNotifyRadio, listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
initMessageCountSettings: function() {
|
initMessageCountSettings: function() {
|
||||||
@ -243,30 +267,25 @@ var firetrayUIOptions = {
|
|||||||
blinkStyle.selectedIndex = this.radioGetIndexByValue(blinkStyle, prefBlinkStyle);
|
blinkStyle.selectedIndex = this.radioGetIndexByValue(blinkStyle, prefBlinkStyle);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
userChangedValue: function(e) {
|
||||||
|
document.getElementById('pref-pane-mail').userChangedValue(e.originalTarget);
|
||||||
|
},
|
||||||
|
|
||||||
radioGetIndexByValue: function(radio, value) {
|
radioGetIndexByValue: function(radio, value) {
|
||||||
for (let i=0, len=radio.itemCount; i<len; ++i)
|
for (let i=0, len=radio.itemCount; i<len; ++i)
|
||||||
if (+radio.getItemAtIndex(i).value == value) return i;
|
if (+radio.getItemAtIndex(i).value == value) return i;
|
||||||
return -1;
|
return -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
initMailTrigger: function() {
|
saveMailChangeTrigger: function(uiElt) {
|
||||||
document.getElementById("ui_mail_change_trigger").value =
|
return uiElt.value.trim();
|
||||||
firetray.Utils.prefService.getCharPref("mail_change_trigger");
|
|
||||||
},
|
|
||||||
|
|
||||||
updateMailTrigger: function() {
|
|
||||||
let mailTrigger = document.getElementById("ui_mail_change_trigger").value.trim();
|
|
||||||
firetray.Utils.prefService.setCharPref("mail_change_trigger", mailTrigger);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateNotificationSettings: function() {
|
updateNotificationSettings: function() {
|
||||||
log.debug("updateNotificationSettings");
|
log.debug("updateNotificationSettings");
|
||||||
let radioMailNotify = document.getElementById("ui_radiogroup_mail_notification");
|
let mailNotifyRadio = document.getElementById("ui_radiogroup_mail_notification");
|
||||||
let mailNotificationType = +radioMailNotify.getItemAtIndex(radioMailNotify.selectedIndex).value;
|
let mailNotificationType = +mailNotifyRadio.getItemAtIndex(mailNotifyRadio.selectedIndex).value;
|
||||||
firetray.Utils.prefService.setIntPref("mail_notification_type", mailNotificationType);
|
|
||||||
this.disableNotificationMaybe(mailNotificationType);
|
this.disableNotificationMaybe(mailNotificationType);
|
||||||
|
|
||||||
firetray.Messaging.updateIcon();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateMessageCountSettings: function() {
|
updateMessageCountSettings: function() {
|
||||||
@ -275,12 +294,6 @@ var firetrayUIOptions = {
|
|||||||
this.disableMessageCountMaybe(messageCountType);
|
this.disableMessageCountMaybe(messageCountType);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateChatBlinkSettings: function() {
|
|
||||||
let radioBlinkStyle = document.getElementById("ui_chat_icon_blink_style");
|
|
||||||
let blinkStyle = +radioBlinkStyle.getItemAtIndex(radioBlinkStyle.selectedIndex).value;
|
|
||||||
firetray.Utils.prefService.setIntPref("chat_icon_blink_style", blinkStyle);
|
|
||||||
},
|
|
||||||
|
|
||||||
disableNotificationMaybe: function(notificationSetting) {
|
disableNotificationMaybe: function(notificationSetting) {
|
||||||
log.debug("disableNotificationMaybe: "+notificationSetting);
|
log.debug("disableNotificationMaybe: "+notificationSetting);
|
||||||
|
|
||||||
@ -288,11 +301,13 @@ var firetrayUIOptions = {
|
|||||||
this.disableChildren(iconTextColor,
|
this.disableChildren(iconTextColor,
|
||||||
(notificationSetting !== FIRETRAY_NOTIFICATION_MESSAGE_COUNT));
|
(notificationSetting !== FIRETRAY_NOTIFICATION_MESSAGE_COUNT));
|
||||||
|
|
||||||
let newMailIconNames = document.getElementById("newmail_icon_names");
|
if (firetray.Handler.support['full_feat']) {
|
||||||
this.disableNChildren(newMailIconNames, 2,
|
let newMailIconNames = document.getElementById("newmail_icon_names");
|
||||||
(notificationSetting !== FIRETRAY_NOTIFICATION_NEWMAIL_ICON));
|
this.disableNChildren(newMailIconNames, 2,
|
||||||
|
(notificationSetting !== FIRETRAY_NOTIFICATION_NEWMAIL_ICON));
|
||||||
|
}
|
||||||
|
|
||||||
let customIconGroup = document.getElementById("custom_mail_icon");
|
let customIconGroup = document.getElementById("mail_icon_custom");
|
||||||
this.disableChildren(customIconGroup,
|
this.disableChildren(customIconGroup,
|
||||||
(notificationSetting !== FIRETRAY_NOTIFICATION_CUSTOM_ICON));
|
(notificationSetting !== FIRETRAY_NOTIFICATION_CUSTOM_ICON));
|
||||||
},
|
},
|
||||||
@ -304,13 +319,14 @@ var firetrayUIOptions = {
|
|||||||
let notificationUnreadCount = document.getElementById("ui_mail_notification_unread_count");
|
let notificationUnreadCount = document.getElementById("ui_mail_notification_unread_count");
|
||||||
this.disableElementsRecursive(notificationUnreadCount, msgCountTypeIsNewMessages);
|
this.disableElementsRecursive(notificationUnreadCount, msgCountTypeIsNewMessages);
|
||||||
|
|
||||||
let radioMailNotify = document.getElementById("ui_radiogroup_mail_notification");
|
let mailNotifyRadio = document.getElementById("ui_radiogroup_mail_notification");
|
||||||
let mailNotificationType = +radioMailNotify.getItemAtIndex(radioMailNotify.selectedIndex).value;
|
let mailNotificationType = +mailNotifyRadio.getItemAtIndex(mailNotifyRadio.selectedIndex).value;
|
||||||
if (msgCountTypeIsNewMessages && (mailNotificationType === FIRETRAY_NOTIFICATION_MESSAGE_COUNT)) {
|
if (msgCountTypeIsNewMessages && (mailNotificationType === FIRETRAY_NOTIFICATION_MESSAGE_COUNT)) {
|
||||||
radioMailNotify.selectedIndex = this.radioGetIndexByValue(radioMailNotify, FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
|
mailNotifyRadio.selectedIndex = this.radioGetIndexByValue(mailNotifyRadio, FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
|
||||||
let newMailIconNames = document.getElementById("newmail_icon_names");
|
if (firetray.Handler.support['full_feat']) {
|
||||||
this.disableNChildren(newMailIconNames, 2, false);
|
let newMailIconNames = document.getElementById("newmail_icon_names");
|
||||||
firetray.Utils.prefService.setIntPref("mail_notification_type", FIRETRAY_NOTIFICATION_NEWMAIL_ICON);
|
this.disableNChildren(newMailIconNames, 2, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -357,7 +373,7 @@ var firetrayUIOptions = {
|
|||||||
|
|
||||||
chooseMailIconFile: function() {
|
chooseMailIconFile: function() {
|
||||||
let updateIcon = firetray.Messaging.updateIcon.bind(firetray.Messaging);
|
let updateIcon = firetray.Messaging.updateIcon.bind(firetray.Messaging);
|
||||||
this._chooseIconFile("custom_mail_icon_filename", updateIcon);
|
this._chooseIconFile("mail_icon_custom_filename", updateIcon);
|
||||||
},
|
},
|
||||||
|
|
||||||
_chooseIconFile: function(elementId, callback) {
|
_chooseIconFile: function(elementId, callback) {
|
||||||
@ -377,7 +393,10 @@ var firetrayUIOptions = {
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
filePicker.init(window, "Select Icon", nsIFilePicker.modeOpen); // FIXME: i18n
|
filePicker.init(window, "Select Icon", nsIFilePicker.modeOpen); // FIXME: i18n
|
||||||
filePicker.appendFilters(nsIFilePicker.filterImages);
|
if (firetray.Handler.runtimeOS === "winnt")
|
||||||
|
filePicker.appendFilter("Icon", "*.bmp; *.ico"); // TODO: support more formats ?
|
||||||
|
else
|
||||||
|
filePicker.appendFilters(nsIFilePicker.filterImages);
|
||||||
filePicker.open(fpCallback);
|
filePicker.open(fpCallback);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -389,44 +408,52 @@ var firetrayUIOptions = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: folder exceptions for unread messages count are *stored* in
|
* NOTE: we store folder type *exceptions* for unread messages count. This is
|
||||||
* preferences as excluded, but *shown* as "not included"
|
* easier than storing all possible included folder types. The drawback is
|
||||||
|
* that we must inverse the selection in the UI: we show exceptions as "not
|
||||||
|
* included".
|
||||||
*/
|
*/
|
||||||
populateExcludedFoldersList: function() {
|
populateExcludedFoldersList: function() {
|
||||||
let excludedFoldersList = document.getElementById('excluded_folders_list');
|
let excludedFoldersList = document.getElementById('excluded_folders_list');
|
||||||
|
|
||||||
let prefExcludedFoldersFlags = firetray.Utils.prefService
|
let prefExcludedFoldersFlags = firetray.Utils.prefService
|
||||||
.getIntPref("excluded_folders_flags");
|
.getIntPref("excluded_folders_flags");
|
||||||
|
log.debug("prefExcludedFoldersFlags="+prefExcludedFoldersFlags.toString(16));
|
||||||
for (let folderType in FLDRS_UNINTERESTING) {
|
for (let folderType in FLDRS_UNINTERESTING) {
|
||||||
let localizedFolderType = this.strings.getString(folderType);
|
let localizedFolderType = this.strings.getString(folderType);
|
||||||
let item = excludedFoldersList.appendItem(localizedFolderType, folderType);
|
let folderTypeVal = FLDRS_UNINTERESTING[folderType];
|
||||||
|
let item = excludedFoldersList.appendItem(localizedFolderType, folderTypeVal);
|
||||||
item.setAttribute("observes", "broadcaster-notification-disabled");
|
item.setAttribute("observes", "broadcaster-notification-disabled");
|
||||||
log.debug("folder: "+folderType);
|
let folderTypeSet = (folderTypeVal & prefExcludedFoldersFlags);
|
||||||
if (!(FLDRS_UNINTERESTING[folderType] & prefExcludedFoldersFlags)) {
|
log.debug("folder: "+folderType+" folderTypeVal="+folderTypeVal+" folderTypeSet="+folderTypeSet);
|
||||||
|
if (!folderTypeSet) {
|
||||||
excludedFoldersList.ensureElementIsVisible(item); // bug 326445
|
excludedFoldersList.ensureElementIsVisible(item); // bug 326445
|
||||||
excludedFoldersList.addItemToSelection(item); // doesn't trigger onselect
|
excludedFoldersList.addItemToSelection(item); // does trigger onselect...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...so we add onselect handler after the listbox is populated. 'select'
|
||||||
|
// also fired on unselect.
|
||||||
|
let listener = {evt:'select', fn:firetrayUIOptions.userChangedValue, cap:true};
|
||||||
|
this.addListener(excludedFoldersList, listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateExcludedFoldersPref: function() {
|
loadExcludedFoldersFlags: function(uiElt) {
|
||||||
let excludedFoldersList = document.getElementById('excluded_folders_list');
|
// we can't do much here since onLoad() not yet applied at onsyncfrompreference...
|
||||||
|
},
|
||||||
|
|
||||||
log.debug("LAST SELECTED: "+excludedFoldersList.currentItem.label);
|
saveExcludedFoldersFlags: function(uiElt) {
|
||||||
let excludedFoldersFlags = null;
|
log.debug("LAST SELECTED: "+uiElt.currentItem.label);
|
||||||
for (let i = 0, len=excludedFoldersList.itemCount; i<len; ++i) {
|
let excludedFoldersFlags = 0;
|
||||||
let folder = excludedFoldersList.getItemAtIndex(i);
|
for (let i = 0, len=uiElt.itemCount; i<len; ++i) {
|
||||||
|
let folder = uiElt.getItemAtIndex(i);
|
||||||
if (folder.selected)
|
if (folder.selected)
|
||||||
excludedFoldersFlags &= ~FLDRS_UNINTERESTING[folder.value];
|
excludedFoldersFlags &= ~folder.value; // clear
|
||||||
else
|
else
|
||||||
excludedFoldersFlags |= FLDRS_UNINTERESTING[folder.value];
|
excludedFoldersFlags |= folder.value; // set
|
||||||
}
|
}
|
||||||
log.debug("excluded folders flags: "+excludedFoldersFlags);
|
log.debug("excluded folders flags: "+excludedFoldersFlags.toString(16));
|
||||||
|
return excludedFoldersFlags;
|
||||||
firetray.Utils.prefService.setIntPref("excluded_folders_flags",
|
|
||||||
excludedFoldersFlags);
|
|
||||||
|
|
||||||
firetray.Messaging.updateMsgCountWithCb();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -442,15 +469,11 @@ var firetrayUIOptions = {
|
|||||||
if (disable === true) {
|
if (disable === true) {
|
||||||
cells[i].setAttribute('properties', "disabled");
|
cells[i].setAttribute('properties', "disabled");
|
||||||
if (i === TREEROW_ACCOUNT_OR_SERVER_TYPE_EXCLUDED) {
|
if (i === TREEROW_ACCOUNT_OR_SERVER_TYPE_EXCLUDED) {
|
||||||
cells[i].removeEventListener(
|
|
||||||
'DOMAttrModified', that._userChangeValueTree, true);
|
|
||||||
cells[i].setAttribute('editable', "false");
|
cells[i].setAttribute('editable', "false");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cells[i].removeAttribute('properties');
|
cells[i].removeAttribute('properties');
|
||||||
if (i === TREEROW_ACCOUNT_OR_SERVER_TYPE_EXCLUDED) {
|
if (i === TREEROW_ACCOUNT_OR_SERVER_TYPE_EXCLUDED) {
|
||||||
cells[i].addEventListener(
|
|
||||||
'DOMAttrModified', that._userChangeValueTree, true);
|
|
||||||
cells[i].setAttribute('editable', "true");
|
cells[i].setAttribute('editable', "true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,39 +483,6 @@ var firetrayUIOptions = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* needed for triggering actual preference change and saving
|
|
||||||
*/
|
|
||||||
_userChangeValueTree: function(event) {
|
|
||||||
if (event.attrName == "label") log.debug("label changed!");
|
|
||||||
if (event.attrName == "value") log.debug("value changed!");
|
|
||||||
document.getElementById("pref-pane-mail")
|
|
||||||
.userChangedValue(document.getElementById("ui_tree_mail_accounts"));
|
|
||||||
|
|
||||||
firetray.Messaging.updateMsgCountWithCb();
|
|
||||||
},
|
|
||||||
|
|
||||||
_userChangeValueTreeServerTypes: function(event) {
|
|
||||||
if (event.attrName === "value") { // checkbox
|
|
||||||
let checkboxCell = event.originalTarget;
|
|
||||||
let tree = document.getElementById("ui_tree_mail_accounts");
|
|
||||||
|
|
||||||
let subRows = firetray.Utils.XPath(
|
|
||||||
checkboxCell,
|
|
||||||
'ancestor::xul:treeitem[1]/child::xul:treechildren/xul:treeitem/xul:treerow');
|
|
||||||
log.debug("subRows="+subRows);
|
|
||||||
for (let i=0, len=subRows.length; i<len; ++i) {
|
|
||||||
firetrayUIOptions._disableTreeRow(
|
|
||||||
subRows[i], (checkboxCell.getAttribute("value") === "false"));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (event.attrName == "label") { // text
|
|
||||||
log.warn("NOT IMPLEMENTED YET: move row to new rank"); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
this._userChangeValueTree(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: account exceptions for unread messages count are *stored* in
|
* NOTE: account exceptions for unread messages count are *stored* in
|
||||||
* preferences as excluded, but *shown* as "not included"
|
* preferences as excluded, but *shown* as "not included"
|
||||||
@ -541,15 +531,11 @@ var firetrayUIOptions = {
|
|||||||
// account_or_server_type_excluded => checkbox
|
// account_or_server_type_excluded => checkbox
|
||||||
let cellExcluded = document.createElement('treecell');
|
let cellExcluded = document.createElement('treecell');
|
||||||
cellExcluded.setAttribute('value',!serverTypes[serverTypeName].excluded);
|
cellExcluded.setAttribute('value',!serverTypes[serverTypeName].excluded);
|
||||||
cellExcluded.addEventListener( // CAUTION: removeEventListener in onQuit()
|
|
||||||
'DOMAttrModified', that._userChangeValueTreeServerTypes, true);
|
|
||||||
typeRow.appendChild(cellExcluded);
|
typeRow.appendChild(cellExcluded);
|
||||||
|
|
||||||
// account_or_server_type_order
|
// account_or_server_type_order
|
||||||
let cellOrder = document.createElement('treecell');
|
let cellOrder = document.createElement('treecell');
|
||||||
cellOrder.setAttribute('label',serverTypes[serverTypeName].order);
|
cellOrder.setAttribute('label',serverTypes[serverTypeName].order);
|
||||||
cellOrder.addEventListener( // CAUTION: removeEventListener in onQuit()
|
|
||||||
'DOMAttrModified', that._userChangeValueTreeServerTypes, true);
|
|
||||||
typeRow.appendChild(cellOrder);
|
typeRow.appendChild(cellOrder);
|
||||||
|
|
||||||
target.appendChild(typeItem);
|
target.appendChild(typeItem);
|
||||||
@ -585,9 +571,6 @@ var firetrayUIOptions = {
|
|||||||
if (rowDisabled === true) {
|
if (rowDisabled === true) {
|
||||||
accountCell.setAttribute('properties', "disabled");
|
accountCell.setAttribute('properties', "disabled");
|
||||||
accountCell.setAttribute('editable', "false");
|
accountCell.setAttribute('editable', "false");
|
||||||
} else {
|
|
||||||
accountCell.addEventListener( // CAUTION: removeEventListener in onQuit()
|
|
||||||
'DOMAttrModified', that._userChangeValueTree, true);
|
|
||||||
}
|
}
|
||||||
accountRow.appendChild(accountCell);
|
accountRow.appendChild(accountCell);
|
||||||
|
|
||||||
@ -649,14 +632,72 @@ var firetrayUIOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tree = document.getElementById("ui_tree_mail_accounts");
|
let tree = document.getElementById("ui_tree_mail_accounts");
|
||||||
tree.addEventListener("keypress", that.onKeyPressTreeAccountsOrServerTypes, true);
|
let listener = {evt:'keypress', fn:firetrayUIOptions.onKeyPressTreeAccountsOrServerTypes, cap:true};
|
||||||
|
this.addListener(tree, listener);
|
||||||
|
},
|
||||||
|
|
||||||
|
addListener: function(elt, listenerData) {
|
||||||
|
elt.addEventListener(listenerData['evt'], listenerData['fn'], listenerData['cap']);
|
||||||
|
this.listeners[elt.id] = listenerData;
|
||||||
|
},
|
||||||
|
|
||||||
|
removeListeners: function() {
|
||||||
|
for (id in this.listeners) {
|
||||||
|
let listener = listeners[id];
|
||||||
|
document.getElementById(id)
|
||||||
|
.removeEventListener(listener['evt'], listener['fn'], listener['cap']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onMutation: function(mutation) {
|
||||||
|
log.debug("mutation: type="+mutation.type+" node="+mutation.target.nodeName+" attr="+mutation.attributeName);
|
||||||
|
if (mutation.type !== "attributes") return;
|
||||||
|
|
||||||
|
if (mutation.attributeName === "value") { // checkbox
|
||||||
|
log.debug("value changed!");
|
||||||
|
let checkboxCell = mutation.target;
|
||||||
|
let tree = document.getElementById("ui_tree_mail_accounts");
|
||||||
|
|
||||||
|
let subRows = firetray.Utils.XPath(
|
||||||
|
checkboxCell,
|
||||||
|
'ancestor::xul:treeitem[1]/child::xul:treechildren/xul:treeitem/xul:treerow');
|
||||||
|
log.debug("subRows="+subRows);
|
||||||
|
for (let i=0, len=subRows.length; i<len; ++i) {
|
||||||
|
firetrayUIOptions._disableTreeRow(
|
||||||
|
subRows[i], (checkboxCell.getAttribute("value") === "false"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (mutation.attributeName == "label") { // text
|
||||||
|
log.debug("label changed!");
|
||||||
|
log.warn("NOT IMPLEMENTED YET: move row to new rank"); // TODO
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("pref-pane-mail")
|
||||||
|
.userChangedValue(document.getElementById("ui_tree_mail_accounts"));
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
addMailAccountsObserver: function() {
|
||||||
|
this.mutationObserver = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(firetrayUIOptions.onMutation);
|
||||||
|
});
|
||||||
|
let config = { attributes: true, childList: true, characterData: false, subtree: true };
|
||||||
|
let target = document.querySelector('#ui_mail_accounts');
|
||||||
|
this.mutationObserver.observe(target, config);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeMailAccountsObserver: function() {
|
||||||
|
this.mutationObserver.disconnect();
|
||||||
|
this.mutationobserver = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the "mail_accounts" preference. This is called by the pref's system
|
* Save the "mail_accounts" preference. This is called by the pref's system
|
||||||
* when the GUI element is altered.
|
* when the GUI element is altered.
|
||||||
*/
|
*/
|
||||||
saveTreeAccountsOrServerTypes: function() {
|
saveTreeAccountsOrServerTypes: function() { // FIXME: broken ?
|
||||||
let tree = document.getElementById("ui_tree_mail_accounts");
|
let tree = document.getElementById("ui_tree_mail_accounts");
|
||||||
|
|
||||||
log.debug("VIEW="+ tree.view + ", rowCount="+tree.view.rowCount);
|
log.debug("VIEW="+ tree.view + ", rowCount="+tree.view.rowCount);
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
|
|
||||||
<preferences>
|
<preferences>
|
||||||
<preference id="pref_app_icon_type" name="extensions.firetray.app_icon_type" type="int"/>
|
<preference id="pref_app_icon_type" name="extensions.firetray.app_icon_type" type="int"/>
|
||||||
<preference id="pref_app_icon_filename" name="extensions.firetray.app_icon_filename" type="string"/>
|
<preference id="pref_app_icon_custom" name="extensions.firetray.app_icon_custom" type="string"/>
|
||||||
<preference id="pref_show_icon_on_hide" name="extensions.firetray.show_icon_on_hide" type="bool"/>
|
<preference id="pref_show_icon_on_hide" name="extensions.firetray.show_icon_on_hide" type="bool"/>
|
||||||
<preference id="pref_scroll_hides" name="extensions.firetray.scroll_hides" type="bool" />
|
<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_scroll_mode" name="extensions.firetray.scroll_mode" type="string" />
|
||||||
@ -97,7 +97,7 @@
|
|||||||
<radio id="ui_app_icon_type_custom" label="&app_icon_custom.label;"
|
<radio id="ui_app_icon_type_custom" label="&app_icon_custom.label;"
|
||||||
accesskey="&app_icon_custom.accesskey;" />
|
accesskey="&app_icon_custom.accesskey;" />
|
||||||
<hbox id="app_icon_custom" align="center" flex="1" >
|
<hbox id="app_icon_custom" align="center" flex="1" >
|
||||||
<textbox id="app_icon_custom_filename" preference="pref_app_icon_filename" flex="1" />
|
<textbox id="app_icon_custom_filename" preference="pref_app_icon_custom" flex="1" />
|
||||||
<button id="app_icon_custom_select" label="&choose;"
|
<button id="app_icon_custom_select" label="&choose;"
|
||||||
accesskey="&choose.accesskey;"
|
accesskey="&choose.accesskey;"
|
||||||
oncommand="firetrayUIOptions.chooseAppIconFile()" />
|
oncommand="firetrayUIOptions.chooseAppIconFile()" />
|
||||||
@ -129,14 +129,17 @@
|
|||||||
|
|
||||||
<preferences>
|
<preferences>
|
||||||
<preference id="pref_mail_notification_enabled" name="extensions.firetray.mail_notification_enabled" type="bool" />
|
<preference id="pref_mail_notification_enabled" name="extensions.firetray.mail_notification_enabled" type="bool" />
|
||||||
|
<preference id="pref_mail_notification_type" name="extensions.firetray.mail_notification_type" type="int" />
|
||||||
<preference id="pref_message_count_type" name="extensions.firetray.message_count_type" type="int" />
|
<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_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" />
|
<preference id="pref_mail_icon_custom" name="extensions.firetray.mail_icon_custom" type="string" />
|
||||||
|
<preference id="pref_excluded_folders_flags" name="extensions.firetray.excluded_folders_flags" type="int" />
|
||||||
<preference id="pref_mail_change_trigger" name="extensions.firetray.mail_change_trigger" type="string"/>
|
<preference id="pref_mail_change_trigger" name="extensions.firetray.mail_change_trigger" type="string"/>
|
||||||
<preference id="pref_mail_accounts" name="extensions.firetray.mail_accounts" type="string"/>
|
<preference id="pref_mail_accounts" name="extensions.firetray.mail_accounts" type="string"/>
|
||||||
<preference id="pref_folder_count_recursive" name="extensions.firetray.folder_count_recursive" 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_only_favorite_folders" name="extensions.firetray.only_favorite_folders" type="bool" />
|
||||||
<preference id="pref_mail_urgency_hint" name="extensions.firetray.mail_urgency_hint" type="bool" />
|
<preference id="pref_mail_change_trigger" name="extensions.firetray.mail_change_trigger" type="string" />
|
||||||
|
<preference id="pref_mail_get_attention" name="extensions.firetray.mail_get_attention" type="bool" />
|
||||||
</preferences>
|
</preferences>
|
||||||
|
|
||||||
<vbox align="left" flex="1">
|
<vbox align="left" flex="1">
|
||||||
@ -169,7 +172,7 @@
|
|||||||
observes="broadcaster-notification-disabled" />
|
observes="broadcaster-notification-disabled" />
|
||||||
</caption>
|
</caption>
|
||||||
|
|
||||||
<radiogroup id="ui_radiogroup_mail_notification">
|
<radiogroup id="ui_radiogroup_mail_notification" preference="pref_mail_notification_type">
|
||||||
<hbox id="ui_mail_notification_unread_count">
|
<hbox id="ui_mail_notification_unread_count">
|
||||||
<radio id="ui_radio_mail_notification_unread_count" label="&mail_notification_unread_count.label;"
|
<radio id="ui_radio_mail_notification_unread_count" label="&mail_notification_unread_count.label;"
|
||||||
accesskey="&mail_notification_unread_count.accesskey;"
|
accesskey="&mail_notification_unread_count.accesskey;"
|
||||||
@ -207,15 +210,14 @@
|
|||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox>
|
<hbox>
|
||||||
<radio id="ui_radio_mail_notification_custom_mail_icon" label="&mail_notification_custom_mail_icon.label;"
|
<radio id="ui_radio_mail_notification_mail_icon_custom" label="&mail_notification_mail_icon_custom.label;"
|
||||||
accesskey="&mail_notification_custom_mail_icon.accesskey;"
|
accesskey="&mail_notification_mail_icon_custom.accesskey;"
|
||||||
oncommand="firetrayUIOptions.updateNotificationSettings()"
|
oncommand="firetrayUIOptions.updateNotificationSettings()"
|
||||||
observes="broadcaster-notification-disabled" />
|
observes="broadcaster-notification-disabled" />
|
||||||
<hbox id="custom_mail_icon" align="center" flex="1" >
|
<hbox id="mail_icon_custom" align="center" flex="1" >
|
||||||
<textbox id="custom_mail_icon_filename" preference="pref_custom_mail_icon"
|
<textbox id="mail_icon_custom_filename" preference="pref_mail_icon_custom"
|
||||||
observes="broadcaster-notification-disabled"
|
observes="broadcaster-notification-disabled" flex="1" />
|
||||||
onchange="firetray.Messaging.updateIcon();" flex="1" />
|
<button id="mail_icon_custom_select" label="&choose;"
|
||||||
<button id="custom_mail_icon_select" label="&choose;"
|
|
||||||
accesskey="&choose.accesskey;"
|
accesskey="&choose.accesskey;"
|
||||||
observes="broadcaster-notification-disabled"
|
observes="broadcaster-notification-disabled"
|
||||||
oncommand="firetrayUIOptions.chooseMailIconFile()" />
|
oncommand="firetrayUIOptions.chooseMailIconFile()" />
|
||||||
@ -238,7 +240,8 @@
|
|||||||
|
|
||||||
<listbox id="excluded_folders_list" rows="7" flex="1" seltype="multiple"
|
<listbox id="excluded_folders_list" rows="7" flex="1" seltype="multiple"
|
||||||
tooltiptext="&excluded_folders_list.tooltip;"
|
tooltiptext="&excluded_folders_list.tooltip;"
|
||||||
onselect="firetrayUIOptions.updateExcludedFoldersPref()"
|
preference="pref_excluded_folders_flags"
|
||||||
|
onsynctopreference="return firetrayUIOptions.saveExcludedFoldersFlags(this);"
|
||||||
observes="broadcaster-notification-disabled" />
|
observes="broadcaster-notification-disabled" />
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
|
||||||
@ -295,15 +298,16 @@
|
|||||||
<label control="ui_mail_change_trigger" value="&mail_change_trigger.label;"
|
<label control="ui_mail_change_trigger" value="&mail_change_trigger.label;"
|
||||||
accesskey="&mail_change_trigger.accesskey;" />
|
accesskey="&mail_change_trigger.accesskey;" />
|
||||||
<textbox id="ui_mail_change_trigger" size="18" placeholder="&mail_change_trigger.placeholder;"
|
<textbox id="ui_mail_change_trigger" size="18" placeholder="&mail_change_trigger.placeholder;"
|
||||||
onchange="firetrayUIOptions.updateMailTrigger();" flex="1"
|
tooltiptext="&mail_change_trigger.tooltip;" flex="1"
|
||||||
tooltiptext="&mail_change_trigger.tooltip;"
|
preference="pref_mail_change_trigger"
|
||||||
|
onsynctopreference="return firetrayUIOptions.saveMailChangeTrigger(this);"
|
||||||
observes="broadcaster-notification-disabled" />
|
observes="broadcaster-notification-disabled" />
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<checkbox id="ui_mail_urgency_hint"
|
<checkbox id="ui_mail_get_attention"
|
||||||
label="&mail_urgency_hint.label;"
|
label="&mail_get_attention.label;"
|
||||||
accesskey="&mail_urgency_hint.accesskey;"
|
accesskey="&mail_get_attention.accesskey;"
|
||||||
preference="pref_mail_urgency_hint"
|
preference="pref_mail_get_attention"
|
||||||
observes="broadcaster-notification-disabled"/>
|
observes="broadcaster-notification-disabled"/>
|
||||||
|
|
||||||
</vbox>
|
</vbox>
|
||||||
@ -338,10 +342,8 @@
|
|||||||
<label control="ui_chat_icon_blink_style" observes="broadcaster-chat-icon-disabled"
|
<label control="ui_chat_icon_blink_style" observes="broadcaster-chat-icon-disabled"
|
||||||
value="&chat_icon_blink_style.label;" accesskey="&chat_icon_blink_style.accesskey;" />
|
value="&chat_icon_blink_style.label;" accesskey="&chat_icon_blink_style.accesskey;" />
|
||||||
<radio id="ui_chat_icon_blink_style_normal" label="&chat_icon_blink_style_normal;"
|
<radio id="ui_chat_icon_blink_style_normal" label="&chat_icon_blink_style_normal;"
|
||||||
oncommand="firetrayUIOptions.updateChatBlinkSettings()"
|
|
||||||
observes="broadcaster-chat-icon-disabled"/>
|
observes="broadcaster-chat-icon-disabled"/>
|
||||||
<radio id="ui_chat_icon_blink_style_fade" label="&chat_icon_blink_style_fade;"
|
<radio id="ui_chat_icon_blink_style_fade" label="&chat_icon_blink_style_fade;"
|
||||||
oncommand="firetrayUIOptions.updateChatBlinkSettings()"
|
|
||||||
observes="broadcaster-chat-icon-disabled"/>
|
observes="broadcaster-chat-icon-disabled"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</radiogroup>
|
</radiogroup>
|
||||||
|
@ -27,16 +27,17 @@ var firetrayChrome = { // each new window gets a new firetrayChrome !
|
|||||||
this.winId = firetray.Handler.registerWindow(win);
|
this.winId = firetray.Handler.registerWindow(win);
|
||||||
|
|
||||||
win.addEventListener('close', firetrayChrome.onClose, true);
|
win.addEventListener('close', firetrayChrome.onClose, true);
|
||||||
|
this.hijackTitlebarButtons();
|
||||||
|
|
||||||
firetray_log.debug('Firetray LOADED: ' + init);
|
firetray_log.debug('Firetray LOADED: ' + init);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: don't do firetray.Handler.initialized=false here, otherwise after a
|
/* NOTE: don't do firetray.Handler.initialized=false here, otherwise after a
|
||||||
window close, a new window will create a new handler (and hence, a new tray
|
window close, a new window will create a new handler (and hence, a new tray
|
||||||
icon) */
|
icon) */
|
||||||
onQuit: function(win) {
|
onQuit: function(win) {
|
||||||
|
win.removeEventListener('close', firetrayChrome.onClose, true);
|
||||||
firetray.Handler.unregisterWindow(win);
|
firetray.Handler.unregisterWindow(win);
|
||||||
firetray_log.info("windowsCount="+firetray.Handler.windowsCount+", visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
|
firetray_log.info("windowsCount="+firetray.Handler.windowsCount+", visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
|
||||||
firetray_log.debug('Firetray UNLOADED !');
|
firetray_log.debug('Firetray UNLOADED !');
|
||||||
@ -49,24 +50,96 @@ var firetrayChrome = { // each new window gets a new firetrayChrome !
|
|||||||
called *after* the popup */
|
called *after* the popup */
|
||||||
onClose: function(event) {
|
onClose: function(event) {
|
||||||
firetray_log.debug('Firetray CLOSE');
|
firetray_log.debug('Firetray CLOSE');
|
||||||
let win = event.originalTarget;
|
|
||||||
if (!win instanceof ChromeWindow)
|
|
||||||
throw new TypeError('originalTarget not a ChromeWindow');
|
|
||||||
|
|
||||||
let hides_on_close = firetray.Utils.prefService.getBoolPref('hides_on_close');
|
let hides_on_close = firetray.Utils.prefService.getBoolPref('hides_on_close');
|
||||||
firetray_log.debug('hides_on_close: '+hides_on_close);
|
firetray_log.debug('hides_on_close: '+hides_on_close);
|
||||||
if (hides_on_close) {
|
if (!hides_on_close) return false;
|
||||||
let hides_single_window = firetray.Utils.prefService.getBoolPref('hides_single_window');
|
|
||||||
let hides_last_only = firetray.Utils.prefService.getBoolPref('hides_last_only');
|
|
||||||
firetray_log.debug('hides_single_window='+hides_single_window+', windowsCount='+firetray.Handler.windowsCount);
|
|
||||||
if (hides_last_only && (firetray.Handler.windowsCount > 1)) return;
|
|
||||||
|
|
||||||
if (hides_single_window)
|
let hides_single_window = firetray.Utils.prefService.getBoolPref('hides_single_window');
|
||||||
firetray.Handler.hideWindow(firetrayChrome.winId);
|
let hides_last_only = firetray.Utils.prefService.getBoolPref('hides_last_only');
|
||||||
else
|
firetray_log.debug('hides_single_window='+hides_single_window+', windowsCount='+firetray.Handler.windowsCount);
|
||||||
firetray.Handler.hideAllWindows();
|
if (hides_last_only && (firetray.Handler.windowsCount > 1)) return true;
|
||||||
|
|
||||||
event && event.preventDefault();
|
if (hides_single_window)
|
||||||
|
firetray.Handler.hideWindow(firetrayChrome.winId);
|
||||||
|
else
|
||||||
|
firetray.Handler.hideAllWindows();
|
||||||
|
|
||||||
|
if (event) event.preventDefault();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimize/Restore/Close buttons can be overlayed by titlebar (fake) buttons
|
||||||
|
* which do not fire the events that we rely on (see Bug 827880). This is why
|
||||||
|
* we override the fake buttons' default actions.
|
||||||
|
*/
|
||||||
|
hijackTitlebarButtons: function() {
|
||||||
|
Object.keys(this.titlebarDispatch).map(function(val, idx) {
|
||||||
|
let fInfo = firetrayChrome.replaceCommand(val, firetrayChrome.titlebarDispatch[val]['new']);
|
||||||
|
if (fInfo) {
|
||||||
|
firetrayChrome.titlebarDispatch[val]['old'] = fInfo[0];
|
||||||
|
firetray_log.debug('replaced command='+val+' type='+fInfo[1]+' func='+fInfo[0]);
|
||||||
|
firetrayChrome.titlebarDispatch[val]['type'] = fInfo[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
titlebarDispatch: {
|
||||||
|
"titlebar-min": {new: function(e){
|
||||||
|
firetray_log.debug(' titlebar-min clicked');
|
||||||
|
if (!firetray.Handler.onMinimize(firetrayChrome.winId))
|
||||||
|
firetrayChrome.applyDefaultCommand("titlebar-min");
|
||||||
|
}, old: null, type: null},
|
||||||
|
|
||||||
|
"titlebar-close": {new: function(e){
|
||||||
|
firetray_log.debug(' titlebar-close clicked');
|
||||||
|
if (!firetrayChrome.onClose(null)) {
|
||||||
|
firetrayChrome.applyDefaultCommand("titlebar-close");
|
||||||
|
}
|
||||||
|
}, old: null, type: null}
|
||||||
|
},
|
||||||
|
|
||||||
|
replaceCommand: function(eltId, func) {
|
||||||
|
let elt = document.getElementById(eltId);
|
||||||
|
if (!elt) {
|
||||||
|
firetray_log.info("Element '"+eltId+"' not found. Command not replaced.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let command = elt.command;
|
||||||
|
let oncommand = elt.getAttribute("oncommand");
|
||||||
|
let old = null, type = null;
|
||||||
|
if (command) {
|
||||||
|
firetray_log.debug('command');
|
||||||
|
type = FIRETRAY_XUL_ATTRIBUTE_COMMAND;
|
||||||
|
old = elt.command;
|
||||||
|
elt.command = null;
|
||||||
|
elt.addEventListener('click', func, false);
|
||||||
|
} else if (oncommand) {
|
||||||
|
firetray_log.debug('oncommand');
|
||||||
|
type = FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND;
|
||||||
|
let prev = elt.getAttribute("oncommand");
|
||||||
|
old = new Function(prev);
|
||||||
|
elt.setAttribute("oncommand", void(0));
|
||||||
|
elt.addEventListener('command', func, false);
|
||||||
|
} else {
|
||||||
|
firetray_log.warn('Could not replace oncommand on '+eltId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [old, type];
|
||||||
|
},
|
||||||
|
applyDefaultCommand: function(key) {
|
||||||
|
let callType = this.titlebarDispatch[key]['type'];
|
||||||
|
if (callType === FIRETRAY_XUL_ATTRIBUTE_COMMAND) {
|
||||||
|
let cmdName = firetrayChrome.titlebarDispatch[key]['old'];
|
||||||
|
let cmd = document.getElementById(cmdName);
|
||||||
|
cmd.doCommand();
|
||||||
|
|
||||||
|
} else if (callType === FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND) {
|
||||||
|
firetrayChrome.titlebarDispatch[key]['old']();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
firetray_log.error("Calling type undefined for "+key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<?xml-stylesheet href="chrome://firetray/skin/overlay.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://firetray/skin/overlay.css" type="text/css"?>
|
||||||
<!DOCTYPE overlay SYSTEM "chrome://firetray/locale/overlay.dtd">
|
<!DOCTYPE overlay SYSTEM "chrome://firetray/locale/overlay.dtd">
|
||||||
<overlay id="firetray-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
<overlay id="firetray-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
<script type="application/javascript;version=1.7" src="overlay.js"/>
|
<script type="application/javascript;version=1.8" src="overlay.js"/>
|
||||||
|
|
||||||
<stringbundleset id="stringbundleset">
|
<stringbundleset id="stringbundleset">
|
||||||
<stringbundle id="firetray-strings" src="chrome://firetray/locale/overlay.properties"/>
|
<stringbundle id="firetray-strings" src="chrome://firetray/locale/overlay.properties"/>
|
||||||
|
@ -57,8 +57,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "U">
|
<!ENTITY mail_notification_unread_count.accesskey "U">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "display newmail icon">
|
<!ENTITY mail_notification_newmail_icon.label "display newmail icon">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "display custom icon">
|
<!ENTITY mail_notification_mail_icon_custom.label "display custom icon">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "I">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "I">
|
||||||
<!ENTITY icon_text_color "Text color">
|
<!ENTITY icon_text_color "Text color">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "Choose">
|
<!ENTITY choose "Choose">
|
||||||
@ -87,8 +87,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "L">
|
<!ENTITY mail_change_trigger.accesskey "L">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Absolute path of the program to run when the message count changes. This program will get the new message count as the first argument.">
|
<!ENTITY mail_change_trigger.tooltip "Absolute path of the program to run when the message count changes. This program will get the new message count as the first argument.">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
|
|
||||||
<!ENTITY chat_icon_enable.label "Enable chat icon">
|
<!ENTITY chat_icon_enable.label "Enable chat icon">
|
||||||
<!ENTITY chat_icon_enable.accesskey "E">
|
<!ENTITY chat_icon_enable.accesskey "E">
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "U">
|
<!ENTITY mail_notification_unread_count.accesskey "U">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "visualizar ícono de correo nuevo">
|
<!ENTITY mail_notification_newmail_icon.label "visualizar ícono de correo nuevo">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "n">
|
<!ENTITY mail_notification_newmail_icon.accesskey "n">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "visualizar ícono personalizado">
|
<!ENTITY mail_notification_mail_icon_custom.label "visualizar ícono personalizado">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "p">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "p">
|
||||||
<!ENTITY icon_text_color "Color de texto">
|
<!ENTITY icon_text_color "Color de texto">
|
||||||
<!ENTITY icon_text_color.accesskey "C">
|
<!ENTITY icon_text_color.accesskey "C">
|
||||||
<!ENTITY choose "Seleccionar">
|
<!ENTITY choose "Seleccionar">
|
||||||
@ -77,8 +77,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "L">
|
<!ENTITY mail_change_trigger.accesskey "L">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Ruta absoluta del programa para correr cuando la cuenta de mensajes cambia. Este programa obtendrá recibira el contador de nuevos mensajes como primer argumento.">
|
<!ENTITY mail_change_trigger.tooltip "Ruta absoluta del programa para correr cuando la cuenta de mensajes cambia. Este programa obtendrá recibira el contador de nuevos mensajes como primer argumento.">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
<!ENTITY chat_icon_enable.label "Habilitar ícono de chat">
|
<!ENTITY chat_icon_enable.label "Habilitar ícono de chat">
|
||||||
<!ENTITY chat_icon_enable.accesskey "H">
|
<!ENTITY chat_icon_enable.accesskey "H">
|
||||||
<!ENTITY chat_icon_blink.label "Icono de chat parpadea con mensajes nuevos.">
|
<!ENTITY chat_icon_blink.label "Icono de chat parpadea con mensajes nuevos.">
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "N">
|
<!ENTITY mail_notification_unread_count.accesskey "N">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "afficher l'icône de nouveau message">
|
<!ENTITY mail_notification_newmail_icon.label "afficher l'icône de nouveau message">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "f">
|
<!ENTITY mail_notification_newmail_icon.accesskey "f">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "afficher l'icône personnalisée">
|
<!ENTITY mail_notification_mail_icon_custom.label "afficher l'icône personnalisée">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "i">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "i">
|
||||||
<!ENTITY icon_text_color "Couleur du texte">
|
<!ENTITY icon_text_color "Couleur du texte">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "Choisir">
|
<!ENTITY choose "Choisir">
|
||||||
@ -77,10 +77,10 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "L">
|
<!ENTITY mail_change_trigger.accesskey "L">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Chemin absolu du programme à lancer lorsque le compte des messages a changé. Ce programme prendra pour base le nouveau décompte de messages">
|
<!ENTITY mail_change_trigger.tooltip "Chemin absolu du programme à lancer lorsque le compte des messages a changé. Ce programme prendra pour base le nouveau décompte de messages">
|
||||||
<!ENTITY mail_urgency_hint.label "Activer l'indice d'urgence X11">
|
<!ENTITY mail_get_attention.label "La fenêtre attire l'attention lors de nouveaux messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "e">
|
||||||
<!ENTITY chat_icon_enable.label "Activer l'icône du chat">
|
<!ENTITY chat_icon_enable.label "Activer l'icône du chat">
|
||||||
<!ENTITY chat_icon_enable.accesskey "A">
|
<!ENTITY chat_icon_enable.accesskey "h">
|
||||||
<!ENTITY chat_icon_blink.label "L'icône du chat clignote à l'arrivée de nouveaux messages">
|
<!ENTITY chat_icon_blink.label "L'icône du chat clignote à l'arrivée de nouveaux messages">
|
||||||
<!ENTITY chat_icon_blink.accesskey "i">
|
<!ENTITY chat_icon_blink.accesskey "i">
|
||||||
<!ENTITY chat_icon_blink.tooltip "quand un message privé est cité sur un canal">
|
<!ENTITY chat_icon_blink.tooltip "quand un message privé est cité sur un canal">
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "U">
|
<!ENTITY mail_notification_unread_count.accesskey "U">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "Visualizza l'icona per i nuovi messaggi">
|
<!ENTITY mail_notification_newmail_icon.label "Visualizza l'icona per i nuovi messaggi">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "Visualizza icona personalizzata">
|
<!ENTITY mail_notification_mail_icon_custom.label "Visualizza icona personalizzata">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "I">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "I">
|
||||||
<!ENTITY icon_text_color "Colore del testo">
|
<!ENTITY icon_text_color "Colore del testo">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "Scegli">
|
<!ENTITY choose "Scegli">
|
||||||
@ -77,8 +77,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "L">
|
<!ENTITY mail_change_trigger.accesskey "L">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Percorso assoluto del programma da lanciare quando viene incrementato il contatore dei messaggi non letti. Il programma utilizzerà il contatore dei nuovi messaggi come primo argomento.">
|
<!ENTITY mail_change_trigger.tooltip "Percorso assoluto del programma da lanciare quando viene incrementato il contatore dei messaggi non letti. Il programma utilizzerà il contatore dei nuovi messaggi come primo argomento.">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
<!ENTITY chat_icon_enable.label "Attiva icona della chat">
|
<!ENTITY chat_icon_enable.label "Attiva icona della chat">
|
||||||
<!ENTITY chat_icon_enable.accesskey "E">
|
<!ENTITY chat_icon_enable.accesskey "E">
|
||||||
<!ENTITY chat_icon_blink.label "Lampeggiamento dell'icona della chat per nuovi messaggi">
|
<!ENTITY chat_icon_blink.label "Lampeggiamento dell'icona della chat per nuovi messaggi">
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "O">
|
<!ENTITY mail_notification_unread_count.accesskey "O">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "pictogram nieuw bericht weergeven">
|
<!ENTITY mail_notification_newmail_icon.label "pictogram nieuw bericht weergeven">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "aangepast pictogram weergeven">
|
<!ENTITY mail_notification_mail_icon_custom.label "aangepast pictogram weergeven">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "i">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "i">
|
||||||
<!ENTITY icon_text_color "Tekstkleur">
|
<!ENTITY icon_text_color "Tekstkleur">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "Kiezen">
|
<!ENTITY choose "Kiezen">
|
||||||
@ -77,8 +77,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "S">
|
<!ENTITY mail_change_trigger.accesskey "S">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Absoluut pad van het uit te voeren programma wanneer het aantal wijzigt. Dit programma krijgt het aantal nieuwe berichten als het eerste argument.">
|
<!ENTITY mail_change_trigger.tooltip "Absoluut pad van het uit te voeren programma wanneer het aantal wijzigt. Dit programma krijgt het aantal nieuwe berichten als het eerste argument.">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
<!ENTITY chat_icon_enable.label "Chatpictogram inschakelen">
|
<!ENTITY chat_icon_enable.label "Chatpictogram inschakelen">
|
||||||
<!ENTITY chat_icon_enable.accesskey "s">
|
<!ENTITY chat_icon_enable.accesskey "s">
|
||||||
<!ENTITY chat_icon_blink.label "Chatpictogram knippert bij nieuwe berichten">
|
<!ENTITY chat_icon_blink.label "Chatpictogram knippert bij nieuwe berichten">
|
||||||
|
@ -57,8 +57,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "P">
|
<!ENTITY mail_notification_unread_count.accesskey "P">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "zobraziť ikonu novej pošty">
|
<!ENTITY mail_notification_newmail_icon.label "zobraziť ikonu novej pošty">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "zobraziť vlastnú ikonu">
|
<!ENTITY mail_notification_mail_icon_custom.label "zobraziť vlastnú ikonu">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "V">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "V">
|
||||||
<!ENTITY icon_text_color "Farba textu">
|
<!ENTITY icon_text_color "Farba textu">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "Vyberte">
|
<!ENTITY choose "Vyberte">
|
||||||
@ -87,8 +87,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "S">
|
<!ENTITY mail_change_trigger.accesskey "S">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "Absolútna cesta programu, ktorý bude spustený pri zmene počtu správ. Prvý argument je počet nových správ.">
|
<!ENTITY mail_change_trigger.tooltip "Absolútna cesta programu, ktorý bude spustený pri zmene počtu správ. Prvý argument je počet nových správ.">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
|
|
||||||
<!ENTITY chat_icon_enable.label "Zapnúť ikonu chatu">
|
<!ENTITY chat_icon_enable.label "Zapnúť ikonu chatu">
|
||||||
<!ENTITY chat_icon_enable.accesskey "E">
|
<!ENTITY chat_icon_enable.accesskey "E">
|
||||||
|
@ -51,8 +51,8 @@
|
|||||||
<!ENTITY mail_notification_unread_count.accesskey "U">
|
<!ENTITY mail_notification_unread_count.accesskey "U">
|
||||||
<!ENTITY mail_notification_newmail_icon.label "顯示新郵件圖示">
|
<!ENTITY mail_notification_newmail_icon.label "顯示新郵件圖示">
|
||||||
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
<!ENTITY mail_notification_newmail_icon.accesskey "N">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.label "顯示自訂圖示">
|
<!ENTITY mail_notification_mail_icon_custom.label "顯示自訂圖示">
|
||||||
<!ENTITY mail_notification_custom_mail_icon.accesskey "I">
|
<!ENTITY mail_notification_mail_icon_custom.accesskey "I">
|
||||||
<!ENTITY icon_text_color "文字色彩">
|
<!ENTITY icon_text_color "文字色彩">
|
||||||
<!ENTITY icon_text_color.accesskey "T">
|
<!ENTITY icon_text_color.accesskey "T">
|
||||||
<!ENTITY choose "選擇">
|
<!ENTITY choose "選擇">
|
||||||
@ -77,8 +77,8 @@
|
|||||||
<!ENTITY mail_change_trigger.accesskey "L">
|
<!ENTITY mail_change_trigger.accesskey "L">
|
||||||
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
<!ENTITY mail_change_trigger.placeholder "/bin/notify-send">
|
||||||
<!ENTITY mail_change_trigger.tooltip "要在訊息數改變時執行程式的絕對路徑。程式會將新的訊息數作為第一個參數。">
|
<!ENTITY mail_change_trigger.tooltip "要在訊息數改變時執行程式的絕對路徑。程式會將新的訊息數作為第一個參數。">
|
||||||
<!ENTITY mail_urgency_hint.label "Set X11 urgency hint">
|
<!ENTITY mail_get_attention.label "Window draws attention on new messages">
|
||||||
<!ENTITY mail_urgency_hint.accesskey "X">
|
<!ENTITY mail_get_attention.accesskey "g">
|
||||||
<!ENTITY chat_icon_enable.label "啟用聊天圖示">
|
<!ENTITY chat_icon_enable.label "啟用聊天圖示">
|
||||||
<!ENTITY chat_icon_enable.accesskey "E">
|
<!ENTITY chat_icon_enable.accesskey "E">
|
||||||
<!ENTITY chat_icon_blink.label "有新訊息時閃爍聊天圖示">
|
<!ENTITY chat_icon_blink.label "有新訊息時閃爍聊天圖示">
|
||||||
|
BIN
src/chrome/skin/winnt/application-exit.bmp
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/chrome/skin/winnt/blank-icon.bmp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src/chrome/skin/winnt/document-new.bmp
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/chrome/skin/winnt/gtk-apply.bmp
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/chrome/skin/winnt/gtk-edit.bmp
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/chrome/skin/winnt/gtk-preferences.bmp
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/chrome/skin/winnt/mail-unread.ico
Normal file
After Width: | Height: | Size: 2.0 KiB |
@ -16,7 +16,7 @@ pref("extensions.firetray.app_icon_type", 0);
|
|||||||
pref("extensions.firetray.app_browser_icon_names", '["web-browser", "internet-web-browser"]');
|
pref("extensions.firetray.app_browser_icon_names", '["web-browser", "internet-web-browser"]');
|
||||||
pref("extensions.firetray.app_mail_icon_names", '["indicator-messages", "applications-email-panel"]');
|
pref("extensions.firetray.app_mail_icon_names", '["indicator-messages", "applications-email-panel"]');
|
||||||
pref("extensions.firetray.app_default_icon_names", '[]');
|
pref("extensions.firetray.app_default_icon_names", '[]');
|
||||||
pref("extensions.firetray.app_icon_filename", "");
|
pref("extensions.firetray.app_icon_custom", "");
|
||||||
pref("extensions.firetray.new_mail_icon_names", '["indicator-messages-new", "mail-message-new"]');
|
pref("extensions.firetray.new_mail_icon_names", '["indicator-messages-new", "mail-message-new"]');
|
||||||
pref("extensions.firetray.show_icon_on_hide", false);
|
pref("extensions.firetray.show_icon_on_hide", false);
|
||||||
pref("extensions.firetray.scroll_hides", true);
|
pref("extensions.firetray.scroll_hides", true);
|
||||||
@ -25,12 +25,12 @@ pref("extensions.firetray.chat_icon_enable", true);
|
|||||||
pref("extensions.firetray.chat_icon_blink", true);
|
pref("extensions.firetray.chat_icon_blink", true);
|
||||||
pref("extensions.firetray.chat_icon_blink_style", 0);
|
pref("extensions.firetray.chat_icon_blink_style", 0);
|
||||||
|
|
||||||
pref("extensions.firetray.mail_urgency_hint", true);
|
pref("extensions.firetray.mail_get_attention", true);
|
||||||
pref("extensions.firetray.message_count_type", 0);
|
pref("extensions.firetray.message_count_type", 0);
|
||||||
pref("extensions.firetray.mail_notification_enabled", true);
|
pref("extensions.firetray.mail_notification_enabled", true);
|
||||||
pref("extensions.firetray.mail_notification_type", 0);
|
pref("extensions.firetray.mail_notification_type", 0);
|
||||||
pref("extensions.firetray.icon_text_color", "#000000");
|
pref("extensions.firetray.icon_text_color", "#000000");
|
||||||
pref("extensions.firetray.custom_mail_icon", "");
|
pref("extensions.firetray.mail_icon_custom", "");
|
||||||
pref("extensions.firetray.mail_change_trigger", "");
|
pref("extensions.firetray.mail_change_trigger", "");
|
||||||
pref("extensions.firetray.folder_count_recursive", true);
|
pref("extensions.firetray.folder_count_recursive", true);
|
||||||
// Ci.nsMsgFolderFlags.Archive|Drafts|Junk|Queue|SentMail|Trash|Virtual
|
// Ci.nsMsgFolderFlags.Archive|Drafts|Junk|Queue|SentMail|Trash|Virtual
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<em:unpack>true</em:unpack> <!-- needed for embedded icons -->
|
<em:unpack>true</em:unpack> <!-- needed for embedded icons -->
|
||||||
<em:type>2</em:type>
|
<em:type>2</em:type>
|
||||||
<em:name>FireTray</em:name>
|
<em:name>FireTray</em:name>
|
||||||
<em:version>0.4.8</em:version> <!-- change FIRETRAY_VERSION accordingly ! -->
|
<em:version>0.5.0b1</em:version> <!-- change FIRETRAY_VERSION accordingly ! -->
|
||||||
<em:creator>Hua Luo, Francesco Solero, Foudil BRÉTEL</em:creator>
|
<em:creator>Hua Luo, Francesco Solero, Foudil BRÉTEL</em:creator>
|
||||||
<em:contributor>Hua Luo, Francesco Solero (Firetray original authors)</em:contributor>
|
<em:contributor>Hua Luo, Francesco Solero (Firetray original authors)</em:contributor>
|
||||||
<em:homepageURL>https://github.com/foudfou/firetray</em:homepageURL>
|
<em:homepageURL>https://github.com/foudfou/firetray</em:homepageURL>
|
||||||
@ -14,21 +14,22 @@
|
|||||||
<em:optionsURL>chrome://firetray/content/options.xul</em:optionsURL>
|
<em:optionsURL>chrome://firetray/content/options.xul</em:optionsURL>
|
||||||
<em:iconURL>chrome://firetray/skin/firetray48.png</em:iconURL>
|
<em:iconURL>chrome://firetray/skin/firetray48.png</em:iconURL>
|
||||||
<em:icon64URL>chrome://firetray/skin/firetray64.png</em:icon64URL>
|
<em:icon64URL>chrome://firetray/skin/firetray64.png</em:icon64URL>
|
||||||
<em:targetPlatform>Linux</em:targetPlatform> <!-- only Linux supported for now -->
|
<em:targetPlatform>Linux</em:targetPlatform>
|
||||||
|
<em:targetPlatform>WINNT</em:targetPlatform>
|
||||||
|
|
||||||
<em:targetApplication>
|
<em:targetApplication>
|
||||||
<Description>
|
<Description>
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
||||||
<em:minVersion>7.0</em:minVersion>
|
<em:minVersion>27.0</em:minVersion>
|
||||||
<em:maxVersion>27.0</em:maxVersion>
|
<em:maxVersion>30.0</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
|
|
||||||
<em:targetApplication> <!-- Thunderbird -->
|
<em:targetApplication> <!-- Thunderbird -->
|
||||||
<Description>
|
<Description>
|
||||||
<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
|
<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
|
||||||
<em:minVersion>7.0</em:minVersion>
|
<em:minVersion>27.0</em:minVersion>
|
||||||
<em:maxVersion>27.0</em:maxVersion>
|
<em:maxVersion>30.0</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = [ "firetray" ];
|
var EXPORTED_SYMBOLS = [ "firetray" ];
|
||||||
|
|
||||||
@ -37,8 +38,14 @@ firetray.Handler = {
|
|||||||
appHasChat: false,
|
appHasChat: false,
|
||||||
appStarted: false,
|
appStarted: false,
|
||||||
windows: {},
|
windows: {},
|
||||||
windowsCount: 0,
|
get windowsCount() {return Object.keys(this.windows).length;},
|
||||||
visibleWindowsCount: 0,
|
get visibleWindowsCount() {
|
||||||
|
let count = 0;
|
||||||
|
for (let wid in firetray.Handler.windows) {
|
||||||
|
if (firetray.Handler.windows[wid].visible) count += 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
},
|
||||||
observedTopics: {},
|
observedTopics: {},
|
||||||
ctypesLibs: {}, // {"lib1": lib1, "lib2": lib2}
|
ctypesLibs: {}, // {"lib1": lib1, "lib2": lib2}
|
||||||
|
|
||||||
@ -46,7 +53,7 @@ firetray.Handler = {
|
|||||||
appName: (function(){return Services.appinfo.name;})(),
|
appName: (function(){return Services.appinfo.name;})(),
|
||||||
xulVer: (function(){return Services.appinfo.platformVersion;})(), // Services.vc.compare(xulVer,"2.0a")>=0
|
xulVer: (function(){return Services.appinfo.platformVersion;})(), // Services.vc.compare(xulVer,"2.0a")>=0
|
||||||
runtimeABI: (function(){return Services.appinfo.XPCOMABI;})(),
|
runtimeABI: (function(){return Services.appinfo.XPCOMABI;})(),
|
||||||
runtimeOS: (function(){return Services.appinfo.OS;})(), // "WINNT", "Linux", "Darwin"
|
runtimeOS: (function(){return Services.appinfo.OS.toLowerCase();})(), // "WINNT", "Linux", "Darwin"
|
||||||
addonRootDir: (function(){
|
addonRootDir: (function(){
|
||||||
let uri = Services.io.newURI(Components.stack.filename, null, null);
|
let uri = Services.io.newURI(Components.stack.filename, null, null);
|
||||||
if (uri instanceof Ci.nsIFileURL) {
|
if (uri instanceof Ci.nsIFileURL) {
|
||||||
@ -55,6 +62,7 @@ firetray.Handler = {
|
|||||||
}
|
}
|
||||||
throw new Error("not resolved");
|
throw new Error("not resolved");
|
||||||
})(),
|
})(),
|
||||||
|
support: {chat: false, full_feat: false},
|
||||||
|
|
||||||
init: function() { // does creates icon
|
init: function() { // does creates icon
|
||||||
firetray.PrefListener.register(false);
|
firetray.PrefListener.register(false);
|
||||||
@ -62,17 +70,20 @@ firetray.Handler = {
|
|||||||
|
|
||||||
// version checked during install, so we shouldn't need to care
|
// version checked during install, so we shouldn't need to care
|
||||||
log.info("OS=" + this.runtimeOS + ", ABI=" + this.runtimeABI + ", XULrunner=" + this.xulVer);
|
log.info("OS=" + this.runtimeOS + ", ABI=" + this.runtimeABI + ", XULrunner=" + this.xulVer);
|
||||||
switch (this.runtimeOS) {
|
if (FIRETRAY_SUPPORTED_OS.indexOf(this.runtimeOS) < 0) {
|
||||||
case "Linux":
|
let platforms = FIRETRAY_SUPPORTED_OS.join(", ");
|
||||||
Cu.import("resource://firetray/linux/FiretrayStatusIcon.jsm");
|
log.error("Only "+platforms+" platform(s) supported at this time. Firetray not loaded");
|
||||||
log.debug('FiretrayStatusIcon imported');
|
|
||||||
Cu.import("resource://firetray/linux/FiretrayWindow.jsm");
|
|
||||||
log.debug('FiretrayWindow imported');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log.error("FIRETRAY: only Linux platform supported at this time. Firetray not loaded");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Cu.import("resource://firetray/"+this.runtimeOS+"/FiretrayStatusIcon.jsm");
|
||||||
|
log.debug("FiretrayStatusIcon "+this.runtimeOS+" imported");
|
||||||
|
Cu.import("resource://firetray/"+this.runtimeOS+"/FiretrayWindow.jsm");
|
||||||
|
log.debug("FiretrayWindow "+this.runtimeOS+" imported");
|
||||||
|
|
||||||
|
this.support['chat'] = FIRETRAY_CHAT_SUPPORTED_OS
|
||||||
|
.indexOf(this.runtimeOS) > -1;
|
||||||
|
this.support['full_feat'] = FIRETRAY_FULL_FEAT_SUPPORTED_OS
|
||||||
|
.indexOf(firetray.Handler.runtimeOS) > -1;
|
||||||
|
|
||||||
if (this.appId === FIRETRAY_APP_DB['thunderbird']['id'] ||
|
if (this.appId === FIRETRAY_APP_DB['thunderbird']['id'] ||
|
||||||
this.appId === FIRETRAY_APP_DB['seamonkey']['id'])
|
this.appId === FIRETRAY_APP_DB['seamonkey']['id'])
|
||||||
@ -108,13 +119,18 @@ firetray.Handler = {
|
|||||||
let chatIsProvided = this.isChatProvided();
|
let chatIsProvided = this.isChatProvided();
|
||||||
log.info('isChatProvided='+chatIsProvided);
|
log.info('isChatProvided='+chatIsProvided);
|
||||||
if (chatIsProvided) {
|
if (chatIsProvided) {
|
||||||
Cu.import("resource://firetray/FiretrayMessaging.jsm"); // needed for existsChatAccount
|
if (this.support['chat']) {
|
||||||
Cu.import("resource://firetray/FiretrayChat.jsm");
|
Cu.import("resource://firetray/FiretrayMessaging.jsm"); // needed for existsChatAccount
|
||||||
firetray.Utils.addObservers(firetray.Handler, [
|
Cu.import("resource://firetray/"+this.runtimeOS+"/FiretrayChat.jsm");
|
||||||
"account-added", "account-removed"]);
|
firetray.Utils.addObservers(firetray.Handler, [
|
||||||
if (firetray.Utils.prefService.getBoolPref("chat_icon_enable") &&
|
"account-added", "account-removed"]);
|
||||||
this.existsChatAccount())
|
if (firetray.Utils.prefService.getBoolPref("chat_icon_enable") &&
|
||||||
firetray.Chat.init();
|
this.existsChatAccount())
|
||||||
|
firetray.Chat.init();
|
||||||
|
} else {
|
||||||
|
let platforms = FIRETRAY_CHAT_SUPPORTED_OS.join(", ");
|
||||||
|
log.warn("Only "+platforms+" platform(s) supported at this time. Chat not loaded");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
firetray.Utils.addObservers(firetray.Handler,
|
firetray.Utils.addObservers(firetray.Handler,
|
||||||
@ -153,7 +169,8 @@ firetray.Handler = {
|
|||||||
|
|
||||||
shutdown: function() {
|
shutdown: function() {
|
||||||
log.debug("Disabling Handler");
|
log.debug("Disabling Handler");
|
||||||
if (firetray.Handler.isChatProvided() && firetray.Chat.initialized)
|
if (firetray.Handler.isChatProvided() && firetray.Handler.support['chat']
|
||||||
|
&& firetray.Chat.initialized)
|
||||||
firetray.Chat.shutdown();
|
firetray.Chat.shutdown();
|
||||||
|
|
||||||
if (this.inMailApp)
|
if (this.inMailApp)
|
||||||
@ -183,7 +200,7 @@ firetray.Handler = {
|
|||||||
|
|
||||||
tryCloseLibs: function() {
|
tryCloseLibs: function() {
|
||||||
try {
|
try {
|
||||||
for (libName in this.ctypesLibs) {
|
for (let libName in this.ctypesLibs) {
|
||||||
let lib = this.ctypesLibs[libName];
|
let lib = this.ctypesLibs[libName];
|
||||||
if (lib.available())
|
if (lib.available())
|
||||||
lib.close();
|
lib.close();
|
||||||
@ -302,7 +319,7 @@ firetray.Handler = {
|
|||||||
} else {
|
} else {
|
||||||
for (let winId in firetray.Handler.windows) {
|
for (let winId in firetray.Handler.windows) {
|
||||||
firetray.Chat.detachSelectListeners(firetray.Handler.windows[winId].chromeWin);
|
firetray.Chat.detachSelectListeners(firetray.Handler.windows[winId].chromeWin);
|
||||||
firetray.ChatStatusIcon.detachOnFocusInCallback(winId);
|
firetray.ChatStatusIcon.detachOnFocusInCallback(winId); // FIXME: to be removed
|
||||||
}
|
}
|
||||||
firetray.Chat.shutdown();
|
firetray.Chat.shutdown();
|
||||||
}
|
}
|
||||||
@ -311,19 +328,21 @@ firetray.Handler = {
|
|||||||
// these get overridden in OS-specific Icon/Window handlers
|
// these get overridden in OS-specific Icon/Window handlers
|
||||||
setIconImageDefault: function() {},
|
setIconImageDefault: function() {},
|
||||||
setIconImageNewMail: function() {},
|
setIconImageNewMail: function() {},
|
||||||
setIconImageFromFile: function(filename) {},
|
setIconImageCustom: function(prefname) {},
|
||||||
setIconText: function(text, color) {},
|
setIconText: function(text, color) {},
|
||||||
setIconTooltip: function(localizedMessage) {},
|
setIconTooltip: function(localizedMessage) {},
|
||||||
setIconTooltipDefault: function() {},
|
setIconTooltipDefault: function() {},
|
||||||
setIconVisibility: function(visible) {},
|
setIconVisibility: function(visible) {},
|
||||||
registerWindow: function(win) {},
|
registerWindow: function(win) {},
|
||||||
unregisterWindow: function(win) {},
|
unregisterWindow: function(win) {},
|
||||||
getWindowIdFromChromeWindow: function(win) {},
|
|
||||||
hideWindow: function(winId) {},
|
hideWindow: function(winId) {},
|
||||||
showWindow: function(winId) {},
|
showWindow: function(winId) {},
|
||||||
showHideAllWindows: function() {},
|
|
||||||
activateLastWindowCb: function(gtkStatusIcon, gdkEvent, userData) {},
|
activateLastWindowCb: function(gtkStatusIcon, gdkEvent, userData) {},
|
||||||
getActiveWindow: function() {},
|
getActiveWindow: function() {},
|
||||||
|
windowGetAttention: function(winId) {},
|
||||||
|
showHidePopupMenuItems: function() {}, // linux
|
||||||
|
addPopupWindowItemAndSeparatorMaybe: function(wid) {}, // winnt
|
||||||
|
removePopupWindowItemAndSeparatorMaybe: function(wid) {}, // winnt
|
||||||
|
|
||||||
showAllWindows: function() {
|
showAllWindows: function() {
|
||||||
log.debug("showAllWindows");
|
log.debug("showAllWindows");
|
||||||
@ -340,6 +359,34 @@ firetray.Handler = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showHideAllWindows: function() {
|
||||||
|
log.debug("showHideAllWindows");
|
||||||
|
log.debug(" visibleWindowsCount="+firetray.Handler.visibleWindowsCount+" / windowsCount="+firetray.Handler.windowsCount);
|
||||||
|
let visibilityRate = firetray.Handler.visibleWindowsCount /
|
||||||
|
firetray.Handler.windowsCount;
|
||||||
|
log.debug(" visibilityRate="+visibilityRate);
|
||||||
|
if ((0.5 < visibilityRate) && (visibilityRate < 1)
|
||||||
|
|| visibilityRate === 0) { // TODO: should be configurable
|
||||||
|
firetray.Handler.showAllWindows();
|
||||||
|
} else {
|
||||||
|
firetray.Handler.hideAllWindows();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onMinimize: function(wid) {
|
||||||
|
let hidden = false;
|
||||||
|
let hides_on_minimize = firetray.Utils.prefService.getBoolPref('hides_on_minimize');
|
||||||
|
if (hides_on_minimize) {
|
||||||
|
let hides_single_window = firetray.Utils.prefService.getBoolPref('hides_single_window');
|
||||||
|
if (hides_single_window)
|
||||||
|
firetray.Handler.hideWindow(wid);
|
||||||
|
else
|
||||||
|
firetray.Handler.hideAllWindows();
|
||||||
|
hidden = true;
|
||||||
|
}
|
||||||
|
return hidden;
|
||||||
|
},
|
||||||
|
|
||||||
showHideIcon: function() {
|
showHideIcon: function() {
|
||||||
if (firetray.Utils.prefService.getBoolPref('show_icon_on_hide'))
|
if (firetray.Utils.prefService.getBoolPref('show_icon_on_hide'))
|
||||||
firetray.Handler.setIconVisibility(
|
firetray.Handler.setIconVisibility(
|
||||||
@ -471,7 +518,7 @@ firetray.Handler = {
|
|||||||
firetray.PrefListener = new PrefListener(
|
firetray.PrefListener = new PrefListener(
|
||||||
FIRETRAY_PREF_BRANCH,
|
FIRETRAY_PREF_BRANCH,
|
||||||
function(branch, name) {
|
function(branch, name) {
|
||||||
log.debug('Pref changed: '+name);
|
log.debug('____Pref changed: '+name);
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'hides_single_window':
|
case 'hides_single_window':
|
||||||
firetray.Handler.showHidePopupMenuItems();
|
firetray.Handler.showHidePopupMenuItems();
|
||||||
@ -488,19 +535,27 @@ firetray.PrefListener = new PrefListener(
|
|||||||
firetray.Handler.setIconImageDefault();
|
firetray.Handler.setIconImageDefault();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'mail_notification_type':
|
||||||
|
case 'icon_text_color':
|
||||||
|
firetray.Messaging.updateIcon();
|
||||||
|
break;
|
||||||
case 'new_mail_icon_names':
|
case 'new_mail_icon_names':
|
||||||
firetray.StatusIcon.loadThemedIcons();
|
firetray.StatusIcon.loadThemedIcons();
|
||||||
case 'only_favorite_folders':
|
case 'excluded_folders_flags':
|
||||||
case 'message_count_type':
|
|
||||||
case 'folder_count_recursive':
|
case 'folder_count_recursive':
|
||||||
|
case 'mail_accounts':
|
||||||
|
case 'message_count_type':
|
||||||
|
case 'only_favorite_folders':
|
||||||
firetray.Messaging.updateMsgCountWithCb();
|
firetray.Messaging.updateMsgCountWithCb();
|
||||||
break;
|
break;
|
||||||
case 'app_mail_icon_names':
|
case 'app_mail_icon_names':
|
||||||
case 'app_browser_icon_names':
|
case 'app_browser_icon_names':
|
||||||
case 'app_default_icon_names':
|
case 'app_default_icon_names':
|
||||||
|
firetray.StatusIcon.loadThemedIcons(); // linux
|
||||||
|
case 'app_icon_custom':
|
||||||
|
case 'mail_icon_custom':
|
||||||
|
firetray.StatusIcon.loadImageCustom(name);
|
||||||
case 'app_icon_type':
|
case 'app_icon_type':
|
||||||
firetray.StatusIcon.loadThemedIcons();
|
|
||||||
case 'app_icon_filename':
|
|
||||||
firetray.Handler.setIconImageDefault();
|
firetray.Handler.setIconImageDefault();
|
||||||
if (firetray.Handler.inMailApp)
|
if (firetray.Handler.inMailApp)
|
||||||
firetray.Messaging.updateMsgCountWithCb();
|
firetray.Messaging.updateMsgCountWithCb();
|
||||||
@ -542,13 +597,14 @@ firetray.MailChatPrefListener = new PrefListener(
|
|||||||
case 'enabled':
|
case 'enabled':
|
||||||
let enableChatCond =
|
let enableChatCond =
|
||||||
(firetray.Handler.appHasChat &&
|
(firetray.Handler.appHasChat &&
|
||||||
firetray.Utils.prefService.getBoolPref("chat_icon_enable"));
|
firetray.Utils.prefService.getBoolPref("chat_icon_enable") &&
|
||||||
|
firetray.Handler.support['chat']);
|
||||||
if (!enableChatCond) return;
|
if (!enableChatCond) return;
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("mail.chat.enabled")) {
|
if (Services.prefs.getBoolPref("mail.chat.enabled")) {
|
||||||
if (!firetray.Chat) {
|
if (!firetray.Chat) {
|
||||||
Cu.import("resource://firetray/FiretrayMessaging.jsm"); // needed for existsChatAccount
|
Cu.import("resource://firetray/FiretrayMessaging.jsm"); // needed for existsChatAccount
|
||||||
Cu.import("resource://firetray/FiretrayChat.jsm");
|
Cu.import("resource://firetray/linux/FiretrayChat.jsm");
|
||||||
firetray.Utils.addObservers(firetray.Handler, [
|
firetray.Utils.addObservers(firetray.Handler, [
|
||||||
"account-added", "account-removed"]);
|
"account-added", "account-removed"]);
|
||||||
}
|
}
|
||||||
@ -642,7 +698,7 @@ firetray.VersionChangeHandler = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
tryEraseOldOptions: function() {
|
tryEraseOldOptions: function() {
|
||||||
let v03Options = [
|
let v0_3_Opts = [
|
||||||
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
"close_to_tray", "minimize_to_tray", "start_minimized", "confirm_exit",
|
||||||
"restore_to_next_unread", "mail_count_type", "show_mail_count",
|
"restore_to_next_unread", "mail_count_type", "show_mail_count",
|
||||||
"dont_count_spam", "dont_count_archive", "dont_count_drafts",
|
"dont_count_spam", "dont_count_archive", "dont_count_drafts",
|
||||||
@ -651,12 +707,13 @@ firetray.VersionChangeHandler = {
|
|||||||
"use_custom_special_icon", "custom_normal_icon", "custom_special_icon",
|
"use_custom_special_icon", "custom_normal_icon", "custom_special_icon",
|
||||||
"text_color", "scroll_to_hide", "scroll_action", "grab_multimedia_keys",
|
"text_color", "scroll_to_hide", "scroll_action", "grab_multimedia_keys",
|
||||||
"hide_show_mm_key", "accounts_to_exclude" ];
|
"hide_show_mm_key", "accounts_to_exclude" ];
|
||||||
let v040b2Options = [ 'mail_notification' ];
|
let v0_4_0b2_Opts = [ 'mail_notification' ];
|
||||||
let oldOptions = v03Options.concat(v040b2Options);
|
let v0_5_0b1_Opts = [ 'mail_urgency_hint', 'app_icon_filename', 'custom_mail_icon' ];
|
||||||
|
let oldOpts = v0_3_Opts.concat(v0_4_0b2_Opts).concat(v0_5_0b1_Opts);
|
||||||
|
|
||||||
for (let i = 0, length = oldOptions.length; i<length; ++i) {
|
for (let i = 0, length = oldOpts.length; i<length; ++i) {
|
||||||
try {
|
try {
|
||||||
let option = oldOptions[i];
|
let option = oldOpts[i];
|
||||||
firetray.Utils.prefService.clearUserPref(option);
|
firetray.Utils.prefService.clearUserPref(option);
|
||||||
} catch (x) {}
|
} catch (x) {}
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,14 @@ Cu.import("resource://gre/modules/PluralForm.jsm");
|
|||||||
Cu.import("resource://firetray/commons.js");
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
|
||||||
const FLDRS_UNINTERESTING = {
|
const FLDRS_UNINTERESTING = {
|
||||||
Archive: Ci.nsMsgFolderFlags.Archive,
|
Archive: Ci.nsMsgFolderFlags.Archive, // 0x00004000
|
||||||
Drafts: Ci.nsMsgFolderFlags.Drafts,
|
Drafts: Ci.nsMsgFolderFlags.Drafts, // 0x00000400
|
||||||
Junk: Ci.nsMsgFolderFlags.Junk,
|
Junk: Ci.nsMsgFolderFlags.Junk, // 0x40000000
|
||||||
Queue: Ci.nsMsgFolderFlags.Queue,
|
Queue: Ci.nsMsgFolderFlags.Queue, // 0x00000800
|
||||||
SentMail: Ci.nsMsgFolderFlags.SentMail,
|
SentMail: Ci.nsMsgFolderFlags.SentMail, // 0x00000200
|
||||||
Templates: Ci.nsMsgFolderFlags.Templates,
|
Templates: Ci.nsMsgFolderFlags.Templates, // 0x00400000
|
||||||
Trash: Ci.nsMsgFolderFlags.Trash,
|
Trash: Ci.nsMsgFolderFlags.Trash, // 0x00000100
|
||||||
Virtual: Ci.nsMsgFolderFlags.Virtual
|
Virtual: Ci.nsMsgFolderFlags.Virtual // 0x00000020
|
||||||
};
|
};
|
||||||
|
|
||||||
const ACCOUNTS_PREF_BRANCH = "mail.accountmanager.accounts";
|
const ACCOUNTS_PREF_BRANCH = "mail.accountmanager.accounts";
|
||||||
@ -73,8 +73,7 @@ firetray.Messaging = {
|
|||||||
|
|
||||||
/* could also use a PrefListener, but let's keep it simple for now */
|
/* could also use a PrefListener, but let's keep it simple for now */
|
||||||
observe: function(subject, topic, data) {
|
observe: function(subject, topic, data) {
|
||||||
if (topic === "nsPref:changed" &&
|
if (topic === "nsPref:changed" && data === ACCOUNTS_PREF_BRANCH) {
|
||||||
data === ACCOUNTS_PREF_BRANCH) {
|
|
||||||
log.debug(ACCOUNTS_PREF_BRANCH+"="+subject.QueryInterface(Ci.nsIPrefBranch).getCharPref(ACCOUNTS_PREF_BRANCH));
|
log.debug(ACCOUNTS_PREF_BRANCH+"="+subject.QueryInterface(Ci.nsIPrefBranch).getCharPref(ACCOUNTS_PREF_BRANCH));
|
||||||
this.cleanExcludedAccounts();
|
this.cleanExcludedAccounts();
|
||||||
}
|
}
|
||||||
@ -183,10 +182,10 @@ firetray.Messaging = {
|
|||||||
if (mailChangeTriggerFile)
|
if (mailChangeTriggerFile)
|
||||||
firetray.Messaging.runProcess(mailChangeTriggerFile, [newMsgCount.toString()]);
|
firetray.Messaging.runProcess(mailChangeTriggerFile, [newMsgCount.toString()]);
|
||||||
|
|
||||||
let setUrgency = firetray.Utils.prefService.getBoolPref("mail_urgency_hint");
|
let getAttention = firetray.Utils.prefService.getBoolPref("mail_get_attention");
|
||||||
if (setUrgency && (newMsgCount > currentMsgCount))
|
if (getAttention && (newMsgCount > currentMsgCount))
|
||||||
for (let winId in firetray.Handler.windows)
|
for (let winId in firetray.Handler.windows)
|
||||||
firetray.Window.setUrgency(winId, true);
|
firetray.Handler.windowGetAttention(winId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -206,6 +205,7 @@ firetray.Messaging = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateIcon: function(msgCount) {
|
updateIcon: function(msgCount) {
|
||||||
|
log.debug("updateIcon");
|
||||||
if ("undefined" === typeof(msgCount)) msgCount = this.currentMsgCount;
|
if ("undefined" === typeof(msgCount)) msgCount = this.currentMsgCount;
|
||||||
|
|
||||||
let localizedTooltip;
|
let localizedTooltip;
|
||||||
@ -227,6 +227,7 @@ firetray.Messaging = {
|
|||||||
|
|
||||||
} else if (msgCount > 0) {
|
} else if (msgCount > 0) {
|
||||||
let prefMailNotification = firetray.Utils.prefService.getIntPref('mail_notification_type');
|
let prefMailNotification = firetray.Utils.prefService.getIntPref('mail_notification_type');
|
||||||
|
log.debug("msgCount prefMailNotification="+prefMailNotification);
|
||||||
switch (prefMailNotification) {
|
switch (prefMailNotification) {
|
||||||
case FIRETRAY_NOTIFICATION_MESSAGE_COUNT:
|
case FIRETRAY_NOTIFICATION_MESSAGE_COUNT:
|
||||||
let prefIconTextColor = firetray.Utils.prefService.getCharPref("icon_text_color");
|
let prefIconTextColor = firetray.Utils.prefService.getCharPref("icon_text_color");
|
||||||
@ -236,8 +237,7 @@ firetray.Messaging = {
|
|||||||
firetray.Handler.setIconImageNewMail();
|
firetray.Handler.setIconImageNewMail();
|
||||||
break;
|
break;
|
||||||
case FIRETRAY_NOTIFICATION_CUSTOM_ICON:
|
case FIRETRAY_NOTIFICATION_CUSTOM_ICON:
|
||||||
let prefCustomIconPath = firetray.Utils.prefService.getCharPref("custom_mail_icon");
|
firetray.Handler.setIconImageCustom('mail_icon_custom');
|
||||||
firetray.Handler.setIconImageFromFile(prefCustomIconPath);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.error("Unknown notification mode: "+prefMailNotification);
|
log.error("Unknown notification mode: "+prefMailNotification);
|
||||||
|
43
src/modules/FiretrayWindow.jsm
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
// https://developer.mozilla.org/en/Code_snippets/Preferences
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = [ "FiretrayWindow" ];
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
|
||||||
|
let log = firetray.Logging.getLogger("firetray.FiretrayWindow");
|
||||||
|
|
||||||
|
if ("undefined" == typeof(firetray.Handler))
|
||||||
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||||
|
|
||||||
|
function FiretrayWindow () {}
|
||||||
|
FiretrayWindow.prototype = {
|
||||||
|
|
||||||
|
getRegisteredWinIdFromChromeWindow: function(win) {
|
||||||
|
for (let wid in firetray.Handler.windows)
|
||||||
|
if (firetray.Handler.windows[wid].chromeWin === win) return wid;
|
||||||
|
log.error("unknown window while lookup");
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
getWindowTitle: function(wid) {
|
||||||
|
let title = firetray.Handler.windows[wid].baseWin.title;
|
||||||
|
log.debug("|baseWin.title="+title+"|");
|
||||||
|
let tailIndex;
|
||||||
|
tailIndex = title.indexOf(" - Mozilla "+firetray.Handler.appName);
|
||||||
|
if (tailIndex === -1)
|
||||||
|
tailIndex = title.indexOf(" - "+firetray.Handler.appName);
|
||||||
|
|
||||||
|
if (tailIndex !== -1)
|
||||||
|
return title.substring(0, tailIndex);
|
||||||
|
else if (title === "Mozilla "+firetray.Handler.appName)
|
||||||
|
return title;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
@ -3,20 +3,20 @@
|
|||||||
/* for now, logging facilities (imported from logging.jsm) and Services are
|
/* for now, logging facilities (imported from logging.jsm) and Services are
|
||||||
automatically provided by this module */
|
automatically provided by this module */
|
||||||
var EXPORTED_SYMBOLS =
|
var EXPORTED_SYMBOLS =
|
||||||
[ "firetray", "FIRETRAY_ID", "FIRETRAY_VERSION", "FIRETRAY_PREF_BRANCH",
|
[ "firetray", "FIRETRAY_VERSION", "FIRETRAY_SUPPORTED_OS",
|
||||||
"FIRETRAY_SPLASH_PAGE", "FIRETRAY_APPLICATION_ICON_TYPE_THEMED",
|
"FIRETRAY_CHAT_SUPPORTED_OS", "FIRETRAY_FULL_FEAT_SUPPORTED_OS",
|
||||||
|
"FIRETRAY_ID", "FIRETRAY_PREF_BRANCH", "FIRETRAY_SPLASH_PAGE",
|
||||||
|
"FIRETRAY_APPLICATION_ICON_TYPE_THEMED",
|
||||||
"FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM",
|
"FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM",
|
||||||
"FIRETRAY_NOTIFICATION_MESSAGE_COUNT",
|
"FIRETRAY_NOTIFICATION_MESSAGE_COUNT",
|
||||||
"FIRETRAY_NOTIFICATION_NEWMAIL_ICON", "FIRETRAY_NOTIFICATION_CUSTOM_ICON",
|
"FIRETRAY_NOTIFICATION_NEWMAIL_ICON", "FIRETRAY_NOTIFICATION_CUSTOM_ICON",
|
||||||
"FIRETRAY_IM_STATUS_AVAILABLE", "FIRETRAY_IM_STATUS_AWAY",
|
"FIRETRAY_IM_STATUS_AVAILABLE", "FIRETRAY_IM_STATUS_AWAY",
|
||||||
"FIRETRAY_IM_STATUS_BUSY", "FIRETRAY_IM_STATUS_OFFLINE",
|
"FIRETRAY_IM_STATUS_BUSY", "FIRETRAY_IM_STATUS_OFFLINE",
|
||||||
"FIRETRAY_ACCOUNT_SERVER_TYPE_IM",
|
"FIRETRAY_ACCOUNT_SERVER_TYPE_IM", "FIRETRAY_DELAY_STARTUP_MILLISECONDS",
|
||||||
"FIRETRAY_DELAY_STARTUP_MILLISECONDS",
|
"FIRETRAY_DELAY_NOWAIT_MILLISECONDS", "FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD",
|
||||||
"FIRETRAY_DELAY_NOWAIT_MILLISECONDS",
|
"FIRETRAY_MESSAGE_COUNT_TYPE_NEW", "FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL",
|
||||||
"FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD", "FIRETRAY_MESSAGE_COUNT_TYPE_NEW",
|
"FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE", "FIRETRAY_APP_DB",
|
||||||
"FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL",
|
"FIRETRAY_XUL_ATTRIBUTE_COMMAND", "FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND" ];
|
||||||
"FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE",
|
|
||||||
"FIRETRAY_APP_DB" ];
|
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
@ -25,10 +25,13 @@ const Cu = Components.utils;
|
|||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://firetray/logging.jsm");
|
Cu.import("resource://firetray/logging.jsm");
|
||||||
|
|
||||||
const FIRETRAY_VERSION = "0.4.8"; // needed for sync call of onVersionChange() :(
|
const FIRETRAY_VERSION = "0.5.0b1"; // needed for sync call of onVersionChange() :(
|
||||||
const FIRETRAY_ID = "{9533f794-00b4-4354-aa15-c2bbda6989f8}";
|
const FIRETRAY_SUPPORTED_OS = ['linux', 'winnt']; // install.rdf sync :(
|
||||||
const FIRETRAY_PREF_BRANCH = "extensions.firetray.";
|
const FIRETRAY_CHAT_SUPPORTED_OS = ['linux'];
|
||||||
const FIRETRAY_SPLASH_PAGE = "http://foudfou.github.com/FireTray/";
|
const FIRETRAY_FULL_FEAT_SUPPORTED_OS = FIRETRAY_CHAT_SUPPORTED_OS;
|
||||||
|
const FIRETRAY_ID = "{9533f794-00b4-4354-aa15-c2bbda6989f8}";
|
||||||
|
const FIRETRAY_PREF_BRANCH = "extensions.firetray.";
|
||||||
|
const FIRETRAY_SPLASH_PAGE = "http://foudfou.github.com/FireTray/";
|
||||||
|
|
||||||
const FIRETRAY_APPLICATION_ICON_TYPE_THEMED = 0;
|
const FIRETRAY_APPLICATION_ICON_TYPE_THEMED = 0;
|
||||||
const FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM = 1;
|
const FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM = 1;
|
||||||
@ -47,12 +50,15 @@ const FIRETRAY_IM_STATUS_OFFLINE = "user-offline";
|
|||||||
|
|
||||||
const FIRETRAY_ACCOUNT_SERVER_TYPE_IM = "im";
|
const FIRETRAY_ACCOUNT_SERVER_TYPE_IM = "im";
|
||||||
|
|
||||||
const FIRETRAY_DELAY_STARTUP_MILLISECONDS = 500;
|
const FIRETRAY_DELAY_STARTUP_MILLISECONDS = 500;
|
||||||
const FIRETRAY_DELAY_NOWAIT_MILLISECONDS = 0;
|
const FIRETRAY_DELAY_NOWAIT_MILLISECONDS = 0;
|
||||||
|
|
||||||
const FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL = 0;
|
const FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL = 0;
|
||||||
const FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE = 1;
|
const FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE = 1;
|
||||||
|
|
||||||
|
const FIRETRAY_XUL_ATTRIBUTE_COMMAND = 0;
|
||||||
|
const FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND = 1;
|
||||||
|
|
||||||
const FIRETRAY_APP_DB = {
|
const FIRETRAY_APP_DB = {
|
||||||
|
|
||||||
firefox: {
|
firefox: {
|
||||||
@ -72,7 +78,7 @@ const FIRETRAY_APP_DB = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
sunbird: {
|
sunbird: {
|
||||||
id: "718e30fb-e89b-41dd-9da7-e25a45638b28}",
|
id: "{718e30fb-e89b-41dd-9da7-e25a45638b28}",
|
||||||
},
|
},
|
||||||
|
|
||||||
chatzilla: {
|
chatzilla: {
|
||||||
@ -144,11 +150,13 @@ firetray.Utils = {
|
|||||||
|
|
||||||
getArrayPref: function(prefStr) {
|
getArrayPref: function(prefStr) {
|
||||||
let arrayPref = this.getObjPref(prefStr);
|
let arrayPref = this.getObjPref(prefStr);
|
||||||
if (!firetray.js.isArray(arrayPref)) throw new TypeError();
|
if (!firetray.js.isArray(arrayPref))
|
||||||
|
throw new TypeError("'"+prefStr+"' preference is not array.");
|
||||||
return arrayPref;
|
return arrayPref;
|
||||||
},
|
},
|
||||||
setArrayPref: function(prefStr, aArray) {
|
setArrayPref: function(prefStr, aArray) {
|
||||||
if (!firetray.js.isArray(aArray)) throw new TypeError();
|
if (!firetray.js.isArray(aArray))
|
||||||
|
throw new TypeError("'"+aArray+"' is not array.");
|
||||||
this.setObjPref(prefStr, aArray);
|
this.setObjPref(prefStr, aArray);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -189,11 +197,11 @@ firetray.Utils = {
|
|||||||
|
|
||||||
dumpObj: function(obj) {
|
dumpObj: function(obj) {
|
||||||
let str = "";
|
let str = "";
|
||||||
for(i in obj) {
|
for(let prop in firetray.js.listAllProperties(obj)) {
|
||||||
try {
|
try {
|
||||||
str += "obj["+i+"]: " + obj[i] + "\n";
|
str += "obj["+prop+"]: " + obj[prop] + "\n";
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
str += "obj["+i+"]: Unavailable\n";
|
str += "obj["+prop+"]: Unavailable\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.info(str);
|
log.info(str);
|
||||||
@ -262,6 +270,17 @@ firetray.Utils = {
|
|||||||
timer.initWithCallback({ notify: callback },
|
timer.initWithCallback({ notify: callback },
|
||||||
delay, timerType);
|
delay, timerType);
|
||||||
return timer;
|
return timer;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extracts statements from functions. Intended for feeding a 'oncommand'
|
||||||
|
* attribute.
|
||||||
|
* BUG: |let| assignations break oncommand inline callback under TB27
|
||||||
|
* The statements should probably be limited to a single function call.
|
||||||
|
*/
|
||||||
|
bodyToString: function(func) {
|
||||||
|
let matches = func.toSource().match(/\{([\s\S]*)\}/m);
|
||||||
|
return matches ? matches[1] : matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -291,7 +310,26 @@ firetray.js = {
|
|||||||
// https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Working_with_data#Quirks_in_equality
|
// https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Working_with_data#Quirks_in_equality
|
||||||
strEquals: function(obj1, obj2) {
|
strEquals: function(obj1, obj2) {
|
||||||
return obj1.toString() === obj2.toString();
|
return obj1.toString() === obj2.toString();
|
||||||
}
|
},
|
||||||
|
|
||||||
|
assert: function(condition, message) {
|
||||||
|
if (!condition) {
|
||||||
|
throw new Error(message || "Assertion failed");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Enumerating_all_properties_of_an_object
|
||||||
|
listAllProperties: function(obj){
|
||||||
|
var objectToInspect;
|
||||||
|
var result = [];
|
||||||
|
for(objectToInspect = obj; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){
|
||||||
|
result = result.concat(Object.getOwnPropertyNames(objectToInspect));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
floatToInt: function(nb) { return nb >> 0; } // bitwise ops on signed int
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/18912/how-to-find-keys-of-a-hash
|
// http://stackoverflow.com/questions/18912/how-to-find-keys-of-a-hash
|
||||||
|
@ -36,13 +36,18 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
var EXPORTED_SYMBOLS = [ "ctypes_library", "is64bit", "WinCbABI" ];
|
||||||
|
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://firetray/logging.jsm");
|
Cu.import("resource://firetray/logging.jsm");
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = [ "ctypes_library" ];
|
const is64bit = ctypes.size_t.size == 8; // firetray.Handler.runtimeABI.indexOf('_64') > -1;
|
||||||
|
|
||||||
|
const WinABI = is64bit ? ctypes.default_abi : ctypes.winapi_abi;
|
||||||
|
const WinCbABI = is64bit ? ctypes.default_abi : ctypes.stdcall_abi;
|
||||||
|
|
||||||
let log = firetray.Logging.getLogger("firetray.ctypes-utils");
|
let log = firetray.Logging.getLogger("firetray.ctypes-utils");
|
||||||
|
|
||||||
@ -111,7 +116,10 @@ function ctypes_library(aName, aABIs, aDefines, aGlobal) {
|
|||||||
|
|
||||||
var library;
|
var library;
|
||||||
for each (let abi in aABIs) {
|
for each (let abi in aABIs) {
|
||||||
let soname = "lib" + aName + ".so." + abi.toString();
|
// FIXME: ABI is in fact SO_VER. Now we're mixing .so versions and the
|
||||||
|
// .dll extension :(
|
||||||
|
let soname = abi === 'dll' ? aName :
|
||||||
|
"lib" + aName + ".so." + abi.toString();
|
||||||
log.debug("Trying " + soname);
|
log.debug("Trying " + soname);
|
||||||
try {
|
try {
|
||||||
library = ctypes.open(soname);
|
library = ctypes.open(soname);
|
||||||
@ -155,7 +163,12 @@ function ctypes_library(aName, aABIs, aDefines, aGlobal) {
|
|||||||
try {
|
try {
|
||||||
args = [];
|
args = [];
|
||||||
args.push(arguments[0]);
|
args.push(arguments[0]);
|
||||||
args.push(ctypes.default_abi);
|
// FIXME: ugly hack. We'll see when we need WinCbABI
|
||||||
|
if (this.ABI === 'dll') {
|
||||||
|
args.push(WinABI);
|
||||||
|
} else {
|
||||||
|
args.push(ctypes.default_abi);
|
||||||
|
}
|
||||||
for each (let arg in Array.prototype.slice.call(arguments, 1)) {
|
for each (let arg in Array.prototype.slice.call(arguments, 1)) {
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ ctypesMap.prototype.get = function(key) {
|
|||||||
return this.array[this.map[key]];
|
return this.array[this.map[key]];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.defineProperties(ctypesMap.prototype, {
|
||||||
|
"keys": {get: function(){return Object.keys(this.map);} }
|
||||||
|
});
|
||||||
|
|
||||||
ctypesMap.prototype.insert = function(key, item) {
|
ctypesMap.prototype.insert = function(key, item) {
|
||||||
if (this.map.hasOwnProperty(key)) {
|
if (this.map.hasOwnProperty(key)) {
|
||||||
log.debug("REPLACE");
|
log.debug("REPLACE");
|
||||||
|
@ -145,6 +145,7 @@ function gtk_defines(lib) {
|
|||||||
|
|
||||||
lib.lazy_bind("gtk_widget_is_focus", gobject.gboolean, this.GtkWidget.ptr);
|
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_has_focus", gobject.gboolean, this.GtkWidget.ptr);
|
||||||
|
lib.lazy_bind("gtk_widget_get_visible", gobject.gboolean, this.GtkWidget.ptr);
|
||||||
lib.lazy_bind("gtk_widget_hide_on_delete", 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_hide", ctypes.void_t, this.GtkWidget.ptr);
|
||||||
lib.lazy_bind("gtk_widget_show", ctypes.void_t, this.GtkWidget.ptr);
|
lib.lazy_bind("gtk_widget_show", ctypes.void_t, this.GtkWidget.ptr);
|
||||||
|
182
src/modules/ctypes/winnt/gdi32.jsm
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
var EXPORTED_SYMBOLS = [ "gdi32" ];
|
||||||
|
|
||||||
|
const GDI32_LIBNAME = "gdi32";
|
||||||
|
const GDI32_ABIS = [ "dll" ];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
|
||||||
|
function gdi32_defines(lib) {
|
||||||
|
|
||||||
|
this.BITMAP = ctypes.StructType("BITMAP", [
|
||||||
|
{ "bmType": win32.LONG },
|
||||||
|
{ "bmWidth": win32.LONG },
|
||||||
|
{ "bmHeight": win32.LONG },
|
||||||
|
{ "bmWidthBytes": win32.LONG },
|
||||||
|
{ "bmPlanes": win32.WORD },
|
||||||
|
{ "bmBitsPixel": win32.WORD },
|
||||||
|
{ "bmBits": win32.LPVOID }
|
||||||
|
]);
|
||||||
|
this.PBITMAP = this.BITMAP.ptr;
|
||||||
|
|
||||||
|
lib.lazy_bind("CreateCompatibleDC", win32.HDC, win32.HDC);
|
||||||
|
lib.lazy_bind("DeleteDC", win32.BOOL, win32.HDC);
|
||||||
|
lib.lazy_bind("BitBlt", win32.BOOL, win32.HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.HDC, ctypes.int, ctypes.int, win32.DWORD);
|
||||||
|
this.SRCCOPY = win32.DWORD(0x00CC0020); /* dest = source */
|
||||||
|
this.SRCPAINT = win32.DWORD(0x00EE0086); /* dest = source OR dest */
|
||||||
|
this.SRCAND = win32.DWORD(0x008800C6); /* dest = source AND dest */
|
||||||
|
this.SRCINVERT = win32.DWORD(0x00660046); /* dest = source XOR dest */
|
||||||
|
this.SRCERASE = win32.DWORD(0x00440328); /* dest = source AND (NOT dest ) */
|
||||||
|
this.NOTSRCCOPY = win32.DWORD(0x00330008); /* dest = (NOT source) */
|
||||||
|
this.NOTSRCERASE = win32.DWORD(0x001100A6); /* dest = (NOT src) AND (NOT dest) */
|
||||||
|
this.MERGECOPY = win32.DWORD(0x00C000CA); /* dest = (source AND pattern) */
|
||||||
|
this.MERGEPAINT = win32.DWORD(0x00BB0226); /* dest = (NOT source) OR dest */
|
||||||
|
this.PATCOPY = win32.DWORD(0x00F00021); /* dest = pattern */
|
||||||
|
this.PATPAINT = win32.DWORD(0x00FB0A09); /* dest = DPSnoo */
|
||||||
|
this.PATINVERT = win32.DWORD(0x005A0049); /* dest = pattern XOR dest */
|
||||||
|
this.DSTINVERT = win32.DWORD(0x00550009); /* dest = (NOT dest) */
|
||||||
|
this.BLACKNESS = win32.DWORD(0x00000042); /* dest = BLACK */
|
||||||
|
this.WHITENESS = win32.DWORD(0x00FF0062); /* dest = WHITE */
|
||||||
|
this.NOMIRRORBITMAP = win32.DWORD(0x80000000); /* Do not Mirror the bitmap in this call */
|
||||||
|
this.CAPTUREBLT = win32.DWORD(0x40000000); /* Include layered windows */
|
||||||
|
lib.lazy_bind("CreateCompatibleBitmap", win32.HBITMAP, win32.HDC, ctypes.int, ctypes.int);
|
||||||
|
lib.lazy_bind("CreateBitmapIndirect", win32.HBITMAP, win32.BITMAP.ptr);
|
||||||
|
lib.lazy_bind("GetObjectW", ctypes.int, win32.HGDIOBJ, ctypes.int, win32.LPVOID);
|
||||||
|
lib.lazy_bind("GetCurrentObject", win32.HGDIOBJ, win32.HDC, win32.UINT);
|
||||||
|
this.OBJ_PEN = 1;
|
||||||
|
this.OBJ_BRUSH = 2;
|
||||||
|
this.OBJ_DC = 3;
|
||||||
|
this.OBJ_METADC = 4;
|
||||||
|
this.OBJ_PAL = 5;
|
||||||
|
this.OBJ_FONT = 6;
|
||||||
|
this.OBJ_BITMAP = 7;
|
||||||
|
this.OBJ_REGION = 8;
|
||||||
|
this.OBJ_METAFILE = 9;
|
||||||
|
this.OBJ_MEMDC = 10;
|
||||||
|
this.OBJ_EXTPEN = 11;
|
||||||
|
this.OBJ_ENHMETADC = 12;
|
||||||
|
this.OBJ_ENHMETAFILE = 13;
|
||||||
|
this.OBJ_COLORSPACE = 14;
|
||||||
|
lib.lazy_bind("SelectObject", win32.HGDIOBJ, win32.HDC, win32.HGDIOBJ);
|
||||||
|
lib.lazy_bind("DeleteObject", win32.BOOL, win32.HGDIOBJ);
|
||||||
|
lib.lazy_bind("PatBlt", win32.BOOL, win32.HDC, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.DWORD);
|
||||||
|
this.BLACKNESS = win32.DWORD(0x00000042); /* dest = BLACK */
|
||||||
|
this.WHITENESS = win32.DWORD(0x00FF0062); /* dest = WHITE */
|
||||||
|
lib.lazy_bind("CreateFontW", win32.HFONT, ctypes.int, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.DWORD, win32.LPCWSTR);
|
||||||
|
this.FW_DONTCARE = 0;
|
||||||
|
this.FW_THIN = 100;
|
||||||
|
this.FW_EXTRALIGHT = 200;
|
||||||
|
this.FW_LIGHT = 300;
|
||||||
|
this.FW_NORMAL = 400;
|
||||||
|
this.FW_MEDIUM = 500;
|
||||||
|
this.FW_SEMIBOLD = 600;
|
||||||
|
this.FW_BOLD = 700;
|
||||||
|
this.FW_EXTRABOLD = 800;
|
||||||
|
this.FW_HEAVY = 900;
|
||||||
|
this.FF_DONTCARE = (0<<4); /* Don't care or don't know. */
|
||||||
|
this.FF_ROMAN = (1<<4); /* Variable stroke width, serifed. Times Roman, Century Schoolbook, etc. */
|
||||||
|
this.FF_SWISS = (2<<4); /* Variable stroke width, sans-serifed. Helvetica, Swiss, etc. */
|
||||||
|
this.FF_MODERN = (3<<4); /* Constant stroke width, serifed or sans-serifed. Pica, Elite, Courier, etc. */
|
||||||
|
this.FF_SCRIPT = (4<<4); /* Cursive, etc. */
|
||||||
|
this.FF_DECORATIVE = (5<<4); /* Old English, etc. */
|
||||||
|
this.DEFAULT_PITCH = 0;
|
||||||
|
this.FIXED_PITCH = 1;
|
||||||
|
this.VARIABLE_PITCH = 2;
|
||||||
|
this.MONO_FONT = 8;
|
||||||
|
this.ANSI_CHARSET = 0;
|
||||||
|
this.DEFAULT_CHARSET = 1;
|
||||||
|
this.SYMBOL_CHARSET = 2;
|
||||||
|
this.SHIFTJIS_CHARSET = 128;
|
||||||
|
this.HANGEUL_CHARSET = 129;
|
||||||
|
this.HANGUL_CHARSET = 129;
|
||||||
|
this.GB2312_CHARSET = 134;
|
||||||
|
this.CHINESEBIG5_CHARSET = 136;
|
||||||
|
this.OEM_CHARSET = 255;
|
||||||
|
this.JOHAB_CHARSET = 130;
|
||||||
|
this.HEBREW_CHARSET = 177;
|
||||||
|
this.ARABIC_CHARSET = 178;
|
||||||
|
this.GREEK_CHARSET = 161;
|
||||||
|
this.TURKISH_CHARSET = 162;
|
||||||
|
this.VIETNAMESE_CHARSET = 163;
|
||||||
|
this.THAI_CHARSET = 222;
|
||||||
|
this.EASTEUROPE_CHARSET = 238;
|
||||||
|
this.RUSSIAN_CHARSET = 204;
|
||||||
|
this.DEFAULT_QUALITY = 0;
|
||||||
|
this.DRAFT_QUALITY = 1;
|
||||||
|
this.PROOF_QUALITY = 2;
|
||||||
|
this.NONANTIALIASED_QUALITY = 3;
|
||||||
|
this.ANTIALIASED_QUALITY = 4;
|
||||||
|
this.CLEARTYPE_QUALITY = 5;
|
||||||
|
this.CLEARTYPE_NATURAL_QUALITY = 6;
|
||||||
|
this.OUT_DEFAULT_PRECIS = 0;
|
||||||
|
this.OUT_STRING_PRECIS = 1;
|
||||||
|
this.OUT_CHARACTER_PRECIS = 2;
|
||||||
|
this.OUT_STROKE_PRECIS = 3;
|
||||||
|
this.OUT_TT_PRECIS = 4;
|
||||||
|
this.OUT_DEVICE_PRECIS = 5;
|
||||||
|
this.OUT_RASTER_PRECIS = 6;
|
||||||
|
this.OUT_TT_ONLY_PRECIS = 7;
|
||||||
|
this.OUT_OUTLINE_PRECIS = 8;
|
||||||
|
this.OUT_SCREEN_OUTLINE_PRECIS = 9;
|
||||||
|
this.OUT_PS_ONLY_PRECIS = 10;
|
||||||
|
|
||||||
|
lib.lazy_bind("GetTextFaceW", ctypes.int, win32.HDC, ctypes.int, win32.LPTSTR);
|
||||||
|
lib.lazy_bind("SetTextColor", win32.COLORREF, win32.HDC, win32.COLORREF);
|
||||||
|
lib.lazy_bind("SetBkMode", ctypes.int, win32.HDC, ctypes.int);
|
||||||
|
this.TRANSPARENT = 1;
|
||||||
|
this.OPAQUE = 2;
|
||||||
|
this.BKMODE_LAST = 2;
|
||||||
|
|
||||||
|
lib.lazy_bind("TextOutW", win32.BOOL, win32.HDC, ctypes.int, ctypes.int, win32.LPCTSTR, ctypes.int);
|
||||||
|
|
||||||
|
this.SIZE = ctypes.StructType("SIZE", [
|
||||||
|
{ "cx": win32.LONG },
|
||||||
|
{ "cy": win32.LONG }
|
||||||
|
]);
|
||||||
|
this.LPSIZE = this.SIZE.ptr;
|
||||||
|
lib.lazy_bind("GetTextExtentPoint32W", win32.BOOL, win32.HDC, win32.LPCTSTR, ctypes.int, this.LPSIZE);
|
||||||
|
|
||||||
|
lib.lazy_bind("GetTextAlign", win32.UINT, win32.HDC);
|
||||||
|
lib.lazy_bind("SetTextAlign", win32.UINT, win32.HDC, win32.UINT);
|
||||||
|
this.TA_LEFT = 0;
|
||||||
|
this.TA_RIGHT = 2;
|
||||||
|
this.TA_CENTER = 6;
|
||||||
|
this.TA_TOP = 0;
|
||||||
|
this.TA_BOTTOM = 8;
|
||||||
|
this.TA_BASELINE = 24;
|
||||||
|
this.TA_RTLREADING = 256;
|
||||||
|
this.TA_MASK =(this.TA_BASELINE+this.TA_CENTER+this.TA_UPDATECP+this.TA_RTLREADING);
|
||||||
|
|
||||||
|
this.BITMAPINFOHEADER = ctypes.StructType("BITMAPINFOHEADER", [
|
||||||
|
{ "biSize": win32.DWORD },
|
||||||
|
{ "biWidth": win32.LONG },
|
||||||
|
{ "biHeight": win32.LONG },
|
||||||
|
{ "biPlanes": win32.WORD },
|
||||||
|
{ "biBitCount": win32.WORD },
|
||||||
|
{ "biCompression": win32.DWORD },
|
||||||
|
{ "biSizeImage": win32.DWORD },
|
||||||
|
{ "biXPelsPerMeter": win32.LONG },
|
||||||
|
{ "biYPelsPerMeter": win32.LONG },
|
||||||
|
{ "biClrUsed": win32.DWORD },
|
||||||
|
{ "biClrImportant": win32.DWORD }
|
||||||
|
]);
|
||||||
|
this.PBITMAPINFOHEADER = this.BITMAPINFOHEADER.ptr;
|
||||||
|
this.RGBQUAD = ctypes.StructType("RGBQUAD", [
|
||||||
|
{ "rgbBlue": win32.BYTE },
|
||||||
|
{ "rgbGreen": win32.BYTE },
|
||||||
|
{ "rgbRed": win32.BYTE },
|
||||||
|
{ "rgbReserved": win32.BYTE }
|
||||||
|
]);
|
||||||
|
this.BITMAPINFO = ctypes.StructType("BITMAPINFO", [
|
||||||
|
{ "bmiHeader": this.BITMAPINFOHEADER },
|
||||||
|
{ "bmiColors": this.RGBQUAD.array(1) }
|
||||||
|
]);
|
||||||
|
this.PBITMAPINFO = this.BITMAPINFO.ptr;
|
||||||
|
lib.lazy_bind("SetDIBits", ctypes.int, win32.HDC, win32.HBITMAP, win32.UINT, win32.UINT, ctypes.voidptr_t, this.BITMAPINFO.ptr, win32.UINT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new ctypes_library(GDI32_LIBNAME, GDI32_ABIS, gdi32_defines, this);
|
49
src/modules/ctypes/winnt/kernel32.jsm
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
var EXPORTED_SYMBOLS = [ "kernel32" ];
|
||||||
|
|
||||||
|
const KERNEL32_LIBNAME = "kernel32";
|
||||||
|
const KERNEL32_ABIS = [ "dll" ];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
|
||||||
|
function kernel32_defines(lib) {
|
||||||
|
|
||||||
|
this.OSVERSIONINFOEXW = ctypes.StructType("OSVERSIONINFOEXW", [
|
||||||
|
{ "dwOSVersionInfoSize": win32.DWORD },
|
||||||
|
{ "dwMajorVersion": win32.DWORD },
|
||||||
|
{ "dwMinorVersion": win32.DWORD },
|
||||||
|
{ "dwBuildNumber": win32.DWORD },
|
||||||
|
{ "dwPlatformId": win32.DWORD },
|
||||||
|
{ "szCSDVersion": ctypes.ArrayType(win32.TCHAR, 128) },
|
||||||
|
{ "wServicePackMajor": win32.WORD },
|
||||||
|
{ "wServicePackMinor": win32.WORD },
|
||||||
|
{ "wSuiteMask": win32.WORD },
|
||||||
|
{ "wProductType": win32.BYTE },
|
||||||
|
{ "wReserved": win32.BYTE }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// lib.lazy_bind("GetLastError", win32.DWORD); // use ctypes.winLastError instead
|
||||||
|
lib.lazy_bind("GetVersionExW", win32.BOOL, this.OSVERSIONINFOEXW.ptr);
|
||||||
|
lib.lazy_bind("GetConsoleWindow", win32.HWND);
|
||||||
|
lib.lazy_bind("GetConsoleTitleW", win32.DWORD, win32.LPTSTR, win32.DWORD);
|
||||||
|
lib.lazy_bind("GetModuleHandleW", win32.HMODULE, win32.LPCTSTR);
|
||||||
|
|
||||||
|
lib.lazy_bind("LoadLibraryW", win32.HMODULE, win32.LPCTSTR);
|
||||||
|
lib.lazy_bind("GetProcAddress", win32.FARPROC, win32.HMODULE, win32.LPCSTR);
|
||||||
|
lib.lazy_bind("GetCurrentThreadId", win32.DWORD);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new ctypes_library(KERNEL32_LIBNAME, KERNEL32_ABIS, kernel32_defines, this);
|
||||||
|
|
||||||
|
|
||||||
|
let osvi = new kernel32.OSVERSIONINFOEXW();
|
||||||
|
osvi.dwOSVersionInfoSize = kernel32.OSVERSIONINFOEXW.size;
|
||||||
|
if (kernel32.GetVersionExW(osvi.address())) {
|
||||||
|
win32.WINVER = (+osvi.dwMajorVersion)*10 + (+osvi.dwMinorVersion); // ctypes.UInt64 objects!
|
||||||
|
} else {
|
||||||
|
Cu.reportError("win version not found");
|
||||||
|
}
|
96
src/modules/ctypes/winnt/shell32.jsm
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
var EXPORTED_SYMBOLS = [ "shell32" ];
|
||||||
|
|
||||||
|
const SHELL32_LIBNAME = "shell32";
|
||||||
|
const SHELL32_ABIS = [ "dll" ];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
|
||||||
|
function shell32_defines(lib) {
|
||||||
|
|
||||||
|
this.NOTIFYICONDATAW = ctypes.StructType("NOTIFYICONDATAW", [
|
||||||
|
{ "cbSize": win32.DWORD },
|
||||||
|
{ "hWnd": win32.HWND },
|
||||||
|
{ "uID": win32.UINT },
|
||||||
|
{ "uFlags": win32.UINT },
|
||||||
|
{ "uCallbackMessage": win32.UINT },
|
||||||
|
{ "hIcon": win32.HICON },
|
||||||
|
{ "szTip": ctypes.ArrayType(win32.TCHAR, 128) },
|
||||||
|
{ "dwState": win32.DWORD },
|
||||||
|
{ "dwStateMask": win32.DWORD },
|
||||||
|
{ "szInfo": ctypes.ArrayType(win32.TCHAR, 256) },
|
||||||
|
{ "uTimeoutOrVersion": win32.UINT }, // union
|
||||||
|
{ "szInfoTitle": ctypes.ArrayType(win32.TCHAR, 64) },
|
||||||
|
{ "dwInfoFlags": win32.DWORD },
|
||||||
|
{ "guidItem": win32.GUID },
|
||||||
|
{ "hBalloonIcon": win32.HICON }
|
||||||
|
]);
|
||||||
|
this.NOTIFY_VERSION = 3; // 2K+
|
||||||
|
this.NOTIFYICON_VERSION_4 = 4; // Vista+
|
||||||
|
|
||||||
|
// #define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))
|
||||||
|
function FIELD_OFFSET(aType, aField, aPos) {
|
||||||
|
function addr2nb(a) {
|
||||||
|
return ctypes.cast(a, ctypes.unsigned_long).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'would be nice to use aType.ptr(1) (0 raises null pointer error) but we
|
||||||
|
// can't access fields (or their size) from a StructType.
|
||||||
|
let s = new aType();
|
||||||
|
let addr_base = addr2nb(s.address());
|
||||||
|
let addr_field;
|
||||||
|
if (typeof(aPos) == "undefined") {
|
||||||
|
addr_field = addr2nb(s.addressOfField(aField)); // s[aField].address() also fine
|
||||||
|
} else {
|
||||||
|
addr_field = addr2nb(s[aField].addressOfElement(aPos)); // pfew! nice feature!
|
||||||
|
}
|
||||||
|
return addr_field - addr_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.NOTIFYICONDATAW_V1_SIZE = FIELD_OFFSET(this.NOTIFYICONDATAW, 'szTip', 64); // FIELD_OFFSET(NOTIFYICONDATAW, szTip[64])
|
||||||
|
this.NOTIFYICONDATAW_V2_SIZE = FIELD_OFFSET(this.NOTIFYICONDATAW, 'guidItem'); // 2K
|
||||||
|
this.NOTIFYICONDATAW_V3_SIZE = FIELD_OFFSET(this.NOTIFYICONDATAW, 'hBalloonIcon'); // XP
|
||||||
|
|
||||||
|
this.NOTIFYICONDATAW_SIZE = function() {
|
||||||
|
let cbSize = this.NOTIFYICONDATAW.size;
|
||||||
|
if (!win32.WINVER) {
|
||||||
|
Cu.reportError("WINVER not defined! shell32 should be initialized before using WINVER.");
|
||||||
|
} else if (win32.WINVER >= win32.WIN_VERSIONS["Vista"]) {
|
||||||
|
cbSize = this.NOTIFYICONDATAW.size;
|
||||||
|
} else if (win32.WINVER >= win32.WIN_VERSIONS["XP"]) {
|
||||||
|
cbSize = this.NOTIFYICONDATAW_V3_SIZE;
|
||||||
|
} else if (win32.WINVER >= win32.WIN_VERSIONS["2K"]) {
|
||||||
|
cbSize = this.NOTIFYICONDATAW_V2_SIZE;
|
||||||
|
} else {
|
||||||
|
cbSize = this.NOTIFYICONDATAW_V1_SIZE;
|
||||||
|
}
|
||||||
|
return cbSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
lib.lazy_bind("Shell_NotifyIconW", win32.BOOL, win32.DWORD, this.NOTIFYICONDATAW.ptr);
|
||||||
|
|
||||||
|
// notify icon message
|
||||||
|
this.NIM_ADD = 0x00000000;
|
||||||
|
this.NIM_MODIFY = 0x00000001;
|
||||||
|
this.NIM_DELETE = 0x00000002;
|
||||||
|
this.NIM_SETFOCUS = 0x00000003;
|
||||||
|
this.NIM_SETVERSION = 0x00000004;
|
||||||
|
|
||||||
|
// for NOTIFYICONDATAW.uFlags
|
||||||
|
this.NIF_MESSAGE = 0x00000001;
|
||||||
|
this.NIF_ICON = 0x00000002;
|
||||||
|
this.NIF_TIP = 0x00000004;
|
||||||
|
this.NIF_STATE = 0x00000008;
|
||||||
|
this.NIF_INFO = 0x00000010;
|
||||||
|
this.NIF_GUID = 0x00000020;
|
||||||
|
this.NIF_REALTIME = 0x00000040;
|
||||||
|
this.NIF_SHOWTIP = 0x00000080;
|
||||||
|
|
||||||
|
lib.lazy_bind("ExtractIconW", win32.HICON, win32.HINSTANCE, win32.LPCTSTR, win32.UINT);
|
||||||
|
lib.lazy_bind("ExtractIconExW", win32.UINT, win32.LPCTSTR, ctypes.int, win32.HICON.ptr, win32.HICON.ptr, win32.UINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
new ctypes_library(SHELL32_LIBNAME, SHELL32_ABIS, shell32_defines, this);
|
380
src/modules/ctypes/winnt/user32.jsm
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
var EXPORTED_SYMBOLS = [ "user32" ];
|
||||||
|
|
||||||
|
const USER32_LIBNAME = "user32";
|
||||||
|
const USER32_ABIS = [ "dll" ];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
|
||||||
|
function user32_defines(lib) {
|
||||||
|
|
||||||
|
this.CHANGEFILTERSTRUCT = ctypes.StructType("CHANGEFILTERSTRUCT", [
|
||||||
|
{ "cbSize": win32.DWORD },
|
||||||
|
{ "ExtStatus": win32.DWORD }
|
||||||
|
]);
|
||||||
|
this.MSGFLTINFO_NONE = 0;
|
||||||
|
this.MSGFLTINFO_ALLOWED_HIGHER = 3;
|
||||||
|
this.MSGFLTINFO_ALREADYALLOWED_FORWND = 1;
|
||||||
|
this.MSGFLTINFO_ALREADYDISALLOWED_FORWND = 2;
|
||||||
|
|
||||||
|
lib.lazy_bind("ChangeWindowMessageFilter", win32.BOOL, win32.UINT, win32.DWORD);
|
||||||
|
this.MSGFLT_ADD = 1;
|
||||||
|
this.MSGFLT_REMOVE = 2;
|
||||||
|
lib.lazy_bind("ChangeWindowMessageFilterEx", win32.BOOL, win32.HWND, win32.UINT, win32.DWORD, this.CHANGEFILTERSTRUCT.ptr);
|
||||||
|
this.MSGFLT_ALLOW = 1;
|
||||||
|
this.MSGFLT_DISALLOW = 2;
|
||||||
|
this.MSGFLT_RESET = 0;
|
||||||
|
|
||||||
|
lib.lazy_bind("RegisterWindowMessageW", win32.UINT, win32.LPCTSTR);
|
||||||
|
lib.lazy_bind("GetWindowTextW", ctypes.int, win32.HWND, win32.LPTSTR, ctypes.int);
|
||||||
|
lib.lazy_bind("FindWindowW", win32.HWND, win32.LPCTSTR, win32.LPCTSTR);
|
||||||
|
|
||||||
|
lib.lazy_bind("SendMessageW", win32.LRESULT, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM);
|
||||||
|
this.WM_GETICON = 0x007F;
|
||||||
|
this.WM_SETICON = 0x0080;
|
||||||
|
this.ICON_SMALL = 0;
|
||||||
|
this.ICON_BIG = 1;
|
||||||
|
this.ICON_SMALL2 = 2;
|
||||||
|
|
||||||
|
lib.lazy_bind("GetClassLongPtrW", win32.ULONG_PTR, win32.HWND, ctypes.int);
|
||||||
|
lib.lazy_bind("GetClassLongW", win32.DWORD, win32.HWND, ctypes.int); // 32-bits
|
||||||
|
this.GetClassLong = is64bit ? this.GetClassLongPtrW : this.GetClassLongW;
|
||||||
|
this.GCLP_HICONSM = -34;
|
||||||
|
|
||||||
|
lib.lazy_bind("LoadIconW", win32.HICON, win32.HINSTANCE, win32.LPCTSTR); // superseeded by LoadImage
|
||||||
|
this.IDI_APPLICATION = win32.MAKEINTRESOURCE(32512);
|
||||||
|
this.IDI_HAND = win32.MAKEINTRESOURCE(32513);
|
||||||
|
this.IDI_QUESTION = win32.MAKEINTRESOURCE(32514);
|
||||||
|
this.IDI_EXCLAMATION = win32.MAKEINTRESOURCE(32515);
|
||||||
|
this.IDI_ASTERISK = win32.MAKEINTRESOURCE(32516);
|
||||||
|
lib.lazy_bind("DestroyIcon", win32.BOOL, win32.HICON);
|
||||||
|
lib.lazy_bind("LoadImageW", win32.HANDLE, win32.HINSTANCE, win32.LPCTSTR, win32.UINT, ctypes.int, ctypes.int, win32.UINT);
|
||||||
|
this.IMAGE_BITMAP = 0;
|
||||||
|
this.IMAGE_ICON = 1;
|
||||||
|
this.IMAGE_CURSOR = 2;
|
||||||
|
this.LR_CREATEDIBSECTION = 0x00002000;
|
||||||
|
this.LR_DEFAULTCOLOR = 0x00000000;
|
||||||
|
this.LR_DEFAULTSIZE = 0x00000040;
|
||||||
|
this.LR_LOADFROMFILE = 0x00000010;
|
||||||
|
this.LR_LOADMAP3DCOLORS = 0x00001000;
|
||||||
|
this.LR_LOADTRANSPARENT = 0x00000020;
|
||||||
|
this.LR_MONOCHROME = 0x00000001;
|
||||||
|
this.LR_SHARED = 0x00008000;
|
||||||
|
this.LR_VGACOLOR = 0x00000080;
|
||||||
|
lib.lazy_bind("CopyImage", win32.HANDLE, win32.HANDLE, win32.UINT, ctypes.int, ctypes.int, win32.UINT);
|
||||||
|
|
||||||
|
lib.lazy_bind("GetPropW", win32.HANDLE, win32.HWND, win32.LPCTSTR);
|
||||||
|
lib.lazy_bind("SetPropW", win32.BOOL, win32.HWND, win32.LPCTSTR, win32.HANDLE);
|
||||||
|
lib.lazy_bind("RemovePropW", win32.HANDLE, win32.HWND, win32.LPCTSTR);
|
||||||
|
|
||||||
|
lib.lazy_bind("GetWindowLongW", win32.LONG_PTR, win32.HWND, ctypes.int);
|
||||||
|
lib.lazy_bind("SetWindowLongW", win32.LONG_PTR , win32.HWND, ctypes.int, win32.LONG_PTR);
|
||||||
|
// SetWindowLongPtrW aliases SetWindowLongW with the correct signature thank
|
||||||
|
// win32.LONG_PTR
|
||||||
|
this.GWLP_WNDPROC = -4;
|
||||||
|
this.GWLP_HINSTANCE = -6;
|
||||||
|
this.GWLP_ID = -12;
|
||||||
|
this.GWL_STYLE = -16;
|
||||||
|
this.GWL_EXSTYLE = -20;
|
||||||
|
this.GWLP_USERDATA = -21;
|
||||||
|
lib.lazy_bind("SetClassLongW", win32.DWORD , win32.HWND, ctypes.int, win32.LONG); // superseeded by SetClassLongPtrW
|
||||||
|
this.GCL_MENUNAME = -8;
|
||||||
|
this.GCL_HBRBACKGROUND = -10;
|
||||||
|
this.GCL_HCURSOR = -12;
|
||||||
|
this.GCL_HICON = -14;
|
||||||
|
this.GCL_HMODULE = -16;
|
||||||
|
this.GCL_CBWNDEXTRA = -18;
|
||||||
|
this.GCL_CBCLSEXTRA = -20;
|
||||||
|
this.GCL_WNDPROC = -24;
|
||||||
|
this.GCL_HICONSM = -34;
|
||||||
|
|
||||||
|
this.WNDPROC = ctypes.FunctionType(
|
||||||
|
WinCbABI, win32.LRESULT,
|
||||||
|
[win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM]).ptr;
|
||||||
|
|
||||||
|
// lib.lazy_bind("CallWindowProcW", win32.LRESULT, this.WNDPROC, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM);
|
||||||
|
lib.lazy_bind("CallWindowProcW", win32.LRESULT, ctypes.voidptr_t, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM);
|
||||||
|
lib.lazy_bind("DefWindowProcW", win32.LRESULT, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM);
|
||||||
|
|
||||||
|
this.WNDCLASSEXW = ctypes.StructType("WNDCLASSEXW", [
|
||||||
|
{ "cbSize": win32.UINT },
|
||||||
|
{ "style": win32.UINT },
|
||||||
|
{ "lpfnWndProc": this.WNDPROC },
|
||||||
|
{ "cbClsExtra": ctypes.int },
|
||||||
|
{ "cbWndExtra": ctypes.int },
|
||||||
|
{ "hInstance": win32.HINSTANCE },
|
||||||
|
{ "hIcon": win32.HICON },
|
||||||
|
{ "hCursor": win32.HCURSOR },
|
||||||
|
{ "hbrBackground": win32.HBRUSH },
|
||||||
|
{ "lpszMenuName": win32.LPCTSTR },
|
||||||
|
{ "lpszClassName": win32.LPCTSTR },
|
||||||
|
{ "hIconSm": win32.HICON }
|
||||||
|
]);
|
||||||
|
|
||||||
|
lib.lazy_bind("RegisterClassExW", win32.ATOM, this.WNDCLASSEXW.ptr);
|
||||||
|
lib.lazy_bind("UnregisterClassW", win32.BOOL, win32.LPCTSTR, win32.HINSTANCE);
|
||||||
|
lib.lazy_bind("CreateWindowExW", win32.HWND, win32.DWORD, win32.LPCTSTR, win32.LPCTSTR, win32.DWORD, ctypes.int, ctypes.int, ctypes.int, ctypes.int, win32.HWND, win32.HMENU, win32.HINSTANCE, win32.LPVOID);
|
||||||
|
lib.lazy_bind("DestroyWindow", win32.BOOL, win32.HWND);
|
||||||
|
lib.lazy_bind("ShowWindow", win32.BOOL, win32.HWND, ctypes.int);
|
||||||
|
lib.lazy_bind("IsWindowVisible", win32.BOOL, win32.HWND);
|
||||||
|
|
||||||
|
this.SW_HIDE = 0;
|
||||||
|
this.SW_SHOWNORMAL = 1;
|
||||||
|
this.SW_NORMAL = 1;
|
||||||
|
this.SW_SHOWMINIMIZED = 2;
|
||||||
|
this.SW_SHOWMAXIMIZED = 3;
|
||||||
|
this.SW_MAXIMIZE = 3;
|
||||||
|
this.SW_SHOWNOACTIVATE = 4;
|
||||||
|
this.SW_SHOW = 5;
|
||||||
|
this.SW_MINIMIZE = 6;
|
||||||
|
this.SW_SHOWMINNOACTIVE = 7;
|
||||||
|
this.SW_SHOWNA = 8;
|
||||||
|
this.SW_RESTORE = 9;
|
||||||
|
this.SW_SHOWDEFAULT = 10;
|
||||||
|
this.SW_FORCEMINIMIZE = 11;
|
||||||
|
this.SW_MAX = 11;
|
||||||
|
|
||||||
|
this.CW_USEDEFAULT = ctypes.int(0x80000000); // -2147483648
|
||||||
|
|
||||||
|
this.HWND_BROADCAST = win32.HWND(0xffff);
|
||||||
|
this.HWND_MESSAGE = win32.HWND(-3); // WINVER >= 0x0500
|
||||||
|
|
||||||
|
// need to be win32.DWORD()'d after binray operations are applied !
|
||||||
|
this.WS_BORDER = 0x00800000;
|
||||||
|
this.WS_CAPTION = 0x00C00000;
|
||||||
|
this.WS_CHILD = 0x40000000;
|
||||||
|
this.WS_CHILDWINDOW = 0x40000000;
|
||||||
|
this.WS_CLIPCHILDREN = 0x02000000;
|
||||||
|
this.WS_CLIPSIBLINGS = 0x04000000;
|
||||||
|
this.WS_DISABLED = 0x08000000;
|
||||||
|
this.WS_DLGFRAME = 0x00400000;
|
||||||
|
this.WS_GROUP = 0x00020000;
|
||||||
|
this.WS_HSCROLL = 0x00100000;
|
||||||
|
this.WS_ICONIC = 0x20000000;
|
||||||
|
this.WS_MAXIMIZE = 0x01000000;
|
||||||
|
this.WS_MAXIMIZEBOX = 0x00010000;
|
||||||
|
this.WS_MINIMIZE = 0x20000000;
|
||||||
|
this.WS_MINIMIZEBOX = 0x00020000;
|
||||||
|
this.WS_OVERLAPPED = 0x00000000;
|
||||||
|
this.WS_POPUP = 0x80000000;
|
||||||
|
this.WS_SIZEBOX = 0x00040000;
|
||||||
|
this.WS_SYSMENU = 0x00080000;
|
||||||
|
this.WS_TABSTOP = 0x00010000;
|
||||||
|
this.WS_THICKFRAME = 0x00040000;
|
||||||
|
this.WS_TILED = 0x00000000;
|
||||||
|
this.WS_VISIBLE = 0x10000000;
|
||||||
|
this.WS_VSCROLL = 0x00200000;
|
||||||
|
this.WS_POPUPWINDOW = (this.WS_POPUP | this.WS_BORDER | this.WS_SYSMENU);
|
||||||
|
this.WS_OVERLAPPEDWINDOW = (this.WS_OVERLAPPED | this.WS_CAPTION | this.WS_SYSMENU | this.WS_THICKFRAME | this.WS_MINIMIZEBOX | this.WS_MAXIMIZEBOX);
|
||||||
|
this.WS_TILEDWINDOW = (this.WS_OVERLAPPED | this.WS_CAPTION | this.WS_SYSMENU | this.WS_THICKFRAME | this.WS_MINIMIZEBOX | this.WS_MAXIMIZEBOX);
|
||||||
|
|
||||||
|
this.CWPSTRUCT = ctypes.StructType("CWPSTRUCT", [
|
||||||
|
{ "lParam": win32.LPARAM },
|
||||||
|
{ "wParam": win32.WPARAM },
|
||||||
|
{ "message": win32.UINT },
|
||||||
|
{ "hwnd": win32.HWND }
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.CWPRETSTRUCT = ctypes.StructType("CWPRETSTRUCT", [
|
||||||
|
{ "lResult": win32.LRESULT },
|
||||||
|
{ "lParam": win32.LPARAM },
|
||||||
|
{ "wParam": win32.WPARAM },
|
||||||
|
{ "message": win32.UINT },
|
||||||
|
{ "hwnd": win32.HWND }
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.HOOKPROC = ctypes.FunctionType(
|
||||||
|
WinCbABI, win32.LRESULT,
|
||||||
|
[ctypes.int, win32.WPARAM, win32.LPARAM]).ptr;
|
||||||
|
|
||||||
|
lib.lazy_bind("SetWindowsHookExW", win32.HHOOK, ctypes.int, this.HOOKPROC, win32.HINSTANCE, win32.DWORD);
|
||||||
|
lib.lazy_bind("CallNextHookEx", win32.LRESULT, win32.HHOOK, ctypes.int, win32.WPARAM, win32.LPARAM);
|
||||||
|
lib.lazy_bind("UnhookWindowsHookEx", win32.BOOL, win32.HHOOK);
|
||||||
|
|
||||||
|
this.WH_MIN = (-1);
|
||||||
|
this.WH_MSGFILTER = (-1);
|
||||||
|
this.WH_JOURNALRECORD = 0;
|
||||||
|
this.WH_JOURNALPLAYBACK = 1;
|
||||||
|
this.WH_KEYBOARD = 2;
|
||||||
|
this.WH_GETMESSAGE = 3;
|
||||||
|
this.WH_CALLWNDPROC = 4;
|
||||||
|
this.WH_CBT = 5;
|
||||||
|
this.WH_SYSMSGFILTER = 6;
|
||||||
|
this.WH_MOUSE = 7;
|
||||||
|
this.WH_HARDWARE = 8;
|
||||||
|
this.WH_DEBUG = 9;
|
||||||
|
this.WH_SHELL = 10;
|
||||||
|
this.WH_FOREGROUNDIDLE = 11;
|
||||||
|
this.WH_CALLWNDPROCRET = 12;
|
||||||
|
this.WH_KEYBOARD_LL = 13;
|
||||||
|
this.WH_MOUSE_LL = 14;
|
||||||
|
|
||||||
|
this.HC_ACTION = 0;
|
||||||
|
this.HC_GETNEXT = 1;
|
||||||
|
this.HC_SKIP = 2;
|
||||||
|
this.HC_NOREMOVE = 3;
|
||||||
|
this.HC_NOREM = this.HC_NOREMOVE;
|
||||||
|
this.HC_SYSMODALON = 4;
|
||||||
|
this.HC_SYSMODALOFF = 5;
|
||||||
|
|
||||||
|
lib.lazy_bind("GetWindowThreadProcessId", win32.DWORD, win32.HWND, win32.LPDWORD);
|
||||||
|
|
||||||
|
this.FLASHWINFO = ctypes.StructType("FLASHWINFO", [
|
||||||
|
{ "cbSize": win32.UINT },
|
||||||
|
{ "hwnd": win32.HWND },
|
||||||
|
{ "dwFlags": win32.DWORD },
|
||||||
|
{ "uCount": win32.UINT },
|
||||||
|
{ "dwTimeout": win32.DWORD }
|
||||||
|
]);
|
||||||
|
this.PFLASHWINFO = this.FLASHWINFO.ptr;
|
||||||
|
|
||||||
|
lib.lazy_bind("FlashWindow", win32.BOOL, win32.HWND, win32.BOOL);
|
||||||
|
lib.lazy_bind("FlashWindowEx", win32.BOOL, this.PFLASHWINFO);
|
||||||
|
|
||||||
|
this.FLASHW_STOP = 0;
|
||||||
|
this.FLASHW_CAPTION = 0x00000001;
|
||||||
|
this.FLASHW_TRAY = 0x00000002;
|
||||||
|
this.FLASHW_ALL =(this.FLASHW_CAPTION | this.FLASHW_TRAY);
|
||||||
|
this.FLASHW_TIMER = 0x00000004;
|
||||||
|
this.FLASHW_TIMERNOFG = 0x0000000C;
|
||||||
|
|
||||||
|
lib.lazy_bind("SystemParametersInfoW", win32.BOOL, win32.UINT, win32.UINT, win32.PVOID, win32.UINT);
|
||||||
|
this.SPI_GETFOREGROUNDFLASHCOUNT = 0x2004;
|
||||||
|
lib.lazy_bind("GetForegroundWindow", win32.HWND);
|
||||||
|
|
||||||
|
lib.lazy_bind("GetDC", win32.HDC, win32.HWND);
|
||||||
|
lib.lazy_bind("ReleaseDC", ctypes.int, win32.HWND, win32.HDC);
|
||||||
|
lib.lazy_bind("CreateIconIndirect", win32.HICON, win32.PICONINFO);
|
||||||
|
lib.lazy_bind("GetClientRect", win32.BOOL, win32.HWND, win32.PRECT);
|
||||||
|
lib.lazy_bind("DrawTextW", ctypes.int, win32.HDC, win32.LPCTSTR, ctypes.int, win32.PRECT, win32.UINT);
|
||||||
|
this.DT_TOP = 0x00000000;
|
||||||
|
this.DT_LEFT = 0x00000000;
|
||||||
|
this.DT_CENTER = 0x00000001;
|
||||||
|
this.DT_RIGHT = 0x00000002;
|
||||||
|
this.DT_VCENTER = 0x00000004;
|
||||||
|
this.DT_BOTTOM = 0x00000008;
|
||||||
|
this.DT_WORDBREAK = 0x00000010;
|
||||||
|
this.DT_SINGLELINE = 0x00000020;
|
||||||
|
this.DT_EXPANDTABS = 0x00000040;
|
||||||
|
this.DT_TABSTOP = 0x00000080;
|
||||||
|
this.DT_NOCLIP = 0x00000100;
|
||||||
|
this.DT_EXTERNALLEADING = 0x00000200;
|
||||||
|
this.DT_CALCRECT = 0x00000400;
|
||||||
|
this.DT_NOPREFIX = 0x00000800;
|
||||||
|
this.DT_INTERNAL = 0x00001000;
|
||||||
|
|
||||||
|
lib.lazy_bind("CreatePopupMenu", win32.HMENU);
|
||||||
|
lib.lazy_bind("DestroyMenu", win32.BOOL, win32.HMENU);
|
||||||
|
|
||||||
|
this.MENUITEMINFOW = ctypes.StructType("MENUITEMINFOW", [
|
||||||
|
{ "cbSize": win32.UINT },
|
||||||
|
{ "fMask": win32.UINT },
|
||||||
|
{ "fType": win32.UINT },
|
||||||
|
{ "fState": win32.UINT },
|
||||||
|
{ "wID": win32.UINT },
|
||||||
|
{ "hSubMenu": win32.HMENU },
|
||||||
|
{ "hbmpChecked": win32.HBITMAP },
|
||||||
|
{ "hbmpUnchecked": win32.HBITMAP },
|
||||||
|
{ "dwItemData": win32.ULONG_PTR },
|
||||||
|
{ "dwTypeData": win32.LPWSTR },
|
||||||
|
{ "cch": win32.UINT },
|
||||||
|
{ "hbmpItem": win32.HBITMAP }
|
||||||
|
]);
|
||||||
|
this.LPCMENUITEMINFO = this.LPMENUITEMINFOW = this.MENUITEMINFOW.ptr;
|
||||||
|
|
||||||
|
lib.lazy_bind("InsertMenuItemW", win32.BOOL, win32.HMENU, win32.UINT, win32.BOOL, this.LPCMENUITEMINFO);
|
||||||
|
lib.lazy_bind("GetMenuItemInfoW", win32.BOOL, win32.HMENU, win32.UINT, win32.BOOL, this.LPCMENUITEMINFO);
|
||||||
|
|
||||||
|
this.MIIM_STATE = 0x00000001;
|
||||||
|
this.MIIM_ID = 0x00000002;
|
||||||
|
this.MIIM_SUBMENU = 0x00000004;
|
||||||
|
this.MIIM_CHECKMARKS = 0x00000008;
|
||||||
|
this.MIIM_TYPE = 0x00000010;
|
||||||
|
this.MIIM_DATA = 0x00000020;
|
||||||
|
this.MIIM_STRING = 0x00000040;
|
||||||
|
this.MIIM_BITMAP = 0x00000080;
|
||||||
|
this.MIIM_FTYPE = 0x00000100;
|
||||||
|
|
||||||
|
lib.lazy_bind("InsertMenuW", win32.BOOL, win32.HMENU, win32.UINT, win32.UINT, win32.UINT_PTR, win32.LPCTSTR);
|
||||||
|
lib.lazy_bind("DeleteMenu", win32.BOOL, win32.HMENU, win32.UINT, win32.UINT);
|
||||||
|
|
||||||
|
this.MF_INSERT = 0x00000000;
|
||||||
|
this.MF_CHANGE = 0x00000080;
|
||||||
|
this.MF_APPEND = 0x00000100;
|
||||||
|
this.MF_DELETE = 0x00000200;
|
||||||
|
this.MF_REMOVE = 0x00001000;
|
||||||
|
this.MF_BYCOMMAND = 0x00000000;
|
||||||
|
this.MF_BYPOSITION = 0x00000400;
|
||||||
|
this.MF_SEPARATOR = 0x00000800;
|
||||||
|
this.MF_ENABLED = 0x00000000;
|
||||||
|
this.MF_GRAYED = 0x00000001;
|
||||||
|
this.MF_DISABLED = 0x00000002;
|
||||||
|
this.MF_UNCHECKED = 0x00000000;
|
||||||
|
this.MF_CHECKED = 0x00000008;
|
||||||
|
this.MF_USECHECKBITMAPS = 0x00000200;
|
||||||
|
this.MF_STRING = 0x00000000;
|
||||||
|
this.MF_BITMAP = 0x00000004;
|
||||||
|
this.MF_OWNERDRAW = 0x00000100;
|
||||||
|
this.MF_POPUP = 0x00000010;
|
||||||
|
this.MF_MENUBARBREAK = 0x00000020;
|
||||||
|
this.MF_MENUBREAK = 0x00000040;
|
||||||
|
this.MF_UNHILITE = 0x00000000;
|
||||||
|
this.MF_HILITE = 0x00000080;
|
||||||
|
this.MF_DEFAULT = 0x00001000;
|
||||||
|
this.MF_RIGHTJUSTIFY = 0x00004000;
|
||||||
|
this.MFT_STRING = this.MF_STRING;
|
||||||
|
this.MFT_BITMAP = this.MF_BITMAP;
|
||||||
|
this.MFT_MENUBARBREAK = this.MF_MENUBARBREAK;
|
||||||
|
this.MFT_MENUBREAK = this.MF_MENUBREAK;
|
||||||
|
this.MFT_OWNERDRAW = this.MF_OWNERDRAW;
|
||||||
|
this.MFT_RADIOCHECK = 0x00000200;
|
||||||
|
this.MFT_SEPARATOR = this.MF_SEPARATOR;
|
||||||
|
this.MFT_RIGHTORDER = 0x00002000;
|
||||||
|
this.MFT_RIGHTJUSTIFY = this.MF_RIGHTJUSTIFY;
|
||||||
|
this.MFS_GRAYED = 0x00000003;
|
||||||
|
this.MFS_DISABLED = this.MFS_GRAYED;
|
||||||
|
this.MFS_CHECKED = this.MF_CHECKED;
|
||||||
|
this.MFS_HILITE = this.MF_HILITE;
|
||||||
|
this.MFS_ENABLED = this.MF_ENABLED;
|
||||||
|
this.MFS_UNCHECKED = this.MF_UNCHECKED;
|
||||||
|
this.MFS_UNHILITE = this.MF_UNHILITE;
|
||||||
|
this.MFS_DEFAULT = this.MF_DEFAULT;
|
||||||
|
|
||||||
|
this.TPM_LEFTBUTTON = 0x0000;
|
||||||
|
this.TPM_RIGHTBUTTON = 0x0002;
|
||||||
|
this.TPM_LEFTALIGN = 0x0000;
|
||||||
|
this.TPM_CENTERALIGN = 0x0004;
|
||||||
|
this.TPM_RIGHTALIGN = 0x0008;
|
||||||
|
this.TPM_TOPALIGN = 0x0000;
|
||||||
|
this.TPM_VCENTERALIGN = 0x0010;
|
||||||
|
this.TPM_BOTTOMALIGN = 0x0020;
|
||||||
|
this.TPM_HORIZONTAL = 0x0000;
|
||||||
|
this.TPM_VERTICAL = 0x0040;
|
||||||
|
|
||||||
|
lib.lazy_bind("GetMenuItemCount", ctypes.int, win32.HMENU);
|
||||||
|
|
||||||
|
lib.lazy_bind("CalculatePopupWindowPosition", win32.BOOL, win32.POINT.ptr, win32.SIZE, win32.UINT, win32.RECT.ptr, win32.RECT.ptr);
|
||||||
|
lib.lazy_bind("TrackPopupMenu", win32.BOOL, win32.HMENU, win32.UINT, ctypes.int, ctypes.int, ctypes.int, win32.HWND, win32.RECT.ptr);
|
||||||
|
lib.lazy_bind("SetForegroundWindow", win32.BOOL, win32.HWND);
|
||||||
|
lib.lazy_bind("GetCursorPos", win32.BOOL, win32.LPPOINT);
|
||||||
|
lib.lazy_bind("GetMessagePos", win32.DWORD);
|
||||||
|
|
||||||
|
this.WINDOWPLACEMENT = ctypes.StructType("WINDOWPLACEMENT", [
|
||||||
|
{ "length": win32.UINT },
|
||||||
|
{ "flags": win32.UINT },
|
||||||
|
{ "showCmd": win32.UINT },
|
||||||
|
{ "ptMinPosition": win32.POINT },
|
||||||
|
{ "ptMaxPosition": win32.POINT },
|
||||||
|
{ "rcNormalPosition": win32.RECT }
|
||||||
|
]);
|
||||||
|
this.PWINDOWPLACEMENT = this.LPWINDOWPLACEMENT = this.WINDOWPLACEMENT.ptr;
|
||||||
|
|
||||||
|
lib.lazy_bind("GetWindowPlacement", win32.BOOL, win32.HWND, this.WINDOWPLACEMENT.ptr);
|
||||||
|
lib.lazy_bind("SetWindowPlacement", win32.BOOL, win32.HWND, this.WINDOWPLACEMENT.ptr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);
|
210
src/modules/ctypes/winnt/win32.jsm
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
var EXPORTED_SYMBOLS = [ "win32" ];
|
||||||
|
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
|
||||||
|
|
||||||
|
|
||||||
|
var win32 = new function() {
|
||||||
|
|
||||||
|
this.WIN_VERSIONS = { // maj*10 + min
|
||||||
|
'8': 62, // 2012
|
||||||
|
'7': 61, // 2009
|
||||||
|
'Vista': 60, // 2007
|
||||||
|
'XP': 51, // 2001
|
||||||
|
'2K': 50, // 2000
|
||||||
|
};
|
||||||
|
// could also parse Cc["@mozilla.org/network/protocol;1?name=http"].
|
||||||
|
// getService(Ci.nsIHttpProtocolHandler).oscpu
|
||||||
|
this.WINVER = null; // initialized in kernel32.jsm
|
||||||
|
|
||||||
|
this.BOOL = ctypes.bool;
|
||||||
|
this.BYTE = ctypes.unsigned_char;
|
||||||
|
this.INT_PTR = is64bit ? ctypes.int64_t : ctypes.int;
|
||||||
|
this.UINT = ctypes.unsigned_int;
|
||||||
|
this.UINT_PTR = is64bit ? ctypes.uint64_t : ctypes.unsigned_int;
|
||||||
|
this.WORD = ctypes.unsigned_short;
|
||||||
|
this.DWORD = ctypes.unsigned_long;
|
||||||
|
this.LPDWORD = this.DWORD.ptr;
|
||||||
|
this.PVOID = ctypes.voidptr_t;
|
||||||
|
this.LPVOID = ctypes.voidptr_t;
|
||||||
|
this.LONG = ctypes.long;
|
||||||
|
this.LONG_PTR = is64bit ? ctypes.int64_t : ctypes.long;
|
||||||
|
this.ULONG_PTR = is64bit ? ctypes.uint64_t : ctypes.unsigned_long;
|
||||||
|
this.SIZE_T = this.ULONG_PTR;
|
||||||
|
this.DWORD_PTR = this.ULONG_PTR;
|
||||||
|
this.ATOM = this.WORD;
|
||||||
|
this.HANDLE = ctypes.voidptr_t;
|
||||||
|
this.HWND = this.HANDLE;
|
||||||
|
this.HICON = this.HANDLE;
|
||||||
|
this.HINSTANCE = this.HANDLE;
|
||||||
|
this.HMODULE = this.HANDLE;
|
||||||
|
this.HMENU = this.HANDLE;
|
||||||
|
this.HBRUSH = this.HICON;
|
||||||
|
this.HCURSOR = this.HANDLE;
|
||||||
|
this.HHOOK = this.HANDLE;
|
||||||
|
this.HDC = this.HANDLE;
|
||||||
|
this.HGDIOBJ = this.HANDLE;
|
||||||
|
this.HBITMAP = this.HANDLE;
|
||||||
|
this.HFONT = this.HANDLE;
|
||||||
|
this.TCHAR = ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t = jschar
|
||||||
|
this.LPSTR = ctypes.char.ptr;
|
||||||
|
this.LPCSTR = ctypes.char.ptr;
|
||||||
|
this.LPTSTR = ctypes.jschar.ptr; // UNICODE
|
||||||
|
this.LPCTSTR = ctypes.jschar.ptr;
|
||||||
|
this.LPCWSTR = ctypes.jschar.ptr;
|
||||||
|
this.LPWSTR = ctypes.jschar.ptr; // WCHAR
|
||||||
|
this.LRESULT = this.LONG_PTR;
|
||||||
|
this.WPARAM = this.UINT_PTR;
|
||||||
|
this.LPARAM = this.LONG_PTR;
|
||||||
|
this.FARPROC = ctypes.voidptr_t; // typedef INT_PTR (FAR WINAPI *FARPROC)();
|
||||||
|
this.COLORREF = this.DWORD; // 0x00bbggrr
|
||||||
|
|
||||||
|
this.GUID = ctypes.StructType("GUID", [
|
||||||
|
{ "Data1": ctypes.unsigned_long },
|
||||||
|
{ "Data2": ctypes.unsigned_short },
|
||||||
|
{ "Data3": ctypes.unsigned_short },
|
||||||
|
{ "Data4": ctypes.char.array(8) }
|
||||||
|
]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
|
||||||
|
* #define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
|
||||||
|
*/
|
||||||
|
this.MAKEINTRESOURCE = function(i) {return this.LPWSTR(i);};
|
||||||
|
|
||||||
|
this._T = function(str) {
|
||||||
|
return ctypes.jschar.array()(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
|
||||||
|
* #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
|
||||||
|
* #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||||
|
* #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||||
|
*/
|
||||||
|
this.LOWORD = function(l) {return l & 0x0000ffff;};
|
||||||
|
this.HIWORD = function(l) {return l >> 16;};
|
||||||
|
/* Although we shouldn't use LO-/HIWORD to get coords, because of negative
|
||||||
|
coords on multi-monitor displays, I'm not sure how to express the
|
||||||
|
GET_?_LPARAM macros with ctypes. */
|
||||||
|
this.GET_X_LPARAM = this.LOWORD;
|
||||||
|
this.GET_Y_LPARAM = this.HIWORD;
|
||||||
|
|
||||||
|
this.ERROR_INVALID_PARAMETER = 87;
|
||||||
|
this.ERROR_INVALID_WINDOW_HANDLE = 1400;
|
||||||
|
this.ERROR_RESOURCE_TYPE_NOT_FOUND = 1813;
|
||||||
|
|
||||||
|
// WinUser.h
|
||||||
|
this.WM_NULL = 0x0000;
|
||||||
|
this.WM_CREATE = 0x0001;
|
||||||
|
this.WM_DESTROY = 0x0002;
|
||||||
|
this.WM_MOVE = 0x0003;
|
||||||
|
this.WM_SIZE = 0x0005;
|
||||||
|
this.WM_ACTIVATE = 0x0006;
|
||||||
|
this.WA_INACTIVE = 0;
|
||||||
|
this.WA_ACTIVE = 1;
|
||||||
|
this.WA_CLICKACTIVE = 2;
|
||||||
|
this.WM_SETFOCUS = 0x0007;
|
||||||
|
this.WM_KILLFOCUS = 0x0008;
|
||||||
|
this.WM_ENABLE = 0x000A;
|
||||||
|
this.WM_SETREDRAW = 0x000B;
|
||||||
|
this.WM_SETTEXT = 0x000C;
|
||||||
|
this.WM_GETTEXT = 0x000D;
|
||||||
|
this.WM_GETTEXTLENGTH = 0x000E;
|
||||||
|
this.WM_PAINT = 0x000F;
|
||||||
|
this.WM_CLOSE = 0x0010;
|
||||||
|
this.WM_QUIT = 0x0012;
|
||||||
|
this.WM_ERASEBKGND = 0x0014;
|
||||||
|
this.WM_SYSCOLORCHANGE = 0x0015;
|
||||||
|
this.WM_SHOWWINDOW = 0x0018;
|
||||||
|
this.WM_WININICHANGE = 0x001A;
|
||||||
|
this.WM_SETTINGCHANGE = this.WM_WININICHANGE;
|
||||||
|
this.WM_DEVMODECHANGE = 0x001B;
|
||||||
|
this.WM_ACTIVATEAPP = 0x001C;
|
||||||
|
this.WM_FONTCHANGE = 0x001D;
|
||||||
|
this.WM_TIMECHANGE = 0x001E;
|
||||||
|
this.WM_CANCELMODE = 0x001F;
|
||||||
|
this.WM_SETCURSOR = 0x0020;
|
||||||
|
this.WM_MOUSEACTIVATE = 0x0021;
|
||||||
|
this.WM_CHILDACTIVATE = 0x0022;
|
||||||
|
this.WM_QUEUESYNC = 0x0023;
|
||||||
|
this.WM_COMMAND = 0x0111;
|
||||||
|
this.WM_SYSCOMMAND = 0x0112;
|
||||||
|
this.WM_HSCROLL = 0x0114;
|
||||||
|
this.WM_VSCROLL = 0x0115;
|
||||||
|
this.WM_MOUSEWHEEL = 0x020A;
|
||||||
|
|
||||||
|
this.WM_USER = 0x0400;
|
||||||
|
this.WM_APP = 0x8000;
|
||||||
|
|
||||||
|
this.WM_CONTEXTMENU = 0x007B;
|
||||||
|
|
||||||
|
this.WM_MOUSEFIRST = 0x0200;
|
||||||
|
this.WM_MOUSEMOVE = 0x0200;
|
||||||
|
this.WM_LBUTTONDOWN = 0x0201;
|
||||||
|
this.WM_LBUTTONUP = 0x0202;
|
||||||
|
this.WM_LBUTTONDBLCLK = 0x0203;
|
||||||
|
this.WM_RBUTTONDOWN = 0x0204;
|
||||||
|
this.WM_RBUTTONUP = 0x0205;
|
||||||
|
this.WM_RBUTTONDBLCLK = 0x0206;
|
||||||
|
this.WM_MBUTTONDOWN = 0x0207;
|
||||||
|
this.WM_MBUTTONUP = 0x0208;
|
||||||
|
this.WM_MBUTTONDBLCLK = 0x0209;
|
||||||
|
this.WM_MOUSEWHEEL = 0x020A;
|
||||||
|
this.WM_XBUTTONDOWN = 0x020B;
|
||||||
|
this.WM_XBUTTONUP = 0x020C;
|
||||||
|
this.WM_XBUTTONDBLCLK = 0x020D;
|
||||||
|
this.WM_MOUSELAST = 0x020D;
|
||||||
|
this.WM_MOUSELAST = 0x020A;
|
||||||
|
|
||||||
|
this.SC_MINIMIZE = 0xF020;
|
||||||
|
this.SC_CLOSE = 0xF060;
|
||||||
|
|
||||||
|
this.SIZE_RESTORED = 0;
|
||||||
|
this.SIZE_MINIMIZED = 1;
|
||||||
|
this.SIZE_MAXIMIZED = 2;
|
||||||
|
this.SIZE_MAXSHOW = 3;
|
||||||
|
this.SIZE_MAXHIDE = 4;
|
||||||
|
|
||||||
|
this.BITMAP = ctypes.StructType("BITMAP", [
|
||||||
|
{ "bmType": this.LONG },
|
||||||
|
{ "bmWidth": this.LONG },
|
||||||
|
{ "bmHeight": this.LONG },
|
||||||
|
{ "bmWidthBytes": this.LONG },
|
||||||
|
{ "bmPlanes": this.WORD },
|
||||||
|
{ "bmBitsPixel": this.WORD },
|
||||||
|
{ "bmBits": this.LPVOID }
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.ICONINFO = ctypes.StructType("ICONINFO", [
|
||||||
|
{ "fIcon": this.BOOL },
|
||||||
|
{ "xHotspot": this.DWORD },
|
||||||
|
{ "yHotspot": this.DWORD },
|
||||||
|
{ "hbmMask": this.HBITMAP },
|
||||||
|
{ "hbmColor": this.HBITMAP }
|
||||||
|
]);
|
||||||
|
this.PICONINFO = this.ICONINFO.ptr;
|
||||||
|
|
||||||
|
this.POINT = ctypes.StructType("POINT", [
|
||||||
|
{ "x": this.LONG },
|
||||||
|
{ "y": this.LONG }
|
||||||
|
]);
|
||||||
|
this.PPOINT = this.LPPOINT =this.POINT.ptr;
|
||||||
|
|
||||||
|
this.RECT = ctypes.StructType("RECT", [
|
||||||
|
{ "left": this.LONG },
|
||||||
|
{ "top": this.LONG },
|
||||||
|
{ "right": this.LONG },
|
||||||
|
{ "bottom": this.LONG }
|
||||||
|
]);
|
||||||
|
this.PRECT = this.RECT.ptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// ShellAPI.h
|
||||||
|
let nin_select = win32.WM_USER + 0;
|
||||||
|
win32.NIN_SELECT = nin_select;
|
||||||
|
win32.NINF_KEY = 0x1;
|
||||||
|
win32.NIN_KEYSELECT = (win32.NIN_SELECT | win32.NINF_KEY);
|
@ -24,7 +24,7 @@ firetray.Chat = {
|
|||||||
init: function() {
|
init: function() {
|
||||||
if (this.initialized) {
|
if (this.initialized) {
|
||||||
log.warn("Chat already initialized");
|
log.warn("Chat already initialized");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
log.debug("Enabling Chat");
|
log.debug("Enabling Chat");
|
||||||
|
|
||||||
@ -42,10 +42,11 @@ firetray.Chat = {
|
|||||||
this.updateIcon();
|
this.updateIcon();
|
||||||
|
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
shutdown: function() {
|
shutdown: function() {
|
||||||
if (!this.initialized) return;
|
if (!this.initialized) return false;
|
||||||
log.debug("Disabling Chat");
|
log.debug("Disabling Chat");
|
||||||
|
|
||||||
if (firetray.Chat.convsToAcknowledge.length())
|
if (firetray.Chat.convsToAcknowledge.length())
|
||||||
@ -55,6 +56,7 @@ firetray.Chat = {
|
|||||||
firetray.Utils.removeAllObservers(firetray.Chat);
|
firetray.Utils.removeAllObservers(firetray.Chat);
|
||||||
|
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
// FIXME: the listener should probably attached on the conv entry in the
|
// FIXME: the listener should probably attached on the conv entry in the
|
@ -204,7 +204,6 @@ firetray.ChatStatusIcon = {
|
|||||||
{ notify: firetray.ChatStatusIcon.fadeStep },
|
{ notify: firetray.ChatStatusIcon.fadeStep },
|
||||||
ALPHA_STEP_SLEEP_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
|
ALPHA_STEP_SLEEP_MILLISECONDS, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||||
|
|
||||||
|
|
||||||
} catch (e if e instanceof StopIteration) {
|
} catch (e if e instanceof StopIteration) {
|
||||||
|
|
||||||
if (firetray.ChatStatusIcon.events['stop-fade']) {
|
if (firetray.ChatStatusIcon.events['stop-fade']) {
|
||||||
|
@ -172,8 +172,7 @@ firetray.PopupMenu = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
hideWindowItemAndSeparatorMaybe: function(xid) {
|
hideWindowItemAndSeparatorMaybe: function(xid) {
|
||||||
if (!this.windowItemsHandled())
|
if (!this.windowItemsHandled()) return;
|
||||||
return;
|
|
||||||
|
|
||||||
this.hideWindowItem(xid);
|
this.hideWindowItem(xid);
|
||||||
if (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount)
|
if (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount)
|
||||||
@ -212,4 +211,5 @@ firetray.PopupMenu = {
|
|||||||
|
|
||||||
}; // firetray.PopupMenu
|
}; // firetray.PopupMenu
|
||||||
|
|
||||||
firetray.Handler.showHidePopupMenuItems = firetray.PopupMenu.showHideWindowItems;
|
firetray.Handler.showHidePopupMenuItems =
|
||||||
|
firetray.PopupMenu.showHideWindowItems.bind(firetray.PopupMenu);
|
||||||
|
@ -97,6 +97,8 @@ firetray.StatusIcon = {
|
|||||||
this.themedIconApp = this.initThemedIcon(appIconNames);
|
this.themedIconApp = this.initThemedIcon(appIconNames);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadImageCustom: function() { }, // done in setIconImageCustom
|
||||||
|
|
||||||
getAppIconNames: function() {
|
getAppIconNames: function() {
|
||||||
let appIconNames = firetray.Utils.getArrayPref(this.prefAppIconNames);
|
let appIconNames = firetray.Utils.getArrayPref(this.prefAppIconNames);
|
||||||
appIconNames.push(this.defaultAppIconName);
|
appIconNames.push(this.defaultAppIconName);
|
||||||
@ -135,7 +137,7 @@ firetray.StatusIcon = {
|
|||||||
|
|
||||||
log.debug("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows"));
|
log.debug("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows"));
|
||||||
this.callbacks.iconActivate = gtk.GCallbackStatusIconActivate_t(
|
this.callbacks.iconActivate = gtk.GCallbackStatusIconActivate_t(
|
||||||
firetray.Handler.showHideAllWindows);
|
firetray.StatusIcon.onClick);
|
||||||
let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon,
|
let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon,
|
||||||
"activate", firetray.StatusIcon.callbacks.iconActivate, null);
|
"activate", firetray.StatusIcon.callbacks.iconActivate, null);
|
||||||
log.debug("g_connect activate="+handlerId);
|
log.debug("g_connect activate="+handlerId);
|
||||||
@ -176,12 +178,18 @@ firetray.StatusIcon = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onClick: function(gtkStatusIcon, userData) {
|
||||||
|
firetray.Handler.showHideAllWindows();
|
||||||
|
let stopPropagation = true;
|
||||||
|
return stopPropagation;
|
||||||
|
},
|
||||||
|
|
||||||
setIconImageFromFile: function(filename) {
|
setIconImageFromFile: function(filename) {
|
||||||
if (!firetray.StatusIcon.trayIcon)
|
if (!firetray.StatusIcon.trayIcon)
|
||||||
log.error("Icon missing");
|
log.error("Icon missing");
|
||||||
log.debug(filename);
|
log.debug(filename);
|
||||||
gtk.gtk_status_icon_set_from_file(firetray.StatusIcon.trayIcon,
|
gtk.gtk_status_icon_set_from_file(firetray.StatusIcon.trayIcon,
|
||||||
filename);
|
filename);
|
||||||
},
|
},
|
||||||
|
|
||||||
setIconImageFromGIcon: function(gicon) {
|
setIconImageFromGIcon: function(gicon) {
|
||||||
@ -200,17 +208,18 @@ firetray.Handler.setIconImageDefault = function() {
|
|||||||
let appIconType = firetray.Utils.prefService.getIntPref("app_icon_type");
|
let appIconType = firetray.Utils.prefService.getIntPref("app_icon_type");
|
||||||
if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_THEMED)
|
if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_THEMED)
|
||||||
firetray.StatusIcon.setIconImageFromGIcon(firetray.StatusIcon.themedIconApp);
|
firetray.StatusIcon.setIconImageFromGIcon(firetray.StatusIcon.themedIconApp);
|
||||||
else if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM) {
|
else if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM)
|
||||||
let appIconFilename = firetray.Utils.prefService.getCharPref("app_icon_filename");
|
firetray.Handler.setIconImageCustom("app_icon_custom");
|
||||||
firetray.StatusIcon.setIconImageFromFile(appIconFilename);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
firetray.Handler.setIconImageNewMail = function() {
|
firetray.Handler.setIconImageNewMail = function() {
|
||||||
firetray.StatusIcon.setIconImageFromGIcon(firetray.StatusIcon.themedIconNewMail);
|
firetray.StatusIcon.setIconImageFromGIcon(firetray.StatusIcon.themedIconNewMail);
|
||||||
};
|
};
|
||||||
|
|
||||||
firetray.Handler.setIconImageFromFile = firetray.StatusIcon.setIconImageFromFile;
|
firetray.Handler.setIconImageCustom = function(prefname) {
|
||||||
|
let prefCustomIconPath = firetray.Utils.prefService.getCharPref(prefname);
|
||||||
|
firetray.StatusIcon.setIconImageFromFile(prefCustomIconPath);
|
||||||
|
};
|
||||||
|
|
||||||
// GTK bug: Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
|
// GTK bug: Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
|
||||||
firetray.Handler.setIconTooltip = function(toolTipStr) {
|
firetray.Handler.setIconTooltip = function(toolTipStr) {
|
||||||
|
@ -6,7 +6,9 @@ const Cc = Components.classes;
|
|||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
|
|
||||||
const FIRETRAY_LOG_LEVEL = "Warn"; // "All" for debugging
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
const FIRETRAY_LOG_LEVEL = "All"; // "All" for debugging
|
||||||
|
|
||||||
const COLOR_NORMAL = "";
|
const COLOR_NORMAL = "";
|
||||||
const COLOR_RESET = "\033[m";
|
const COLOR_RESET = "\033[m";
|
||||||
@ -45,6 +47,7 @@ var colorTermLogColors = {
|
|||||||
if ("undefined" == typeof(firetray)) {
|
if ("undefined" == typeof(firetray)) {
|
||||||
var firetray = {};
|
var firetray = {};
|
||||||
};
|
};
|
||||||
|
var LogMod;
|
||||||
|
|
||||||
// https://wiki.mozilla.org/Labs/JS_Modules#Logging
|
// https://wiki.mozilla.org/Labs/JS_Modules#Logging
|
||||||
firetray.Logging = {
|
firetray.Logging = {
|
||||||
@ -53,17 +56,22 @@ firetray.Logging = {
|
|||||||
init: function() {
|
init: function() {
|
||||||
if (this.initialized) return;
|
if (this.initialized) return;
|
||||||
|
|
||||||
["resource://services-common/log4moz.js", // FF
|
["resource://gre/modules/Log.jsm", // FF 27+
|
||||||
"resource:///app/modules/gloda/log4moz.js", // TB
|
"resource://services-common/log4moz.js", // FF
|
||||||
"resource://firetray/log4moz.js"] // default
|
"resource:///app/modules/gloda/log4moz.js", // TB
|
||||||
|
"resource://firetray/log4moz.js"] // default
|
||||||
.forEach(function(file){
|
.forEach(function(file){
|
||||||
try {Cu.import(file);} catch(x) {}
|
try {Cu.import(file);} catch(x) {}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if ("undefined" == typeof(Log4Moz)) {
|
if ("undefined" != typeof(Log)) {
|
||||||
let errMsg = "log4moz.js not found";
|
LogMod = Log;
|
||||||
|
} else if ("undefined" != typeof(Log4Moz)) {
|
||||||
|
LogMod = Log4Moz;
|
||||||
|
} else {
|
||||||
|
let errMsg = "Log module not found";
|
||||||
dump(errMsg+"\n");
|
dump(errMsg+"\n");
|
||||||
Cu.ReportError(errMsg);
|
Cu.reportError(errMsg);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setupLogging("firetray");
|
this.setupLogging("firetray");
|
||||||
@ -77,24 +85,9 @@ firetray.Logging = {
|
|||||||
setupLogging: function(loggerName) {
|
setupLogging: function(loggerName) {
|
||||||
|
|
||||||
// lifted from log4moz.js
|
// lifted from log4moz.js
|
||||||
function SimpleFormatter(dateFormat) {
|
function SimpleFormatter() {}
|
||||||
if (dateFormat)
|
|
||||||
this.dateFormat = dateFormat;
|
|
||||||
}
|
|
||||||
SimpleFormatter.prototype = {
|
SimpleFormatter.prototype = {
|
||||||
__proto__: Log4Moz.Formatter.prototype,
|
__proto__: LogMod.Formatter.prototype,
|
||||||
|
|
||||||
_dateFormat: null,
|
|
||||||
|
|
||||||
get dateFormat() {
|
|
||||||
if (!this._dateFormat)
|
|
||||||
this._dateFormat = "%Y-%m-%d %H:%M:%S";
|
|
||||||
return this._dateFormat;
|
|
||||||
},
|
|
||||||
|
|
||||||
set dateFormat(format) {
|
|
||||||
this._dateFormat = format;
|
|
||||||
},
|
|
||||||
|
|
||||||
format: function(message) {
|
format: function(message) {
|
||||||
let messageString = "";
|
let messageString = "";
|
||||||
@ -108,7 +101,9 @@ firetray.Logging = {
|
|||||||
([,mo] in Iterator(message.messageObjects))].join(" ");
|
([,mo] in Iterator(message.messageObjects))].join(" ");
|
||||||
|
|
||||||
let date = new Date(message.time);
|
let date = new Date(message.time);
|
||||||
let stringLog = date.toLocaleFormat(this.dateFormat) + " " +
|
let dateStr = date.getHours() + ":" + date.getMinutes() + ":" +
|
||||||
|
date.getSeconds() + "." + date.getMilliseconds();
|
||||||
|
let stringLog = dateStr + " " +
|
||||||
message.levelDesc + " " + message.loggerName + " " +
|
message.levelDesc + " " + message.loggerName + " " +
|
||||||
messageString + "\n";
|
messageString + "\n";
|
||||||
|
|
||||||
@ -119,10 +114,7 @@ firetray.Logging = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function ColorTermFormatter(dateFormat) {
|
function ColorTermFormatter() {}
|
||||||
if (dateFormat)
|
|
||||||
this.dateFormat = dateFormat;
|
|
||||||
}
|
|
||||||
ColorTermFormatter.prototype = {
|
ColorTermFormatter.prototype = {
|
||||||
__proto__: SimpleFormatter.prototype,
|
__proto__: SimpleFormatter.prototype,
|
||||||
|
|
||||||
@ -136,26 +128,30 @@ firetray.Logging = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Loggers are hierarchical, affiliation is handled by a '.' in the name.
|
// Loggers are hierarchical, affiliation is handled by a '.' in the name.
|
||||||
this._logger = Log4Moz.repository.getLogger(loggerName);
|
this._logger = LogMod.repository.getLogger(loggerName);
|
||||||
// Lowering this log level will affect all of our addon output
|
// Lowering this log level will affect all of our addon output
|
||||||
this._logger.level = Log4Moz.Level[FIRETRAY_LOG_LEVEL];
|
this._logger.level = LogMod.Level[FIRETRAY_LOG_LEVEL];
|
||||||
|
|
||||||
// A console appender outputs to the JS Error Console
|
// A console appender outputs to the JS Error Console
|
||||||
let dateFormat = "%T";
|
let simpleFormatter = new SimpleFormatter();
|
||||||
let simpleFormatter = new SimpleFormatter(dateFormat);
|
let capp = new LogMod.ConsoleAppender(simpleFormatter);
|
||||||
let capp = new Log4Moz.ConsoleAppender(simpleFormatter);
|
capp.level = LogMod.Level["Debug"];
|
||||||
capp.level = Log4Moz.Level["Debug"];
|
|
||||||
this._logger.addAppender(capp);
|
this._logger.addAppender(capp);
|
||||||
|
|
||||||
// A dump appender outputs to standard out
|
// A dump appender outputs to standard out
|
||||||
let colorFormatter = new ColorTermFormatter(dateFormat);
|
let dumpFormatter;
|
||||||
let dapp = new Log4Moz.DumpAppender(colorFormatter);
|
if (Services.appinfo.OS.match(/(^Linux|^Darwin|BSD$)/)) {
|
||||||
dapp.level = Log4Moz.Level["Debug"];
|
dumpFormatter = new ColorTermFormatter();
|
||||||
|
} else {
|
||||||
|
dumpFormatter = new SimpleFormatter();
|
||||||
|
}
|
||||||
|
let dapp = new LogMod.DumpAppender(dumpFormatter);
|
||||||
|
dapp.level = LogMod.Level["Debug"];
|
||||||
this._logger.addAppender(dapp);
|
this._logger.addAppender(dapp);
|
||||||
},
|
},
|
||||||
|
|
||||||
getLogger: function(loggerName){
|
getLogger: function(loggerName){
|
||||||
return Log4Moz.repository.getLogger(loggerName);
|
return LogMod.repository.getLogger(loggerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // firetray.Logging
|
}; // firetray.Logging
|
||||||
|
160
src/modules/winnt/FiretrayPopupMenu.jsm
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/* -*- 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/winnt/win32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
||||||
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
firetray.Handler.subscribeLibsForClosing([user32]);
|
||||||
|
|
||||||
|
let log = firetray.Logging.getLogger("firetray.PopupMenu");
|
||||||
|
|
||||||
|
if ("undefined" == typeof(firetray.StatusIcon))
|
||||||
|
log.error("This module MUST be imported from/after StatusIcon !");
|
||||||
|
|
||||||
|
// popupmenu items
|
||||||
|
const IDM_PREF = 100;
|
||||||
|
const IDM_QUIT = 200;
|
||||||
|
const IDM_NEW_MSG = 300;
|
||||||
|
const IDM_NEW_WND = 400;
|
||||||
|
const IDM_RESET = 500;
|
||||||
|
|
||||||
|
|
||||||
|
firetray.PopupMenu = {
|
||||||
|
initialized: false,
|
||||||
|
menu: null,
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this.create();
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
shutdown: function() {
|
||||||
|
this.destroy();
|
||||||
|
|
||||||
|
log.debug("Disabling PopupMenu");
|
||||||
|
this.initialized = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
create: function() {
|
||||||
|
this.menu = user32.CreatePopupMenu();
|
||||||
|
log.debug("menu="+this.menu);
|
||||||
|
|
||||||
|
this.insertMenuItem('Quit', 'quit', IDM_QUIT);
|
||||||
|
this.insertSeparator();
|
||||||
|
this.insertMenuItem('Preferences', 'prefs', IDM_PREF);
|
||||||
|
|
||||||
|
let menuSeparatorAdded = false;
|
||||||
|
if (firetray.Handler.inBrowserApp) {
|
||||||
|
this.insertSeparator();
|
||||||
|
menuSeparatorAdded = true;
|
||||||
|
this.insertMenuItem('NewWindow', 'new-wnd', IDM_NEW_WND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firetray.Handler.inMailApp) {
|
||||||
|
if (!menuSeparatorAdded) {
|
||||||
|
this.insertSeparator();
|
||||||
|
}
|
||||||
|
this.insertMenuItem('NewMessage', 'new-msg', IDM_NEW_MSG);
|
||||||
|
this.insertMenuItem('ResetIcon', 'reset', IDM_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("PopupMenu created");
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
user32.DestroyMenu(this.menu);
|
||||||
|
log.debug("PopupMenu destroyed");
|
||||||
|
},
|
||||||
|
|
||||||
|
insertMenuItem: function(itemName, iconName, actionId) {
|
||||||
|
var menuItemLabel = firetray.Utils.strings.GetStringFromName("popupMenu.itemLabel."+itemName);
|
||||||
|
let mii = new user32.MENUITEMINFOW();
|
||||||
|
// BUG: ctypes doesn't detect wrong field assignments mii.size = ... ('size' undefined)
|
||||||
|
mii.cbSize = user32.MENUITEMINFOW.size;
|
||||||
|
mii.fMask = user32.MIIM_ID | user32.MIIM_STRING | user32.MIIM_DATA;
|
||||||
|
mii.wID = actionId;
|
||||||
|
// mii.dwItemData = win32.ULONG_PTR(actionId);
|
||||||
|
mii.dwTypeData = win32._T(menuItemLabel);
|
||||||
|
/* Under XP, putting a bitmap into hbmpItem results in ugly icons. We
|
||||||
|
should probably use HBMMENU_CALLBACK as explained in
|
||||||
|
http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution.
|
||||||
|
But for now, we just don't display icons in XP-. */
|
||||||
|
if (win32.WINVER >= win32.WIN_VERSIONS["Vista"]) {
|
||||||
|
mii.fMask |= user32.MIIM_BITMAP;
|
||||||
|
mii.hbmpItem = firetray.StatusIcon.bitmaps.get(iconName);
|
||||||
|
}
|
||||||
|
log.debug("mii="+mii);
|
||||||
|
if (!user32.InsertMenuItemW(this.menu, 0, true, mii.address())) {
|
||||||
|
log.error("InsertMenuItemW failed winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
insertSeparator: function() {
|
||||||
|
user32.InsertMenuW(this.menu, 0, user32.MF_BYPOSITION|user32.MF_SEPARATOR,
|
||||||
|
0, null);
|
||||||
|
},
|
||||||
|
|
||||||
|
// FIXME: need to handle hides_single_window=false
|
||||||
|
addWindowItemAndSeparatorMaybe: function(wid) {
|
||||||
|
if (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount)
|
||||||
|
this.insertSeparator();
|
||||||
|
this.addWindowItem(wid);
|
||||||
|
},
|
||||||
|
removeWindowItemAndSeparatorMaybe: function(wid) {
|
||||||
|
this.removeWindowItem(wid);
|
||||||
|
if (firetray.Handler.visibleWindowsCount === firetray.Handler.windowsCount - 1)
|
||||||
|
user32.DeleteMenu(this.menu, 0, user32.MF_BYPOSITION);
|
||||||
|
},
|
||||||
|
|
||||||
|
addWindowItem: function(wid) {
|
||||||
|
let title = firetray.Window.getWindowTitle(wid);
|
||||||
|
let mii = new user32.MENUITEMINFOW();
|
||||||
|
mii.cbSize = user32.MENUITEMINFOW.size;
|
||||||
|
mii.fMask = user32.MIIM_ID | user32.MIIM_STRING | user32.MIIM_DATA;
|
||||||
|
mii.wID = ctypes.UInt64(wid);
|
||||||
|
mii.dwTypeData = win32._T(title);
|
||||||
|
if (!user32.InsertMenuItemW(this.menu, 0, true, mii.address())) {
|
||||||
|
log.error("InsertMenuItemW failed winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeWindowItem: function(wid) {
|
||||||
|
let itemId = ctypes.UInt64(wid);
|
||||||
|
if (!user32.DeleteMenu(this.menu, itemId, user32.MF_BYCOMMAND)) {
|
||||||
|
log.error("DeleteMenu failed winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
processMenuItem: function(itemId) {
|
||||||
|
let wid = firetray.Win32.hwndToHexStr(win32.HWND(itemId));
|
||||||
|
if (firetray.Handler.windows[wid]) {
|
||||||
|
firetray.Handler.showWindow(wid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (itemId) {
|
||||||
|
case IDM_PREF: firetray.Handler.openPrefWindow(); break;
|
||||||
|
case IDM_QUIT: firetray.Handler.quitApplication(); break;
|
||||||
|
case IDM_NEW_MSG: firetray.Handler.openMailMessage(); break;
|
||||||
|
case IDM_NEW_WND: firetray.Handler.openBrowserWindow(); break;
|
||||||
|
case IDM_RESET: firetray.Handler.setIconImageDefault(); break;
|
||||||
|
default:
|
||||||
|
log.error("no action for itemId ("+itemId+")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // firetray.PopupMenu
|
||||||
|
|
||||||
|
firetray.Handler.addPopupMenuWindowItemAndSeparatorMaybe =
|
||||||
|
firetray.PopupMenu.addWindowItemAndSeparatorMaybe.bind(firetray.PopupMenu);
|
||||||
|
firetray.Handler.removePopupMenuWindowItemAndSeparatorMaybe =
|
||||||
|
firetray.PopupMenu.removeWindowItemAndSeparatorMaybe.bind(firetray.PopupMenu);
|
467
src/modules/winnt/FiretrayStatusIcon.jsm
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
|
||||||
|
/* The tray icon for the main app. We need a hidden proxy window as (1) we want
|
||||||
|
a unique icon, (2) the icon sends notifications to a single window. */
|
||||||
|
|
||||||
|
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/ctypesMap.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/gdi32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/kernel32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/shell32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
||||||
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||||
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
firetray.Handler.subscribeLibsForClosing([gdi32, kernel32, shell32, user32]);
|
||||||
|
|
||||||
|
let log = firetray.Logging.getLogger("firetray.StatusIcon");
|
||||||
|
|
||||||
|
if ("undefined" == typeof(firetray.Handler))
|
||||||
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||||
|
|
||||||
|
const ICON_CHROME_PATHS = {
|
||||||
|
'blank-icon': "chrome://firetray/skin/winnt/blank-icon.bmp",
|
||||||
|
'mail-unread': "chrome://firetray/skin/winnt/mail-unread.ico",
|
||||||
|
// these are for the popup menu:
|
||||||
|
'prefs': "chrome://firetray/skin/winnt/gtk-preferences.bmp",
|
||||||
|
'quit': "chrome://firetray/skin/winnt/application-exit.bmp",
|
||||||
|
'new-wnd': "chrome://firetray/skin/winnt/document-new.bmp",
|
||||||
|
'new-msg': "chrome://firetray/skin/winnt/gtk-edit.bmp",
|
||||||
|
'reset': "chrome://firetray/skin/winnt/gtk-apply.bmp"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
firetray.StatusIcon = {
|
||||||
|
initialized: false,
|
||||||
|
callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
|
||||||
|
notifyIconData: null,
|
||||||
|
hwndProxy: null,
|
||||||
|
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
|
||||||
|
WNDCLASS_ATOM: null,
|
||||||
|
icons: (function(){return new ctypesMap(win32.HICON);})(),
|
||||||
|
bitmaps: (function(){return new ctypesMap(win32.HBITMAP);})(),
|
||||||
|
IMG_TYPES: {
|
||||||
|
ico: { win_t: win32.HICON, load_const: user32.IMAGE_ICON, map: 'icons' },
|
||||||
|
bmp: { win_t: win32.HBITMAP, load_const: user32.IMAGE_BITMAP, map: 'bitmaps' }
|
||||||
|
},
|
||||||
|
PREF_TO_ICON_NAME: {
|
||||||
|
app_icon_custom: 'app-custom',
|
||||||
|
mail_icon_custom: 'mail-custom'
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this.loadImages();
|
||||||
|
this.create();
|
||||||
|
firetray.Handler.setIconImageDefault();
|
||||||
|
|
||||||
|
Cu.import("resource://firetray/winnt/FiretrayPopupMenu.jsm");
|
||||||
|
if (!firetray.PopupMenu.init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.initialized = true;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
shutdown: function() {
|
||||||
|
log.debug("Disabling StatusIcon");
|
||||||
|
firetray.PopupMenu.shutdown();
|
||||||
|
|
||||||
|
this.destroy();
|
||||||
|
this.destroyImages();
|
||||||
|
|
||||||
|
this.initialized = false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
loadThemedIcons: function() { },
|
||||||
|
|
||||||
|
loadImages: function() {
|
||||||
|
// the Mozilla hidden window has the default Mozilla icon
|
||||||
|
let hwnd_hidden_moz = user32.FindWindowW("MozillaHiddenWindowClass", null);
|
||||||
|
log.debug("=== hwnd_hidden_moz="+hwnd_hidden_moz);
|
||||||
|
this.icons.insert('app', this.getIconFromWindow(hwnd_hidden_moz));
|
||||||
|
['app_icon_custom', 'mail_icon_custom'].forEach(function(elt) {
|
||||||
|
firetray.StatusIcon.loadImageCustom(elt);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* we'll take the first icon in the .ico file. To get the icon count in the
|
||||||
|
file, pass ctypes.cast(ctypes.int(-1), win32.UINT); */
|
||||||
|
for (let imgName in ICON_CHROME_PATHS) {
|
||||||
|
let path = firetray.Utils.chromeToPath(ICON_CHROME_PATHS[imgName]);
|
||||||
|
let img = this.loadImageFromFile(path);
|
||||||
|
if (img)
|
||||||
|
this[this.IMG_TYPES[img['type']]['map']].insert(imgName, img['himg']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loadImageCustom: function(prefname) {
|
||||||
|
log.debug("loadImageCustom pref="+prefname);
|
||||||
|
let filename = firetray.Utils.prefService.getCharPref(prefname);
|
||||||
|
if (!filename) return;
|
||||||
|
let img = this.loadImageFromFile(filename);
|
||||||
|
if (!img) return;
|
||||||
|
|
||||||
|
log.debug("loadImageCustom img type="+img['type']+" himg="+img['himg']);
|
||||||
|
let hicon = img['himg'];
|
||||||
|
if (img['type'] === 'bmp')
|
||||||
|
hicon = this.HBITMAPToHICON(img['himg']);
|
||||||
|
let name = this.PREF_TO_ICON_NAME[prefname];
|
||||||
|
log.debug(" name="+name);
|
||||||
|
this.icons.insert(name, hicon);
|
||||||
|
},
|
||||||
|
|
||||||
|
loadImageFromFile: function(path) {
|
||||||
|
let imgType = path.substr(-3, 3).toLowerCase();
|
||||||
|
if (!(imgType in this.IMG_TYPES)) {
|
||||||
|
throw Error("Unrecognized type '"+imgType+"'");
|
||||||
|
}
|
||||||
|
let imgTypeRec = this.IMG_TYPES[imgType];
|
||||||
|
let himg = ctypes.cast(
|
||||||
|
user32.LoadImageW(null, path, imgTypeRec['load_const'], 0, 0,
|
||||||
|
user32.LR_LOADFROMFILE|user32.LR_SHARED),
|
||||||
|
imgTypeRec['win_t']);
|
||||||
|
if (himg.isNull()) {
|
||||||
|
log.error("Could not load '"+path+"'="+himg+" winLastError="+ctypes.winLastError);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {type:imgType, himg:himg};
|
||||||
|
},
|
||||||
|
|
||||||
|
HBITMAPToHICON: function(hBitmap) {
|
||||||
|
log.debug("HBITMAPToHICON hBitmap="+hBitmap);
|
||||||
|
let hWnd = null; // firetray.StatusIcon.hwndProxy;
|
||||||
|
let hdc = user32.GetDC(hWnd);
|
||||||
|
let bitmap = new win32.BITMAP();
|
||||||
|
let err = gdi32.GetObjectW(hBitmap, win32.BITMAP.size, bitmap.address()); // get bitmap info
|
||||||
|
let hBitmapMask = gdi32.CreateCompatibleBitmap(hdc, bitmap.bmWidth, bitmap.bmHeight);
|
||||||
|
user32.ReleaseDC(hWnd, hdc);
|
||||||
|
|
||||||
|
let iconInfo = win32.ICONINFO();
|
||||||
|
iconInfo.fIcon = true;
|
||||||
|
iconInfo.xHotspot = 0;
|
||||||
|
iconInfo.yHotspot = 0;
|
||||||
|
iconInfo.hbmMask = hBitmapMask;
|
||||||
|
iconInfo.hbmColor = hBitmap;
|
||||||
|
|
||||||
|
let hIcon = user32.CreateIconIndirect(iconInfo.address());
|
||||||
|
log.debug(" CreateIconIndirect hIcon="+hIcon+" lastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
gdi32.DeleteObject(hBitmap);
|
||||||
|
gdi32.DeleteObject(hBitmapMask);
|
||||||
|
|
||||||
|
return hIcon;
|
||||||
|
},
|
||||||
|
|
||||||
|
// images loaded with LR_SHARED need't be destroyed
|
||||||
|
destroyImages: function() {
|
||||||
|
[this.icons, this.bitmaps].forEach(function(map, idx, ary) {
|
||||||
|
let keys = map.keys;
|
||||||
|
for (let i=0, len=keys.length; i<len; ++i) {
|
||||||
|
let imgName = keys[i];
|
||||||
|
map.remove(imgName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
log.debug("Icons destroyed");
|
||||||
|
},
|
||||||
|
|
||||||
|
create: function() {
|
||||||
|
let hwnd_hidden = this.createProxyWindow();
|
||||||
|
|
||||||
|
nid = new shell32.NOTIFYICONDATAW();
|
||||||
|
nid.cbSize = shell32.NOTIFYICONDATAW_SIZE();
|
||||||
|
log.debug("SIZE="+nid.cbSize);
|
||||||
|
nid.szTip = firetray.Handler.appName;
|
||||||
|
nid.hIcon = this.icons.get('app');
|
||||||
|
nid.hWnd = hwnd_hidden;
|
||||||
|
nid.uCallbackMessage = firetray.Win32.WM_TRAYMESSAGE;
|
||||||
|
nid.uFlags = shell32.NIF_ICON | shell32.NIF_MESSAGE | shell32.NIF_TIP;
|
||||||
|
nid.uVersion = shell32.NOTIFYICON_VERSION_4;
|
||||||
|
|
||||||
|
// Install the icon
|
||||||
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_ADD, nid.address());
|
||||||
|
log.debug("Shell_NotifyIcon ADD="+rv+" winLastError="+ctypes.winLastError); // ERROR_INVALID_WINDOW_HANDLE(1400)
|
||||||
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_SETVERSION, nid.address());
|
||||||
|
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
this.notifyIconData = nid;
|
||||||
|
this.hwndProxy = hwnd_hidden;
|
||||||
|
},
|
||||||
|
|
||||||
|
createProxyWindow: function() {
|
||||||
|
this.registerWindowClass();
|
||||||
|
|
||||||
|
let hwnd_hidden = user32.CreateWindowExW(
|
||||||
|
0, win32.LPCTSTR(this.WNDCLASS_ATOM), // lpClassName can also be _T(WNDCLASS_NAME)
|
||||||
|
"Firetray Message Window", 0,
|
||||||
|
user32.CW_USEDEFAULT, user32.CW_USEDEFAULT, user32.CW_USEDEFAULT, user32.CW_USEDEFAULT,
|
||||||
|
null, null, firetray.Win32.hInstance, null);
|
||||||
|
log.debug("CreateWindow="+!hwnd_hidden.isNull()+" winLastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
this.callbacks.proxyWndProc = user32.WNDPROC(firetray.StatusIcon.proxyWndProc);
|
||||||
|
let procPrev = user32.SetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC,
|
||||||
|
ctypes.cast(this.callbacks.proxyWndProc, win32.LONG_PTR));
|
||||||
|
log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
firetray.Win32.acceptAllMessages(hwnd_hidden);
|
||||||
|
|
||||||
|
return hwnd_hidden;
|
||||||
|
},
|
||||||
|
|
||||||
|
registerWindowClass: function() {
|
||||||
|
let wndClass = new user32.WNDCLASSEXW();
|
||||||
|
wndClass.cbSize = user32.WNDCLASSEXW.size;
|
||||||
|
wndClass.lpfnWndProc = ctypes.cast(user32.DefWindowProcW, user32.WNDPROC);
|
||||||
|
wndClass.hInstance = firetray.Win32.hInstance;
|
||||||
|
wndClass.lpszClassName = win32._T(this.WNDCLASS_NAME);
|
||||||
|
this.WNDCLASS_ATOM = user32.RegisterClassExW(wndClass.address());
|
||||||
|
log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM);
|
||||||
|
},
|
||||||
|
|
||||||
|
proxyWndProc: function(hWnd, uMsg, wParam, lParam) {
|
||||||
|
// log.debug("ProxyWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
||||||
|
|
||||||
|
// FIXME: WM_TASKBARCREATED is needed in case of explorer crash
|
||||||
|
// http://twigstechtips.blogspot.fr/2011/02/c-detect-when-windows-explorer-has.html
|
||||||
|
if (uMsg === firetray.Win32.WM_TASKBARCREATED) {
|
||||||
|
log.info("____________TASKBARCREATED");
|
||||||
|
|
||||||
|
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
||||||
|
|
||||||
|
switch (win32.LOWORD(lParam)) {
|
||||||
|
case win32.WM_LBUTTONUP:
|
||||||
|
log.debug("WM_LBUTTONUP");
|
||||||
|
firetray.Handler.showHideAllWindows();
|
||||||
|
break;
|
||||||
|
case win32.WM_RBUTTONUP:
|
||||||
|
log.debug("WM_RBUTTONUP");
|
||||||
|
case win32.WM_CONTEXTMENU:
|
||||||
|
log.debug("WM_CONTEXTMENU");
|
||||||
|
/* Can't determine tray icon position precisely: the mouse cursor can
|
||||||
|
move between WM_RBUTTONDOWN and WM_RBUTTONUP, or the icon can have
|
||||||
|
been moved inside the notification area... so we opt for the easy
|
||||||
|
solution. */
|
||||||
|
let pos = user32.GetMessagePos();
|
||||||
|
let xPos = win32.GET_X_LPARAM(pos), yPos = win32.GET_Y_LPARAM(pos);
|
||||||
|
log.debug(" x="+xPos+" y="+yPos);
|
||||||
|
user32.SetForegroundWindow(hWnd);
|
||||||
|
user32.TrackPopupMenu(firetray.PopupMenu.menu, user32.TPM_RIGHTALIGN|user32.TPM_BOTTOMALIGN, xPos, yPos, 0, hWnd, null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
switch (uMsg) {
|
||||||
|
case win32.WM_SYSCOMMAND:
|
||||||
|
log.debug("WM_SYSCOMMAND wParam="+wParam+", lParam="+lParam);
|
||||||
|
break;
|
||||||
|
case win32.WM_COMMAND:
|
||||||
|
log.debug("WM_COMMAND wParam="+wParam+", lParam="+lParam);
|
||||||
|
firetray.PopupMenu.processMenuItem(wParam);
|
||||||
|
break;
|
||||||
|
case win32.WM_MENUCOMMAND:
|
||||||
|
log.debug("WM_MENUCOMMAND wParam="+wParam+", lParam="+lParam);
|
||||||
|
break;
|
||||||
|
case win32.WM_MENUCHAR:
|
||||||
|
log.debug("WM_MENUCHAR wParam="+wParam+", lParam="+lParam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIconFromWindow: function(hwnd) {
|
||||||
|
let rv = user32.SendMessageW(hwnd, user32.WM_GETICON, user32.ICON_SMALL, 0);
|
||||||
|
log.debug("SendMessageW winLastError="+ctypes.winLastError);
|
||||||
|
// result is a ctypes.Int64. So we need to create a CData from it before
|
||||||
|
// casting it to a HICON.
|
||||||
|
let icon = ctypes.cast(win32.LRESULT(rv), win32.HICON);
|
||||||
|
if (icon.isNull()) { // from the window class
|
||||||
|
rv = user32.GetClassLong(hwnd, user32.GCLP_HICONSM);
|
||||||
|
icon = ctypes.cast(win32.ULONG_PTR(rv), win32.HICON);
|
||||||
|
log.debug("GetClassLong winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
if (icon.isNull()) { // from the first resource -> ERROR_RESOURCE_TYPE_NOT_FOUND(1813)
|
||||||
|
icon = user32.LoadIconW(firetray.Win32.hInstance, win32.MAKEINTRESOURCE(0));
|
||||||
|
log.debug("LoadIconW module winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
if (icon.isNull()) { // OS default icon
|
||||||
|
icon = user32.LoadIconW(null, win32.MAKEINTRESOURCE(user32.IDI_APPLICATION));
|
||||||
|
log.debug("LoadIconW default winLastError="+ctypes.winLastError);
|
||||||
|
}
|
||||||
|
log.debug("=== icon="+icon);
|
||||||
|
return icon;
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyProxyWindow: function() {
|
||||||
|
let rv = user32.DestroyWindow(this.hwndProxy);
|
||||||
|
|
||||||
|
rv = this.unregisterWindowClass();
|
||||||
|
log.debug("Hidden window removed");
|
||||||
|
},
|
||||||
|
|
||||||
|
unregisterWindowClass: function() {
|
||||||
|
return user32.UnregisterClassW(win32.LPCTSTR(this.WNDCLASS_ATOM), firetray.Win32.hInstance);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
let rv = shell32.Shell_NotifyIconW(shell32.NIM_DELETE, this.notifyIconData.address());
|
||||||
|
log.debug("Shell_NotifyIcon DELETE="+rv+" winLastError="+ctypes.winLastError);
|
||||||
|
this.destroyProxyWindow();
|
||||||
|
},
|
||||||
|
|
||||||
|
setIcon: function(iconinfo) {
|
||||||
|
let nid = firetray.StatusIcon.notifyIconData;
|
||||||
|
if (iconinfo.hicon)
|
||||||
|
nid.hIcon = iconinfo.hicon;
|
||||||
|
if (iconinfo.tip)
|
||||||
|
nid.szTip = iconinfo.tip;
|
||||||
|
rv = shell32.Shell_NotifyIconW(shell32.NIM_MODIFY, nid.address());
|
||||||
|
log.debug("Shell_NotifyIcon MODIFY="+rv+" winLastError="+ctypes.winLastError);
|
||||||
|
},
|
||||||
|
|
||||||
|
// rgb colors encoded in *bbggrr*
|
||||||
|
cssColorToCOLORREF: function(csscolor) {
|
||||||
|
let rgb = csscolor.substr(1);
|
||||||
|
let rr = rgb.substr(0, 2);
|
||||||
|
let gg = rgb.substr(2, 2);
|
||||||
|
let bb = rgb.substr(4, 2);
|
||||||
|
return parseInt("0x"+bb+gg+rr);
|
||||||
|
},
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/457050/how-to-display-text-in-system-tray-icon-with-win32-api
|
||||||
|
createTextIcon: function(hWnd, text, color) {
|
||||||
|
log.debug("createTextIcon hWnd="+hWnd+" text="+text+" color="+color);
|
||||||
|
|
||||||
|
let blank = this.bitmaps.get('blank-icon');
|
||||||
|
let bitmap = new win32.BITMAP();
|
||||||
|
let err = gdi32.GetObjectW(blank, win32.BITMAP.size, bitmap.address()); // get bitmap info
|
||||||
|
let width = bitmap.bmWidth, height = bitmap.bmHeight;
|
||||||
|
|
||||||
|
let hdc = user32.GetDC(hWnd); // get device context (DC) for hWnd
|
||||||
|
let hdcMem = gdi32.CreateCompatibleDC(hdc); // creates a memory device context (DC) compatible with hdc (need a bitmap)
|
||||||
|
let hBitmap = user32.CopyImage(blank, user32.IMAGE_BITMAP, width, height, 0);
|
||||||
|
let hBitmapMask = gdi32.CreateCompatibleBitmap(hdc, width, height);
|
||||||
|
user32.ReleaseDC(hWnd, hdc);
|
||||||
|
|
||||||
|
let hBitmapOrig = gdi32.SelectObject(hdcMem, hBitmap);
|
||||||
|
|
||||||
|
function getFont(fnHeight) {
|
||||||
|
return gdi32.CreateFontW(
|
||||||
|
fnHeight, 0, 0, 0, gdi32.FW_SEMIBOLD, 0, 0, 0,
|
||||||
|
gdi32.ANSI_CHARSET, gdi32.OUT_OUTLINE_PRECIS, 0, gdi32.ANTIALIASED_QUALITY,
|
||||||
|
gdi32.FIXED_PITCH|gdi32.FF_SWISS, "Arial"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fnHeight = firetray.js.floatToInt(height);
|
||||||
|
log.debug(" fnHeight initial="+fnHeight);
|
||||||
|
let hFont = getFont(fnHeight);
|
||||||
|
gdi32.SelectObject(hdcMem, hFont); // replace font in bitmap by hFont
|
||||||
|
{ let bufLen = 32, faceName = ctypes.jschar.array()(bufLen); gdi32.GetTextFaceW(hdcMem, bufLen, faceName); log.debug(" font="+faceName); }
|
||||||
|
|
||||||
|
let size = new gdi32.SIZE();
|
||||||
|
gdi32.GetTextExtentPoint32W(hdcMem, text, text.length, size.address()); // more reliable than DrawText(DT_CALCRECT)
|
||||||
|
while (size.cx > width - 6 || size.cy > height - 4) {
|
||||||
|
fnHeight -= 1;
|
||||||
|
hFont = getFont(fnHeight);
|
||||||
|
gdi32.SelectObject(hdcMem, hFont);
|
||||||
|
gdi32.GetTextExtentPoint32W(hdcMem, text, text.length, size.address());
|
||||||
|
log.debug(" fnHeight="+fnHeight+" width="+size.cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdi32.SetTextColor(hdcMem, win32.COLORREF(this.cssColorToCOLORREF(color)));
|
||||||
|
gdi32.SetBkMode(hdcMem, gdi32.TRANSPARENT); // VERY IMPORTANT
|
||||||
|
gdi32.SetTextAlign(hdcMem, gdi32.TA_TOP|gdi32.TA_CENTER);
|
||||||
|
log.debug(" ___ALIGN=(winLastError="+ctypes.winLastError+") "+gdi32.GetTextAlign(hdcMem));
|
||||||
|
|
||||||
|
let nXStart = firetray.js.floatToInt((width - size.cx)/2),
|
||||||
|
nYStart = firetray.js.floatToInt((height - size.cy)/2);
|
||||||
|
gdi32.TextOutW(hdcMem, width/2, nYStart+2, text, text.length); // ref point for alignment
|
||||||
|
|
||||||
|
gdi32.SelectObject(hdcMem, hBitmapOrig);
|
||||||
|
|
||||||
|
let iconInfo = win32.ICONINFO();
|
||||||
|
iconInfo.fIcon = true;
|
||||||
|
iconInfo.xHotspot = 0;
|
||||||
|
iconInfo.yHotspot = 0;
|
||||||
|
iconInfo.hbmMask = hBitmapMask;
|
||||||
|
iconInfo.hbmColor = hBitmap;
|
||||||
|
|
||||||
|
let hIcon = user32.CreateIconIndirect(iconInfo.address());
|
||||||
|
log.debug(" CreateIconIndirect hIcon="+hIcon+" lastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
gdi32.DeleteObject(gdi32.SelectObject(hdcMem, hFont));
|
||||||
|
gdi32.DeleteDC(hdcMem);
|
||||||
|
// gdi32.DeleteDC(hdc); // already ReleaseDC's
|
||||||
|
gdi32.DeleteObject(hBitmap);
|
||||||
|
gdi32.DeleteObject(hBitmapMask);
|
||||||
|
|
||||||
|
return hIcon; // to be destroyed (DestroyIcon)
|
||||||
|
},
|
||||||
|
|
||||||
|
getIconSafe: function(name) {
|
||||||
|
let hicon = null;
|
||||||
|
try {
|
||||||
|
hicon = firetray.StatusIcon.icons.get(name);
|
||||||
|
} catch(error) {
|
||||||
|
log.error("icon '"+name+"' not defined.");
|
||||||
|
}
|
||||||
|
return hicon;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // firetray.StatusIcon
|
||||||
|
|
||||||
|
|
||||||
|
firetray.Handler.setIconImageDefault = function() {
|
||||||
|
log.debug("setIconImageDefault");
|
||||||
|
let appIconType = firetray.Utils.prefService.getIntPref("app_icon_type");
|
||||||
|
if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_THEMED)
|
||||||
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.icons.get('app')});
|
||||||
|
else if (appIconType === FIRETRAY_APPLICATION_ICON_TYPE_CUSTOM) {
|
||||||
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.getIconSafe('app-custom')});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.setIconImageNewMail = function() {
|
||||||
|
log.debug("setIconImageDefault");
|
||||||
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.icons.get('mail-unread')});
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.setIconImageCustom = function(prefname) {
|
||||||
|
log.debug("setIconImageCustom pref="+prefname);
|
||||||
|
let name = firetray.StatusIcon.PREF_TO_ICON_NAME[prefname];
|
||||||
|
firetray.StatusIcon.setIcon({hicon:firetray.StatusIcon.getIconSafe(name)});
|
||||||
|
};
|
||||||
|
|
||||||
|
// firetray.Handler.setIconImageFromFile = firetray.StatusIcon.setIconImageFromFile;
|
||||||
|
|
||||||
|
firetray.Handler.setIconTooltip = function(toolTipStr) {
|
||||||
|
log.debug("setIconTooltip");
|
||||||
|
firetray.StatusIcon.setIcon({tip:toolTipStr});
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.setIconTooltipDefault = function() {
|
||||||
|
log.debug("setIconTooltipDefault");
|
||||||
|
firetray.StatusIcon.setIcon({tip:this.appName});
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.setIconText = function(text, color) {
|
||||||
|
let hicon = firetray.StatusIcon.createTextIcon(
|
||||||
|
firetray.StatusIcon.hwndProxy, text, color);
|
||||||
|
log.debug("setIconText icon="+hicon);
|
||||||
|
if (hicon.isNull())
|
||||||
|
log.error("Could not create hicon");
|
||||||
|
firetray.StatusIcon.setIcon({hicon:hicon});
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.setIconVisibility = function(visible) {
|
||||||
|
};
|
61
src/modules/winnt/FiretrayWin32.jsm
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* -*- 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/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/kernel32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
||||||
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
firetray.Handler.subscribeLibsForClosing([kernel32, user32]);
|
||||||
|
|
||||||
|
let log = firetray.Logging.getLogger("firetray.Win32");
|
||||||
|
|
||||||
|
const kMessageTray = "_FIRETRAY_Tray";
|
||||||
|
|
||||||
|
if ("undefined" == typeof(firetray.Handler))
|
||||||
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||||
|
|
||||||
|
|
||||||
|
function Win32Env() {
|
||||||
|
|
||||||
|
this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll
|
||||||
|
log.debug("hInstance="+this.hInstance);
|
||||||
|
|
||||||
|
// we use our own messages because we create a different window class than Moz
|
||||||
|
this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
|
||||||
|
this.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray);
|
||||||
|
log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK);
|
||||||
|
|
||||||
|
/* if Administrator, accept messages from applications running in a lower
|
||||||
|
privilege level */
|
||||||
|
this.acceptAllMessages = function(hwnd) {
|
||||||
|
let rv = null;
|
||||||
|
log.debug(win32.WINVER+" >= "+win32.WIN_VERSIONS["7"]);
|
||||||
|
if (win32.WINVER >= win32.WIN_VERSIONS["7"]) {
|
||||||
|
rv = user32.ChangeWindowMessageFilterEx(hwnd, firetray.Win32.WM_TASKBARCREATED, user32.MSGFLT_ALLOW, null);
|
||||||
|
log.debug("ChangeWindowMessageFilterEx res="+rv+" winLastError="+ctypes.winLastError);
|
||||||
|
} else if (win32.WINVER >= win32.WINVER["Vista"]) {
|
||||||
|
rv = user32.ChangeWindowMessageFilter(firetray.Win32.WM_TASKBARCREATED, user32.MSGFLT_ADD);
|
||||||
|
log.debug("ChangeWindowMessageFilter res="+rv+" winLastError="+ctypes.winLastError);
|
||||||
|
} else {
|
||||||
|
// no UIPI
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
};
|
||||||
|
|
||||||
|
// wid will be used as a string most of the time (through f.Handler.windows mainly)
|
||||||
|
this.hwndToHexStr = function(hWnd) {
|
||||||
|
return "0x" + ctypes.cast(hWnd, ctypes.uintptr_t).value.toString(16);
|
||||||
|
};
|
||||||
|
this.hexStrToHwnd = function(wid) {
|
||||||
|
return win32.HWND(ctypes.UInt64(wid));
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
firetray.Win32 = new Win32Env();
|
294
src/modules/winnt/FiretrayWindow.jsm
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/* -*- 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/ctypes.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/kernel32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
||||||
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
||||||
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||||
|
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
||||||
|
Cu.import("resource://firetray/commons.js");
|
||||||
|
firetray.Handler.subscribeLibsForClosing([user32, kernel32]);
|
||||||
|
|
||||||
|
let log = firetray.Logging.getLogger("firetray.Window");
|
||||||
|
|
||||||
|
if ("undefined" == typeof(firetray.Handler))
|
||||||
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||||
|
|
||||||
|
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
||||||
|
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
||||||
|
|
||||||
|
// We need to keep long-living references to wndProcs callbacks. As they also
|
||||||
|
// happen to be ctypes pointers, we store them into real ctypes arrays.
|
||||||
|
firetray.Handler.wndProcs = new ctypesMap(user32.WNDPROC);
|
||||||
|
firetray.Handler.wndProcsOrig = new ctypesMap(user32.WNDPROC);
|
||||||
|
firetray.Handler.procHooks = new ctypesMap(win32.HHOOK);
|
||||||
|
firetray.Handler.procHooksRegistred = new ctypesMap(win32.HHOOK);
|
||||||
|
|
||||||
|
|
||||||
|
firetray.Window = new FiretrayWindow();
|
||||||
|
|
||||||
|
firetray.Window.init = function() {
|
||||||
|
this.initialized = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.shutdown = function() {
|
||||||
|
this.initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.getVisibility = function(wid) {
|
||||||
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
||||||
|
let style = user32.GetWindowLongW(hwnd, user32.GWL_STYLE);
|
||||||
|
return ((style & user32.WS_VISIBLE) != 0); // user32.IsWindowVisible(hwnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
// firetray.Window.{show,hide} useless as we don't need to restore position and size
|
||||||
|
firetray.Window.setVisibility = function(wid, visible) {
|
||||||
|
log.debug("setVisibility="+visible);
|
||||||
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
||||||
|
let ret = user32.ShowWindow(hwnd, visible ? user32.SW_SHOW : user32.SW_HIDE);
|
||||||
|
log.debug(" ShowWindow="+ret+" winLastError="+ctypes.winLastError);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
|
||||||
|
// log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg=0x"+uMsg.toString(16)+", wParam="+wParam+", lParam="+lParam);
|
||||||
|
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
||||||
|
|
||||||
|
if (uMsg === win32.WM_SYSCOMMAND) {
|
||||||
|
log.debug("wndProc CALLED with WM_SYSCOMMAND wParam="+wParam);
|
||||||
|
if (wParam === win32.SC_MINIMIZE) {
|
||||||
|
log.debug("GOT ICONIFIED");
|
||||||
|
if (firetray.Handler.hideOnMinimizeMaybe(wid)) {
|
||||||
|
return 0; // processed => preventDefault
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
||||||
|
return user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam); // or DefWindowProcW
|
||||||
|
};
|
||||||
|
|
||||||
|
// We could chain wndProcs, but adding a hook looks simpler.
|
||||||
|
firetray.Window.showCount = 0;
|
||||||
|
firetray.Window.startupHook = function(nCode, wParam, lParam) { // WH_CALLWNDPROC, WH_GETMESSAGE
|
||||||
|
// log.debug("startupHook CALLED: nCode="+nCode+", wParam="+wParam+", lParam="+lParam);
|
||||||
|
if (nCode < 0) return user32.CallNextHookEx(null, nCode, wParam, lParam); // user32.HC_ACTION
|
||||||
|
|
||||||
|
let cwpstruct = ctypes.cast(win32.LPARAM(lParam), user32.CWPSTRUCT.ptr).contents;
|
||||||
|
let uMsg = cwpstruct.message;
|
||||||
|
let hwnd = cwpstruct.hwnd;
|
||||||
|
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
||||||
|
let wparam = cwpstruct.wParam;
|
||||||
|
let lparam = cwpstruct.lParam;
|
||||||
|
|
||||||
|
if (uMsg === win32.WM_SHOWWINDOW && wparam == 1 && lparam == 0) { // shown and ShowWindow called
|
||||||
|
log.debug("startupHook CALLED with WM_SHOWWINDOW wparam="+wparam+" lparam="+lparam);
|
||||||
|
firetray.Window.showCount += 1;
|
||||||
|
|
||||||
|
if (firetray.Utils.prefService.getBoolPref('start_hidden')) {
|
||||||
|
log.debug("start_hidden");
|
||||||
|
|
||||||
|
/* Compared to ShowWindow, SetWindowPlacement seems to bypass window
|
||||||
|
animations. http://stackoverflow.com/a/6087214 */
|
||||||
|
let placement = new user32.WINDOWPLACEMENT;
|
||||||
|
let ret = user32.GetWindowPlacement(hwnd, placement.address());
|
||||||
|
log.debug(" GetWindowPlacement="+ret+" winLastError="+ctypes.winLastError);
|
||||||
|
log.debug(" PLACEMENT="+placement);
|
||||||
|
|
||||||
|
if (firetray.Window.showCount < 2) {
|
||||||
|
// we can't prevent ShowWindow, so we mitigate the effect by minimizing
|
||||||
|
// it before. This is why we'll have to restore it when unhidden.
|
||||||
|
placement.showCmd = user32.SW_SHOWMINNOACTIVE;
|
||||||
|
ret = user32.SetWindowPlacement(hwnd, placement.address());
|
||||||
|
log.debug(" SetWindowPlacement="+ret+" winLastError="+ctypes.winLastError);
|
||||||
|
|
||||||
|
firetray.Utils.timer(
|
||||||
|
FIRETRAY_DELAY_NOWAIT_MILLISECONDS,
|
||||||
|
Ci.nsITimer.TYPE_ONE_SHOT, function(){firetray.Handler.hideWindow(wid);}
|
||||||
|
); // looks like CData (hwnd) cannot be closured
|
||||||
|
|
||||||
|
} else { // restore
|
||||||
|
firetray.Window.detachHook(wid);
|
||||||
|
|
||||||
|
placement.showCmd = user32.SW_RESTORE;
|
||||||
|
user32.SetWindowPlacement(hwnd, placement.address());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
firetray.Window.detachHook(wid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return user32.CallNextHookEx(null, nCode, wParam, lParam);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.attachWndProc = function(wid, hwnd) {
|
||||||
|
try {
|
||||||
|
let wndProc = user32.WNDPROC(firetray.Window.wndProc);
|
||||||
|
log.debug("proc="+wndProc);
|
||||||
|
firetray.Handler.wndProcs.insert(wid, wndProc);
|
||||||
|
let procPrev = user32.WNDPROC(
|
||||||
|
user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC,
|
||||||
|
ctypes.cast(wndProc, win32.LONG_PTR))
|
||||||
|
);
|
||||||
|
log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
|
||||||
|
/* we can't store WNDPROC callbacks (JS ctypes objects) with SetPropW(), as
|
||||||
|
we need long-living refs. */
|
||||||
|
firetray.Handler.wndProcsOrig.insert(wid, procPrev);
|
||||||
|
|
||||||
|
} catch (x) {
|
||||||
|
if (x.name === "RangeError") { // instanceof not working :-(
|
||||||
|
let msg = x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
|
||||||
|
+" windows open. This breaks FireTray and most probably "
|
||||||
|
+firetray.Handler.appName+".";
|
||||||
|
log.error(msg);
|
||||||
|
Cu.reportError(msg);
|
||||||
|
}else {
|
||||||
|
log.error(x);
|
||||||
|
Cu.reportError(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.detachWndProc = function(wid) {
|
||||||
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
||||||
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
||||||
|
log.debug("hwnd="+hwnd);
|
||||||
|
let proc = user32.WNDPROC(
|
||||||
|
user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC,
|
||||||
|
ctypes.cast(procPrev, win32.LONG_PTR))
|
||||||
|
);
|
||||||
|
firetray.js.assert(firetray.js.strEquals(proc, firetray.Handler.wndProcs.get(wid)),
|
||||||
|
"Wrong WndProc replaced.");
|
||||||
|
firetray.Handler.wndProcs.remove(wid);
|
||||||
|
firetray.Handler.wndProcsOrig.remove(wid);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.attachHook = function(wid) { // detaches itself alone
|
||||||
|
let startupHook = user32.HOOKPROC(firetray.Window.startupHook);
|
||||||
|
log.debug("callhk="+startupHook);
|
||||||
|
firetray.Handler.procHooks.insert(wid, startupHook);
|
||||||
|
// Global hooks must reside in a dll (hence hInst). This is important for
|
||||||
|
// the scope of variables.
|
||||||
|
let hhook = user32.SetWindowsHookExW(
|
||||||
|
user32.WH_CALLWNDPROC, startupHook, null, kernel32.GetCurrentThreadId());
|
||||||
|
log.debug(" hhook="+hhook+" winLastError="+ctypes.winLastError);
|
||||||
|
firetray.Handler.procHooksRegistred.insert(wid, hhook);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Window.detachHook = function(wid) { // detaches itself alone
|
||||||
|
let hook = firetray.Handler.procHooksRegistred.get(wid);
|
||||||
|
if (!user32.UnhookWindowsHookEx(hook)) {
|
||||||
|
log.error("UnhookWindowsHookEx for window "+wid+" failed: winLastError="+ctypes.winLastError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
firetray.Handler.procHooks.remove(wid);
|
||||||
|
firetray.Handler.procHooksRegistred.remove(wid);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////// firetray.Handler overriding /////////////////////////
|
||||||
|
|
||||||
|
/** debug facility */
|
||||||
|
firetray.Handler.dumpWindows = function() {
|
||||||
|
let dumpStr = ""+firetray.Handler.windowsCount;
|
||||||
|
for (let wid in firetray.Handler.windows) {
|
||||||
|
dumpStr += " "+wid;
|
||||||
|
}
|
||||||
|
log.info(dumpStr);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.registerWindow = function(win) {
|
||||||
|
log.debug("register window");
|
||||||
|
|
||||||
|
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
||||||
|
let nativeHandle = baseWin.nativeHandle;
|
||||||
|
let hwnd = nativeHandle ?
|
||||||
|
firetray.Win32.hexStrToHwnd(nativeHandle) :
|
||||||
|
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
||||||
|
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
||||||
|
log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
|
||||||
|
|
||||||
|
if (this.windows.hasOwnProperty(wid)) {
|
||||||
|
let msg = "Window ("+wid+") already registered.";
|
||||||
|
log.error(msg);
|
||||||
|
Cu.reportError(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.windows[wid] = {};
|
||||||
|
this.windows[wid].chromeWin = win;
|
||||||
|
this.windows[wid].baseWin = baseWin;
|
||||||
|
Object.defineProperties(this.windows[wid], {
|
||||||
|
"visible": { get: function(){return firetray.Window.getVisibility(wid);} }
|
||||||
|
});
|
||||||
|
log.debug("window "+wid+" registered");
|
||||||
|
|
||||||
|
firetray.Window.attachWndProc(wid, hwnd);
|
||||||
|
if (!firetray.Handler.appStarted) {
|
||||||
|
firetray.Window.attachHook(wid);
|
||||||
|
}
|
||||||
|
|
||||||
|
firetray.Win32.acceptAllMessages(hwnd);
|
||||||
|
|
||||||
|
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
||||||
|
return wid;
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.unregisterWindow = function(win) {
|
||||||
|
log.debug("unregister window");
|
||||||
|
|
||||||
|
let wid = firetray.Window.getRegisteredWinIdFromChromeWindow(win);
|
||||||
|
if (!firetray.Handler.windows.hasOwnProperty(wid)) {
|
||||||
|
log.error("can't unregister unknown window "+wid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
firetray.Window.detachWndProc(wid);
|
||||||
|
|
||||||
|
if (!delete firetray.Handler.windows[wid])
|
||||||
|
throw new DeleteError();
|
||||||
|
|
||||||
|
firetray.Handler.dumpWindows();
|
||||||
|
log.debug("window "+wid+" unregistered");
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.showWindow = function(wid) {
|
||||||
|
firetray.Handler.removePopupMenuWindowItemAndSeparatorMaybe(wid);
|
||||||
|
return firetray.Window.setVisibility(wid, true);
|
||||||
|
};
|
||||||
|
firetray.Handler.hideWindow = function(wid) {
|
||||||
|
firetray.Handler.addPopupMenuWindowItemAndSeparatorMaybe(wid);
|
||||||
|
return firetray.Window.setVisibility(wid, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
firetray.Handler.windowGetAttention = function(wid) { // see nsWindow.cpp
|
||||||
|
for (var first in this.windows) break;
|
||||||
|
wid = wid || first;
|
||||||
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
||||||
|
let fgWnd = user32.GetForegroundWindow();
|
||||||
|
log.debug(hwnd+" === "+fgWnd);
|
||||||
|
if (firetray.js.strEquals(hwnd, fgWnd) ||
|
||||||
|
!this.windows[wid].visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let defaultCycleCount = new win32.DWORD;
|
||||||
|
user32.SystemParametersInfoW(user32.SPI_GETFOREGROUNDFLASHCOUNT, 0,
|
||||||
|
defaultCycleCount.address(), 0);
|
||||||
|
log.debug("defaultCycleCount="+defaultCycleCount);
|
||||||
|
|
||||||
|
let flashInfo = new user32.FLASHWINFO;
|
||||||
|
flashInfo.cbSize = user32.FLASHWINFO.size;
|
||||||
|
flashInfo.hwnd = hwnd;
|
||||||
|
flashInfo.dwFlags = user32.FLASHW_ALL;
|
||||||
|
flashInfo.uCount = defaultCycleCount;
|
||||||
|
flashInfo.dwTimeout = 0;
|
||||||
|
user32.FlashWindowEx(flashInfo.address());
|
||||||
|
};
|
@ -7,6 +7,7 @@
|
|||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
printf("sizeof(void*)=%d\n",sizeof(void*));
|
printf("sizeof(void*)=%d\n",sizeof(void*));
|
||||||
printf("sizeof(char)=%d\n",sizeof(char));
|
printf("sizeof(char)=%d\n",sizeof(char));
|
||||||
|
printf("sizeof(short)=%d\n",sizeof(short));
|
||||||
printf("sizeof(int)=%d\n",sizeof(int));
|
printf("sizeof(int)=%d\n",sizeof(int));
|
||||||
printf("sizeof(long)=%d\n",sizeof(long));
|
printf("sizeof(long)=%d\n",sizeof(long));
|
||||||
printf("sizeof(unsigned_long)=%d\n",sizeof(unsigned long));
|
printf("sizeof(unsigned_long)=%d\n",sizeof(unsigned long));
|
||||||
|