1
0
mirror of https://github.com/moparisthebest/FireTray synced 2024-08-13 15:53:47 -04:00

singleton tray icon handler (avoid creation of multiple icons when new windows

created)

https://developer.mozilla.org/en/Using_JavaScript_code_modules
http://stackoverflow.com/questions/2275882/setting-a-preference-at-startup-in-firefox/2276772#2276772
This commit is contained in:
foudfou 2011-08-08 04:32:52 +02:00
parent 98ee40353e
commit ef190af251
3 changed files with 187 additions and 175 deletions

View File

@ -1,118 +1,11 @@
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/ctypes.jsm");
Components.utils.import("resource://moztray/LibGObject.jsm");
Components.utils.import("resource://moztray/LibGtkStatusIcon.jsm");
Components.utils.import("resource://moztray/commons.js");
const MOZT_ICON_DIR = "chrome/skin/";
const MOZT_ICON_SUFFIX = "32.png";
/**
* mozt namespace.
*/
if ("undefined" == typeof(mozt)) {
var mozt = {};
};
mozt.Handler = {
_windowsHidden: false,
_getBaseWindow: function(win) {
var bw;
try { // thx Neil Deakin !!
bw = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIBaseWindow);
} catch (ex) {
bw = null;
setTimeout(function() {throw ex; }, 0);
// ignore no-interface exception
}
return bw;
},
_getAllWindows: function() {
mozt.Debug.debug("_getAllWindows");
var baseWindows = new Array();
var e = Services.wm.getEnumerator(null);
while (e.hasMoreElements()) {
var w = e.getNext();
baseWindows[baseWindows.length] = this._getBaseWindow(w);
}
return baseWindows;
},
/*
* might need to remember position...
* var outX = {}, outY = {}, outCX = {}, outCY = {};
* bw.getPositionAndSize(outX, outY, outCX, outCY);
* mozt.Debug.debug("pos: "
* + outX.value + ", "
* + outY.value + ", "
* + outCX.value + ", "
* + outCY.value
* );
*/
showHideToTray: function(a1, a2, a3) {
mozt.Debug.debug("showHideToTray");
var baseWindows;
try {
baseWindows = this._getAllWindows();
} catch (x) {
mozt.Debug.debug(x);
}
mozt.Debug.debug("baseWindows: " + baseWindows.length);
for(var i=0; i<baseWindows.length; i++) {
var bw = baseWindows[i];
mozt.Debug.debug('isHidden: ' + this._windowsHidden);
mozt.Debug.debug("bw.visibility: " + bw.visibility);
try {
if (this._windowsHidden) {
bw.visibility = true;
} else {
bw.visibility = false;
}
} catch (x) {
mozt.Debug.debug(x);
}
mozt.Debug.debug("bw.visibility: " + bw.visibility);
mozt.Debug.debug("bw.title: " + bw.title);
mozt.Debug.debug("bw.parentNativeWindow: " + bw.parentNativeWindow);
}
if (this._windowsHidden) {
this._windowsHidden = false;
} else {
this._windowsHidden = true;
}
},
}; // mozt.Handler
var mozt_activateCb; // pointer to JS function. should not be eaten
// by GC ("Running global cleanup code from
// study base classes" ?)
Components.utils.import("resource://moztray/MoztHandler.jsm");
mozt.Main = {
initialized: false,
onLoad: function() {
if (this.initialized)
return true; // prevent creating multiple tray icon
mozt.Debug.debug('initialized: ' + this.initialized);
// initialization code
this.strings = document.getElementById("moztray-strings");
@ -126,67 +19,10 @@ mozt.Main = {
return false;
}
try {
// instanciate tray icon
LibGtkStatusIcon.init();
this.tray_icon = LibGtkStatusIcon.gtk_status_icon_new();
var mozApp = Services.appinfo.name.toLowerCase();
var iconFilename = MOZT_ICON_DIR + mozApp + MOZT_ICON_SUFFIX;
LibGtkStatusIcon.gtk_status_icon_set_from_file(this.tray_icon,
iconFilename);
// set tooltip.
// TODO: produces:
// (firefox-bin:5302): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
// (thunderbird-bin:5380): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
LibGtkStatusIcon.gtk_status_icon_set_tooltip_text(this.tray_icon,
mozApp);
LibGtkStatusIcon.shutdown();
// watch out for binding problems !
mozt_activateCb = LibGObject.GCallback_t(
function(){mozt.Handler.showHideToTray();});
LibGObject.g_signal_connect(this.tray_icon, "activate",
mozt_activateCb, null);
} catch (x) {
Components.utils.reportError(x);
return false;
}
/*
try {
// Experimental stuff... needs
// Components.utils.import("resource://moztray/LibGdkWindow.js");
var gdkScreen = LibGdkWindow.GdkScreenGetDefault();
var tl = LibGdkWindow.GdkScreenGetToplevelWindows(gdkScreen);
mozt.Debug.debug(tl);
// gboolean gdk_window_is_visible (GdkWindow *window);
mozt_func = LibGObject.GFunc_t(mozt_funcGdkJS);
LibGObject.g_list_foreach(tl, mozt_func, null);
var gdkWinCount = LibGObject.g_list_length(tl);
mozt.Debug.debug('gdkWinCount: ' + gdkWinCount);
var pid = LibC.getpid();
mozt.Debug.debug(pid);
tl = LibGtkStatusIcon.gtk_window_list_toplevels();
mozt_func = LibGObject.GFunc_t(mozt_funcGtkJS);
LibGObject.g_list_foreach(tl, mozt_func, null);
var gtkWinCount = LibGObject.g_list_length(tl);
mozt.Debug.debug('gtkWinCount: ' + gtkWinCount);
} catch (x) {
mozt.Debug.debug(x);
}
*/
if (!mozt.Handler.initialized)
mozt.Handler.init();
mozt.Debug.debug('Moztray LOADED !');
this.initialized = true;
return true;
},
@ -195,7 +31,7 @@ mozt.Main = {
mozt.Utils.prefService.removeObserver("", this);
mozt.Debug.debug('Moztray UNLOADED !');
this.initialized = false;
mozt.Handler.initialized = false;
},
observe: function(subject, topic, data) {
@ -213,7 +49,6 @@ mozt.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

183
src/modules/MoztHandler.jsm Normal file
View File

@ -0,0 +1,183 @@
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
var EXPORTED_SYMBOLS = [ "mozt" ];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/ctypes.jsm");
/* Cu.import("resource://moztray/LibC.jsm"); */
Cu.import("resource://moztray/LibGObject.jsm");
Cu.import("resource://moztray/LibGtkStatusIcon.jsm");
Cu.import("resource://moztray/commons.js");
const MOZT_ICON_DIR = "chrome/skin/";
const MOZT_ICON_SUFFIX = "32.png";
/**
* mozt namespace.
*/
if ("undefined" == typeof(mozt)) {
var mozt = {};
};
var mozt_activateCb; // pointer to JS function. should not be eaten
// by GC ("Running global cleanup code from
// study base classes" ?)
/**
* Singleton object for tray icon management
*/
// NOTE: modules work outside of the window scope. Unlike scripts in the
// chrome, modules don't have access to objects such as window, document, or
// other global functions
// (https://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management)
mozt.Handler = {
initialized: false,
_windowsHidden: false,
_getBaseWindow: function(win) {
var bw;
try { // thx Neil Deakin !!
bw = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIBaseWindow);
} catch (ex) {
bw = null;
setTimeout(function() {throw ex; }, 0);
// ignore no-interface exception
}
return bw;
},
_getAllWindows: function() {
mozt.Debug.debug("_getAllWindows");
var baseWindows = new Array();
var e = Services.wm.getEnumerator(null);
while (e.hasMoreElements()) {
var w = e.getNext();
baseWindows[baseWindows.length] = this._getBaseWindow(w);
}
return baseWindows;
},
/*
* might need to remember position...
* var outX = {}, outY = {}, outCX = {}, outCY = {};
* bw.getPositionAndSize(outX, outY, outCX, outCY);
* mozt.Debug.debug("pos: "
* + outX.value + ", "
* + outY.value + ", "
* + outCX.value + ", "
* + outCY.value
* );
*/
showHideToTray: function(a1, a2, a3) {
mozt.Debug.debug("showHideToTray");
var baseWindows;
try {
baseWindows = this._getAllWindows();
} catch (x) {
mozt.Debug.debug(x);
}
mozt.Debug.debug("baseWindows: " + baseWindows.length);
for(var i=0; i<baseWindows.length; i++) {
var bw = baseWindows[i];
mozt.Debug.debug('isHidden: ' + this._windowsHidden);
mozt.Debug.debug("bw.visibility: " + bw.visibility);
try {
if (this._windowsHidden) {
bw.visibility = true;
} else {
bw.visibility = false;
}
} catch (x) {
mozt.Debug.debug(x);
}
mozt.Debug.debug("bw.visibility: " + bw.visibility);
mozt.Debug.debug("bw.title: " + bw.title);
mozt.Debug.debug("bw.parentNativeWindow: " + bw.parentNativeWindow);
}
if (this._windowsHidden) {
this._windowsHidden = false;
} else {
this._windowsHidden = true;
}
},
init: function() { // creates icon
try {
// instanciate tray icon
LibGtkStatusIcon.init();
this.tray_icon = LibGtkStatusIcon.gtk_status_icon_new();
var mozApp = Services.appinfo.name.toLowerCase();
var iconFilename = MOZT_ICON_DIR + mozApp + MOZT_ICON_SUFFIX;
LibGtkStatusIcon.gtk_status_icon_set_from_file(this.tray_icon,
iconFilename);
// set tooltip.
// TODO: produces:
// (firefox-bin:5302): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
// (thunderbird-bin:5380): Gdk-CRITICAL **: IA__gdk_window_get_root_coords: assertion `GDK_IS_WINDOW (window)' failed
LibGtkStatusIcon.gtk_status_icon_set_tooltip_text(this.tray_icon,
mozApp);
// close lib
LibGtkStatusIcon.shutdown();
// watch out for binding problems !
mozt_activateCb = LibGObject.GCallback_t(
function(){mozt.Handler.showHideToTray();});
LibGObject.g_signal_connect(this.tray_icon, "activate",
mozt_activateCb, null);
} catch (x) {
Components.utils.reportError(x);
return false;
}
/*
try {
// Experimental stuff... needs
// Components.utils.import("resource://moztray/LibGdkWindow.js");
var gdkScreen = LibGdkWindow.GdkScreenGetDefault();
var tl = LibGdkWindow.GdkScreenGetToplevelWindows(gdkScreen);
mozt.Debug.debug(tl);
// gboolean gdk_window_is_visible (GdkWindow *window);
mozt_func = LibGObject.GFunc_t(mozt_funcGdkJS);
LibGObject.g_list_foreach(tl, mozt_func, null);
var gdkWinCount = LibGObject.g_list_length(tl);
mozt.Debug.debug('gdkWinCount: ' + gdkWinCount);
var pid = LibC.getpid();
mozt.Debug.debug(pid);
tl = LibGtkStatusIcon.gtk_window_list_toplevels();
mozt_func = LibGObject.GFunc_t(mozt_funcGtkJS);
LibGObject.g_list_foreach(tl, mozt_func, null);
var gtkWinCount = LibGObject.g_list_length(tl);
mozt.Debug.debug('gtkWinCount: ' + gtkWinCount);
} catch (x) {
mozt.Debug.debug(x);
}
*/
this.initialized = true;
return true;
},
}; // mozt.Handler

View File

@ -1,11 +1,5 @@
/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* should contain our business logic in JSM, available through service objects,
* and keep chrome scripts limited to handle presentation logic.
* http://developer.mozilla.org/en/XUL_School/JavaScript_Object_Management.html
*/
var EXPORTED_SYMBOLS = [ "mozt", "Cc", "Ci", "Cu" ];
const Cc = Components.classes;