* fix unload event listeners (and thus unregistration of windows)

* add hides_single_window preference
* revert to JS handeling of 'delete-event' (rely on onclose rather than GTK)

WORK IN PROGESS
This commit is contained in:
foudfou 2011-12-23 16:44:09 +01:00
parent 8ec4d995b8
commit 4c72b1fcbd
7 changed files with 67 additions and 83 deletions

View File

@ -23,7 +23,9 @@ const TREELEVEL_EXCLUDED_ACCOUNTS = 1;
firetray.UIOptions = {
strings: null,
onLoad: function() {
onLoad: function(e) {
window.removeEventListener('load', arguments.callee, true);
this.strings = document.getElementById("firetray-options-strings");
if(firetray.Handler.inMailApp) {
@ -36,7 +38,9 @@ firetray.UIOptions = {
},
onQuit: function() {
onQuit: function(e) {
window.removeEventListener('unload', arguments.callee, true);
// cleaning: removeEventListener on cells
// NOTE: not sure this is necessary on window close
let tree = document.getElementById("ui_tree_mail_accounts");
@ -415,13 +419,5 @@ firetray.UIOptions = {
};
window.addEventListener(
'load', function (e) {
removeEventListener('load', arguments.callee, true);
firetray.UIOptions.onLoad(); },
false);
window.addEventListener(
'unload', function (e) {
removeEventListener('unload', arguments.callee, true);
firetray.UIOptions.onQuit(); },
false);
window.addEventListener('load', firetray.UIOptions.onLoad, false);
window.addEventListener('unload', firetray.UIOptions.onQuit, false);

View File

@ -21,6 +21,7 @@
<preferences>
<preference id="pref_bool_hides_on_close" name="extensions.firetray.hides_on_close" type="bool"/>
<preference id="pref_bool_hides_on_minimize" name="extensions.firetray.hides_on_minimize" type="bool"/>
<preference id="pref_bool_hides_single_window" name="extensions.firetray.hides_single_window" type="bool"/>
<preference id="pref_string_icon_text_color" name="extensions.firetray.icon_text_color" type="string" />
<preference id="pref_string_custom_mail_icon" name="extensions.firetray.custom_mail_icon" type="string" />
<preference id="pref_string_mail_accounts" name="extensions.firetray.mail_accounts" type="string"/>
@ -46,6 +47,9 @@
label="&bool_hides_on_minimize.label;"
accesskey="&bool_hides_on_minimize.accesskey;"
disabled="true" tooltiptext="&NOT_IMPLEMENTED_YET;"/>
<checkbox id="ui_hides_single_window" preference="pref_bool_hides_single_window"
label="&bool_hides_single_window.label;"
accesskey="&bool_hides_single_window.accesskey;"/>
</groupbox>
</tabpanel>

View File

@ -16,15 +16,16 @@ if ("undefined" == typeof(firetray)) {
firetray.Main = {
onLoad: function(win) {
onLoad: function() {
window.removeEventListener('load', arguments.callee, true);
// initialization code
this.strings = document.getElementById("firetray-strings");
try {
// Set up preference change observer
firetray.Utils.prefService.QueryInterface(Ci.nsIPrefBranch2);
let that = this;
firetray.Utils.prefService.addObserver("", that, false);
firetray.Utils.prefService.addObserver("", firetray.Main, false);
}
catch (ex) {
ERROR(ex);
@ -32,30 +33,28 @@ firetray.Main = {
}
let init = firetray.Handler.initialized || firetray.Handler.init();
firetray.Handler.registerWindow(win);
firetray.Handler.registerWindow(window);
// update unread messages count
if (firetray.Handler.inMailApp && firetray.Messaging.initialized)
firetray.Messaging.updateUnreadMsgCount();
/* GTK TEST
// prevent window closing.
let that = this;
window.addEventListener('close', that.onClose, true);
window.addEventListener('close', firetray.Main.onClose, true);
// NOTE: each new window gets a new firetray.Main, and hence listens to pref
// changes
*/
LOG('Firetray LOADED: ' + init);
return true;
},
onQuit: function(win) {
// Remove observer
let that = this;
firetray.Utils.prefService.removeObserver("", that);
onQuit: function(e) {
window.removeEventListener('unload', arguments.callee, true);
firetray.Handler.unregisterWindow(win);
// Remove observer
firetray.Utils.prefService.removeObserver("", firetray.Main);
firetray.Handler.unregisterWindow(window);
/* NOTE: don't firetray.Handler.initialized=false here, otherwise after a
window close, a new window will create a new handler (and hence, a new
@ -63,18 +62,21 @@ firetray.Main = {
LOG('Firetray UNLOADED !');
},
/* GTK TEST
// TODO: prevent preceding warning about closing multiple tabs (browser.tabs.warnOnClose)
onClose: function(event) {
LOG('Firetray CLOSE');
let hides_on_close = firetray.Utils.prefService.getBoolPref('hides_on_close');
LOG('hides_on_close: '+hides_on_close);
let hides_single_window = firetray.Utils.prefService.getBoolPref('hides_single_window');
LOG('hides_on_close: '+hides_on_close+', hides_single_window='+hides_single_window);
LOG('event.originalTarget: '+event.originalTarget);
if (hides_on_close) {
firetray.Handler.showHideToTray();
if (hides_single_window)
firetray.Window.hideWindow(window);
else
firetray.Handler.hideAllWindows(window);
event && event.preventDefault(); // no event when called directly (xul)
}
},
*/
observe: function(subject, topic, data) {
// Observer for pref changes
@ -86,17 +88,7 @@ firetray.Main = {
};
// should be sufficient for a delayed Startup (no need for window.setTimeout())
// https://developer.mozilla.org/en/Extensions/Performance_best_practices_in_extensions
// https://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management.html
// https://developer.mozilla.org/en/Extensions/Performance_best_practices_in_extensions#Removing_Event_Listeners
let thatWindow = window;
window.addEventListener(
'load', function (e) {
removeEventListener('load', arguments.callee, true);
firetray.Main.onLoad(thatWindow); },
false);
window.addEventListener(
'unload', function (e) {
removeEventListener('unload', arguments.callee, true);
firetray.Main.onQuit(thatWindow); },
false);
window.addEventListener('load', firetray.Main.onLoad, false);
window.addEventListener('unload', firetray.Main.onQuit, false);

View File

@ -14,6 +14,8 @@
<!ENTITY bool_hides_on_close.accesskey "C">
<!ENTITY bool_hides_on_minimize.label "Minimize window hides to tray">
<!ENTITY bool_hides_on_minimize.accesskey "M">
<!ENTITY bool_hides_single_window.label "Hide the current window only (not all windows)">
<!ENTITY bool_hides_single_window.accesskey "H">
<!ENTITY mail_notification.label "Mail notification">
<!ENTITY mail_notification_disabled.label "disabled">

View File

@ -8,6 +8,7 @@ pref("browser.tabs.warnOnClose", false);
pref("extensions.firetray.hides_on_close", true);
pref("extensions.firetray.hides_on_minimize", true);
pref("extensions.firetray.hides_single_window", true); // FIXME: should default to 'false'
pref("extensions.firetray.mail_notification", 1);
pref("extensions.firetray.icon_text_color", "#000000");

View File

@ -49,8 +49,8 @@ firetray.StatusIcon = {
LOG("showHideAllWindows: "+firetray.Handler.hasOwnProperty("showHideAllWindows"));
firetray_iconActivateCb = gtk.GCallbackStatusIconActivate_t(firetray.Handler.showHideAllWindows);
let res = gobject.g_signal_connect(firetray.StatusIcon.trayIcon, "activate", firetray_iconActivateCb, null);
LOG("g_connect activate="+res);
let handlerId = gobject.g_signal_connect(firetray.StatusIcon.trayIcon, "activate", firetray_iconActivateCb, null);
LOG("g_connect activate="+handlerId);
this.initialized = true;
return true;

View File

@ -57,20 +57,9 @@ firetray.Handler.registerWindow = function(win) {
gdk.GDK_ALL_EVENTS_MASK); */
try {
/* delete_event_cb (in gtk2/nsWindow.cpp) prevents us from catching
"delete-event" */
let deleteEventId = gobject.g_signal_lookup("delete-event", gtk.gtk_window_get_type());
LOG("deleteEventId="+deleteEventId);
let mozDeleteEventCbId = gobject.g_signal_handler_find(gtkWin, gobject.G_SIGNAL_MATCH_ID, deleteEventId, 0, null, null, null);
LOG("mozDeleteEventCbId="+mozDeleteEventCbId);
gobject.g_signal_handler_block(gtkWin, mozDeleteEventCbId); // not _disconnect !
this.windows[xid].mozDeleteEventCbId = mozDeleteEventCbId;
this.windows[xid].windowDeleteCb = gtk.GCallbackGenericEvent_t(firetray.Window.windowDelete);
// NOTE: it'd be nice to pass the xid to g_signal_connect...
this.windows[xid].windowDeleteCbId = gobject.g_signal_connect(gtkWin, "delete-event", that.windows[xid].windowDeleteCb, null);
LOG("g_connect delete-event="+this.windows[xid].windowDeleteCbId);
/* NOTE: we could try to catch the "delete-event" here and block
delete_event_cb (in gtk2/nsWindow.cpp), but we prefer to use the
provided "close" JS event */
/* we'll catch minimize events with Gtk:
http://stackoverflow.com/questions/8018328/what-is-the-gtk-event-called-when-a-window-minimizes */
@ -91,30 +80,26 @@ firetray.Handler.unregisterWindow = function(win) {
LOG("unregister window");
try {
let [gtkWin, gdkWin, xid] = firetray.Window.getWindowsFromChromeWindow(win);
// unblock Moz original delete-event handler
gobject.g_signal_handler_disconnect(gtkWin, this.windows[xid].windowDeleteCbId);
gobject.g_signal_handler_unblock(gtkWin, this.windows[xid].mozDeleteEventCbId);
let xid = firetray.Window.getXIDFromChromeWindow(win);
return this._unregisterWindowByXID(xid);
} catch (x) {
ERROR(x);
}
return null;
return false;
};
firetray.Handler._unregisterWindowByXID = function(xid) {
try {
if (this.windows.hasOwnProperty(xid))
delete this.windows[xid];
else {
ERROR("can't unregister unknown window "+xid);
try {
if (this.windows.hasOwnProperty(xid))
delete this.windows[xid];
else {
ERROR("can't unregister unknown window "+xid);
return false;
}
} catch (x) {
ERROR(x);
return false;
}
} catch (x) {
ERROR(x);
}
LOG("window "+xid+" unregistered");
return true;
};
@ -200,11 +185,11 @@ firetray.Window = {
* @param userData: _find_data_t
*/
_findGtkWindowByTitle: function(gtkWidget, userData) {
LOG("GTK Window: "+gtkWidget+", "+userData);
// LOG("GTK Window: "+gtkWidget+", "+userData);
let data = ctypes.cast(userData, _find_data_t.ptr);
let inTitle = data.contents.inTitle;
LOG("inTitle="+inTitle.readString());
// LOG("inTitle="+inTitle.readString());
let gtkWin = ctypes.cast(gtkWidget, gtk.GtkWindow.ptr);
let winTitle = gtk.gtk_window_get_title(gtkWin);
@ -244,6 +229,7 @@ firetray.Window = {
return null;
},
/** consider using getXIDFromChromeWindow() if you only need the XID */
getWindowsFromChromeWindow: function(win) {
let gtkWin = firetray.Window.getGtkWindowHandle(win);
LOG("gtkWin="+gtkWin);
@ -254,24 +240,27 @@ firetray.Window = {
return [gtkWin, gdkWin, xid];
},
windowDelete: function(gtkWidget, gdkEv, userData){
LOG("gtk_widget_hide: "+gtkWidget+", "+gdkEv+", "+userData);
let xid = firetray.Window.getXIDFromGtkWidget(gtkWidget);
LOG("windowDelete XID="+xid);
getXIDFromChromeWindow: function(win) {
for (let xid in firetray.Handler.windows)
if (firetray.Handler.windows[xid].win === win)
return xid;
ERROR("unknown window while lookup");
return null;
},
hideWindow: function(win) {
LOG("hideWindow");
let xid = this.getXIDFromChromeWindow(win);
LOG("found xid="+xid);
try {
firetray.Window._saveWindowPositionSizeState(xid);
// hide window - NOTE: we don't use BaseWindow.visibility to have full
// control
let gdkWin = firetray.Window.getGdkWindowFromGtkWindow(gtkWidget);
gdk.gdk_window_hide(gdkWin);
gdk.gdk_window_hide(firetray.Handler.windows[xid].gdkWin);
} catch (x) {
ERROR(x);
}
let stopPropagation = true;
return stopPropagation;
},
_saveWindowPositionSizeState: function(xid) {