Overcome titlebar buttons not firing expected events.

This commit is contained in:
foudfou 2014-03-16 18:40:59 +01:00
parent 25bc039a6d
commit 9b2f2016aa
5 changed files with 107 additions and 19 deletions

View File

@ -27,6 +27,7 @@ var firetrayChrome = { // each new window gets a new firetrayChrome !
this.winId = firetray.Handler.registerWindow(win);
win.addEventListener('close', firetrayChrome.onClose, true);
this.hijackTitlebarButtons();
firetray_log.debug('Firetray LOADED: ' + init);
return true;
@ -47,30 +48,102 @@ var firetrayChrome = { // each new window gets a new firetrayChrome !
hides_on_close is set (we are not actually closing the tabs!). There is no
use trying to set warnOnClose=false temporarily in onClose, since onClose is
called *after* the popup */
// FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=827880 menubar
// prevents close button to fire 'close'
onClose: function(event) {
firetray_log.debug('Firetray CLOSE');
if (event.originalTarget != window)
throw new TypeError('originalTarget not the current ChromeWindow');
let hides_on_close = firetray.Utils.prefService.getBoolPref('hides_on_close');
firetray_log.debug('hides_on_close: '+hides_on_close);
if (hides_on_close) {
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_on_close) return false;
if (hides_single_window)
firetray.Handler.hideWindow(firetrayChrome.winId);
else
firetray.Handler.hideAllWindows();
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 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);
}
}
};
// should be sufficient for a delayed Startup (no need for window.setTimeout())

View File

@ -370,7 +370,7 @@ firetray.Handler = {
}
},
hideOnMinimizeMaybe: function(wid) {
onMinimize: function(wid) {
let hidden = false;
let hides_on_minimize = firetray.Utils.prefService.getBoolPref('hides_on_minimize');
if (hides_on_minimize) {

View File

@ -15,7 +15,8 @@ var EXPORTED_SYMBOLS =
"FIRETRAY_ACCOUNT_SERVER_TYPE_IM", "FIRETRAY_DELAY_STARTUP_MILLISECONDS",
"FIRETRAY_DELAY_NOWAIT_MILLISECONDS", "FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD",
"FIRETRAY_MESSAGE_COUNT_TYPE_NEW", "FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL",
"FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE", "FIRETRAY_APP_DB" ];
"FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE", "FIRETRAY_APP_DB",
"FIRETRAY_XUL_ATTRIBUTE_COMMAND", "FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND" ];
const Cc = Components.classes;
const Ci = Components.interfaces;
@ -55,6 +56,9 @@ const FIRETRAY_DELAY_NOWAIT_MILLISECONDS = 0;
const FIRETRAY_CHAT_ICON_BLINK_STYLE_NORMAL = 0;
const FIRETRAY_CHAT_ICON_BLINK_STYLE_FADE = 1;
const FIRETRAY_XUL_ATTRIBUTE_COMMAND = 0;
const FIRETRAY_XUL_ATTRIBUTE_ONCOMMAND = 1;
const FIRETRAY_APP_DB = {
firefox: {
@ -266,6 +270,17 @@ firetray.Utils = {
timer.initWithCallback({ notify: callback },
delay, timerType);
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;
}
};

View File

@ -560,7 +560,7 @@ firetray.Window.filterWindow = function(xev, gdkEv, data) {
// prevent the event.
if (isHidden) {
log.debug("GOT ICONIFIED");
firetray.Handler.hideOnMinimizeMaybe(xid);
firetray.Handler.onMinimize(xid);
}
break;

View File

@ -74,7 +74,7 @@ firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
log.debug("wndProc CALLED with WM_SYSCOMMAND wParam="+wParam);
if (wParam === win32.SC_MINIMIZE) {
log.debug("GOT ICONIFIED");
if (firetray.Window.hideOnMinimizeMaybe(wid)) {
if (firetray.Handler.hideOnMinimizeMaybe(wid)) {
return 0; // processed => preventDefault
}
}