diff --git a/src/install.rdf b/src/install.rdf
index 0dd8901..f948aac 100644
--- a/src/install.rdf
+++ b/src/install.rdf
@@ -14,7 +14,8 @@
chrome://firetray/content/options.xul
chrome://firetray/skin/firetray48.png
chrome://firetray/skin/firetray64.png
- Linux
+ Linux
+ WINNT
diff --git a/src/modules/FiretrayHandler.jsm b/src/modules/FiretrayHandler.jsm
index eacbcc4..1b74574 100644
--- a/src/modules/FiretrayHandler.jsm
+++ b/src/modules/FiretrayHandler.jsm
@@ -69,8 +69,15 @@ firetray.Handler = {
Cu.import("resource://firetray/linux/FiretrayWindow.jsm");
log.debug('FiretrayWindow imported');
break;
+ case "WINNT":
+ Cu.import("resource://firetray/winnt/FiretrayStatusIcon.jsm");
+ log.debug('FiretrayStatusIcon imported');
+ Cu.import("resource://firetray/winnt/FiretrayWindow.jsm");
+ log.debug('FiretrayWindow imported');
+ break;
default:
- log.error("FIRETRAY: only Linux platform supported at this time. Firetray not loaded");
+ log.error("FIRETRAY: only Linux and WINNT platforms supported at this"
+ + "time. Firetray not loaded");
return false;
}
diff --git a/src/modules/ctypes/ctypes-utils.jsm b/src/modules/ctypes/ctypes-utils.jsm
index 3ddfa34..c6b951e 100644
--- a/src/modules/ctypes/ctypes-utils.jsm
+++ b/src/modules/ctypes/ctypes-utils.jsm
@@ -36,13 +36,18 @@
*
* ***** END LICENSE BLOCK ***** */
+var EXPORTED_SYMBOLS = [ "ctypes_library", "is64bit" ];
+
const Cu = Components.utils;
Cu.import("resource://gre/modules/ctypes.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.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");
@@ -111,7 +116,10 @@ function ctypes_library(aName, aABIs, aDefines, aGlobal) {
var library;
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);
try {
library = ctypes.open(soname);
@@ -155,7 +163,12 @@ function ctypes_library(aName, aABIs, aDefines, aGlobal) {
try {
args = [];
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)) {
args.push(arg);
}
diff --git a/src/modules/ctypes/winnt/kernel32.jsm b/src/modules/ctypes/winnt/kernel32.jsm
new file mode 100644
index 0000000..4495e19
--- /dev/null
+++ b/src/modules/ctypes/winnt/kernel32.jsm
@@ -0,0 +1,36 @@
+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/types.jsm");
+
+function kernel32_defines(lib) {
+
+ this.OSVERSIONINFOEXW = ctypes.StructType("OSVERSIONINFOEXW", [
+ { "dwOSVersionInfoSize": win_t.DWORD },
+ { "dwMajorVersion": win_t.DWORD },
+ { "dwMinorVersion": win_t.DWORD },
+ { "dwBuildNumber": win_t.DWORD },
+ { "dwPlatformId": win_t.DWORD },
+ { "szCSDVersion": ctypes.ArrayType(win_t.TCHAR, 128) },
+ { "wServicePackMajor": win_t.WORD },
+ { "wServicePackMinor": win_t.WORD },
+ { "wSuiteMask": win_t.WORD },
+ { "wProductType": win_t.BYTE },
+ { "wReserved": win_t.BYTE }
+ ]);
+
+ // lib.lazy_bind("GetLastError", win_t.DWORD); // use ctypes.winLastError instead
+ lib.lazy_bind("GetVersionExW", win_t.BOOL, this.OSVERSIONINFOEXW.ptr);
+ lib.lazy_bind("GetConsoleWindow", win_t.HWND);
+ lib.lazy_bind("GetConsoleTitleW", win_t.DWORD, win_t.LPTSTR, win_t.DWORD);
+ lib.lazy_bind("GetModuleHandleW", win_t.HMODULE, win_t.LPCTSTR);
+
+}
+
+new ctypes_library(KERNEL32_LIBNAME, KERNEL32_ABIS, kernel32_defines, this);
diff --git a/src/modules/ctypes/winnt/shell32.jsm b/src/modules/ctypes/winnt/shell32.jsm
new file mode 100644
index 0000000..a07f0a2
--- /dev/null
+++ b/src/modules/ctypes/winnt/shell32.jsm
@@ -0,0 +1,53 @@
+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/types.jsm");
+
+function shell32_defines(lib) {
+
+ // 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;
+
+ this.NOTIFYICONDATAW = ctypes.StructType("NOTIFYICONDATAW", [
+ { "cbSize": win_t.DWORD },
+ { "hWnd": win_t.HWND },
+ { "uID": win_t.UINT },
+ { "uFlags": win_t.UINT },
+ { "uCallbackMessage": win_t.UINT },
+ { "hIcon": win_t.HICON },
+ { "szTip": ctypes.ArrayType(win_t.TCHAR, 64) }, // 128 on win2k+
+ { "dwState": win_t.DWORD },
+ { "dwStateMask": win_t.DWORD },
+ { "szInfo": ctypes.ArrayType(win_t.TCHAR, 256) },
+ { "uTimeoutOrVersion": win_t.UINT }, // union
+ { "szInfoTitle[64]": win_t.TCHAR },
+ { "dwInfoFlags": win_t.DWORD },
+ { "guidItem": win_t.GUID },
+ { "hBalloonIcon": win_t.HICON }
+ ]);
+
+ lib.lazy_bind("Shell_NotifyIconW", win_t.BOOL, win_t.DWORD, this.NOTIFYICONDATAW.ptr);
+
+}
+
+new ctypes_library(SHELL32_LIBNAME, SHELL32_ABIS, shell32_defines, this);
diff --git a/src/modules/ctypes/winnt/types.jsm b/src/modules/ctypes/winnt/types.jsm
new file mode 100644
index 0000000..8f89e2b
--- /dev/null
+++ b/src/modules/ctypes/winnt/types.jsm
@@ -0,0 +1,51 @@
+var EXPORTED_SYMBOLS = [ "win_t" ];
+
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
+
+const UINT_PTR_T = is64bit ? ctypes.uint64_t : ctypes.unsigned_int;
+const LONG_PTR_T = is64bit ? ctypes.int64_t : ctypes.long;
+const ULONG_PTR_T = is64bit ? ctypes.uint64_t : ctypes.unsigned_long;
+const HANDLE_T = ctypes.voidptr_t; // oder ctypes.intptr_t, ctypes.size_t,
+
+var win_t = {
+
+ BOOL: ctypes.bool,
+ BYTE: ctypes.unsigned_char,
+ UINT: ctypes.unsigned_int,
+ WORD: ctypes.unsigned_short,
+ DWORD: ctypes.unsigned_long,
+ PVOID: ctypes.voidptr_t,
+ ULONG_PTR: ULONG_PTR_T,
+ SIZE_T: ULONG_PTR_T,
+ HWND: HANDLE_T,
+ HICON: HANDLE_T,
+ HINSTANCE: HANDLE_T,
+ HMODULE: HANDLE_T,
+ TCHAR: ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t: jschar
+ LPSTR: ctypes.char.ptr,
+ LPCSTR: ctypes.char.ptr,
+ LPTSTR: ctypes.jschar.ptr, // UNICODE
+ LPCTSTR: ctypes.jschar.ptr,
+ LPCWSTR: ctypes.jschar.ptr,
+ LPWSTR: ctypes.jschar.ptr, // WCHAR
+ LRESULT: LONG_PTR_T,
+ WPARAM: UINT_PTR_T,
+ LPARAM: LONG_PTR_T,
+
+ 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))))
+ */
+ MAKEINTRESOURCE: function(i) {return this.LPWSTR(i); }
+
+};
diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm
new file mode 100644
index 0000000..9d04b56
--- /dev/null
+++ b/src/modules/ctypes/winnt/user32.jsm
@@ -0,0 +1,45 @@
+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/types.jsm");
+
+function user32_defines(lib) {
+
+ lib.lazy_bind("GetWindowTextW", ctypes.int, win_t.HWND, win_t.LPTSTR, ctypes.int);
+ lib.lazy_bind("FindWindowW", win_t.HWND, win_t.LPCTSTR, win_t.LPCTSTR);
+
+ lib.lazy_bind("SendMessageW", win_t.LRESULT, win_t.HWND, win_t.UINT, win_t.WPARAM, win_t.WPARAM);
+ this.WM_GETICON = 0x007F;
+ this.ICON_SMALL = 0;
+ this.ICON_BIG = 1;
+ this.ICON_SMALL2 = 2;
+
+ lib.lazy_bind("GetClassLongPtrW", win_t.ULONG_PTR, win_t.HWND, ctypes.int);
+ lib.lazy_bind("GetClassLongW", win_t.DWORD, win_t.HWND, ctypes.int); // 32-bits
+ this.GetClassLong = is64bit ? this.GetClassLongPtrW : this.GetClassLongW;
+ this.GCLP_HICONSM = -34;
+
+ lib.lazy_bind("LoadIconW", win_t.HICON, win_t.HINSTANCE, win_t.LPCTSTR); // superseeded by LoadImage
+ this.IDI_APPLICATION = 32512;
+
+ lib.lazy_bind("LoadImageW", win_t.HANDLE, win_t.HINSTANCE, win_t.LPCTSTR,
+ win_t.UINT, ctypes.int, ctypes.int, win_t.UINT);
+ 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;
+
+}
+
+new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);
diff --git a/src/modules/logging.jsm b/src/modules/logging.jsm
index 1b03300..0801c31 100644
--- a/src/modules/logging.jsm
+++ b/src/modules/logging.jsm
@@ -6,7 +6,9 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
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_RESET = "\033[m";
@@ -77,25 +79,10 @@ firetray.Logging = {
setupLogging: function(loggerName) {
// lifted from log4moz.js
- function SimpleFormatter(dateFormat) {
- if (dateFormat)
- this.dateFormat = dateFormat;
- }
+ function SimpleFormatter() {}
SimpleFormatter.prototype = {
__proto__: Log4Moz.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) {
let messageString = "";
if (message.hasOwnProperty("message"))
@@ -108,7 +95,9 @@ firetray.Logging = {
([,mo] in Iterator(message.messageObjects))].join(" ");
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 + " " +
messageString + "\n";
@@ -119,10 +108,7 @@ firetray.Logging = {
}
};
- function ColorTermFormatter(dateFormat) {
- if (dateFormat)
- this.dateFormat = dateFormat;
- }
+ function ColorTermFormatter() {}
ColorTermFormatter.prototype = {
__proto__: SimpleFormatter.prototype,
@@ -141,15 +127,19 @@ firetray.Logging = {
this._logger.level = Log4Moz.Level[FIRETRAY_LOG_LEVEL];
// A console appender outputs to the JS Error Console
- let dateFormat = "%T";
- let simpleFormatter = new SimpleFormatter(dateFormat);
+ let simpleFormatter = new SimpleFormatter();
let capp = new Log4Moz.ConsoleAppender(simpleFormatter);
capp.level = Log4Moz.Level["Debug"];
this._logger.addAppender(capp);
// A dump appender outputs to standard out
- let colorFormatter = new ColorTermFormatter(dateFormat);
- let dapp = new Log4Moz.DumpAppender(colorFormatter);
+ let dumpFormatter;
+ if (Services.appinfo.OS.match(/(^Linux|^Darwin|BSD$)/)) {
+ dumpFormatter = new ColorTermFormatter();
+ } else {
+ dumpFormatter = new SimpleFormatter();
+ }
+ let dapp = new Log4Moz.DumpAppender(dumpFormatter);
dapp.level = Log4Moz.Level["Debug"];
this._logger.addAppender(dapp);
},
diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm
new file mode 100644
index 0000000..f47fa58
--- /dev/null
+++ b/src/modules/winnt/FiretrayStatusIcon.jsm
@@ -0,0 +1,68 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+var EXPORTED_SYMBOLS = [ "firetray" ];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/ctypes.jsm");
+// Cu.import("resource://firetray/ctypes/linux/pangocairo.jsm");
+Cu.import("resource://firetray/commons.js");
+// firetray.Handler.subscribeLibsForClosing([pangocairo]);
+
+let log = firetray.Logging.getLogger("firetray.StatusIcon");
+
+if ("undefined" == typeof(firetray.Handler))
+ log.error("This module MUST be imported from/after FiretrayHandler !");
+
+
+firetray.StatusIcon = {
+ initialized: false,
+ callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION
+ trayIcon: null,
+ themedIconApp: null,
+ themedIconNewMail: null,
+ prefAppIconNames: null,
+ prefNewMailIconNames: null,
+ defaultAppIconName: null,
+ defaultNewMailIconName: null,
+
+ init: function() {
+ this.FILENAME_BLANK = firetray.Utils.chromeToPath(
+ "chrome://firetray/skin/blank-icon.png");
+
+ log.warn("YEAH! From Windobe!");
+
+ this.initialized = true;
+ return true;
+ },
+
+ shutdown: function() {
+ log.debug("Disabling StatusIcon");
+ this.initialized = false;
+ },
+}; // firetray.StatusIcon
+
+firetray.Handler.setIconImageDefault = function() {
+ log.debug("setIconImageDefault");
+};
+
+firetray.Handler.setIconImageNewMail = function() {
+};
+
+// firetray.Handler.setIconImageFromFile = firetray.StatusIcon.setIconImageFromFile;
+
+firetray.Handler.setIconTooltip = function(toolTipStr) {
+};
+
+firetray.Handler.setIconTooltipDefault = function() {
+};
+
+firetray.Handler.setIconText = function(text, color) { // FIXME: function too long
+};
+
+firetray.Handler.setIconVisibility = function(visible) {
+};
diff --git a/src/modules/winnt/FiretrayWindow.jsm b/src/modules/winnt/FiretrayWindow.jsm
new file mode 100644
index 0000000..eb6b7fe
--- /dev/null
+++ b/src/modules/winnt/FiretrayWindow.jsm
@@ -0,0 +1,310 @@
+/* -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* GdkWindow and GtkWindow are totally different things. A GtkWindow is a
+ "standalone" window. A GdkWindow is just a region on the screen that can
+ capture events and has certain attributes (such as a cursor, and a coordinate
+ system). Basically a GdkWindow is an X window, in the Xlib sense, and
+ GtkWindow is a widget used for a particular UI effect.
+ (http://mail.gnome.org/archives/gtk-app-devel-list/1999-January/msg00138.html) */
+
+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/types.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/commons.js");
+firetray.Handler.subscribeLibsForClosing([kernel32, shell32, user32]);
+
+let log = firetray.Logging.getLogger("firetray.Window");
+
+if ("undefined" == typeof(firetray.Handler))
+ log.error("This module MUST be imported from/after FiretrayHandler !");
+
+const Services2 = {};
+XPCOMUtils.defineLazyServiceGetter(
+ Services2,
+ "uuid",
+ "@mozilla.org/uuid-generator;1",
+ "nsIUUIDGenerator"
+);
+
+const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
+const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
+
+// // NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
+// // "evolving" after a while (maybe due to back and forth conversion). So we
+// // need to store them into a real ctypes array !
+// firetray.Handler.gtkWindows = new ctypesMap(gtk.GtkWindow.ptr),
+
+
+firetray.Window = {
+ signals: {'focus-in': {callback: {}, handler: {}}},
+
+ init: function() {
+ this.initialized = true;
+ },
+
+ shutdown: function() {
+ this.initialized = false;
+ },
+
+ show: function(xid) {
+ log.debug("show xid="+xid);
+ },
+
+ hide: function(xid) {
+ log.debug("hide");
+ },
+
+ startupHide: function(xid) {
+ log.debug('startupHide: '+xid);
+ },
+
+ setVisibility: function(xid, visibility) {
+ },
+
+}; // firetray.Window
+
+
+///////////////////////// firetray.Handler overriding /////////////////////////
+
+/** debug facility */
+firetray.Handler.dumpWindows = function() {
+ log.debug(firetray.Handler.windowsCount);
+ for (let winId in firetray.Handler.windows) log.info(winId+"="+firetray.Handler.gtkWindows.get(winId));
+};
+
+firetray.Handler.getWindowIdFromChromeWindow = firetray.Window.getXIDFromChromeWindow;
+
+firetray.Handler.registerWindow = function(win) {
+ log.debug("register window");
+
+ // TESTING
+ let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
+ let nativeHandle = baseWin.nativeHandle; // Moz' private pointer to the GdkWindow
+ log.info("nativeHandle="+nativeHandle);
+
+ log.info("size="+ctypes.size_t.size);
+ log.info("psize="+ctypes.voidptr_t.size);
+ log.info("osvi size="+kernel32.OSVERSIONINFOEXW.size);
+
+ let osvi = new kernel32.OSVERSIONINFOEXW();
+ osvi.dwOSVersionInfoSize = kernel32.OSVERSIONINFOEXW.size;
+ if (kernel32.GetVersionExW(osvi.address())) {
+ log.debug("osvi.dwMajorVersion="+osvi.dwMajorVersion);
+ log.debug("osvi.dwMinorVersion="+osvi.dwMinorVersion);
+ }
+
+ /*
+ * Windows 8 6.2
+ * Windows 7 6.1
+ * Windows Vista 6.0
+ * Windows XP 5.1
+ */
+ let version = osvi.dwMajorVersion*10 + osvi.dwMinorVersion; // if (version >= 51)
+
+ let nid = new shell32.NOTIFYICONDATAW();
+ nid.cbSize = shell32.NOTIFYICONDATAW.size;
+
+ let hwnd = user32.FindWindowW("MozillaWindowClass", win.document.title);
+ log.debug("hwnd FindWindow="+hwnd);
+
+/*
+ let hwnd = new ctypes.voidptr_t(ctypes.UInt64(nativeHandle));
+ log.debug("hwnd nativeHandle="+hwnd);
+*/
+
+ const BUF_SIZE = 255;
+ let buffer_t = ctypes.jschar.array(BUF_SIZE); // LPTSTR
+
+ let title = new buffer_t();
+ let len = user32.GetWindowTextW(hwnd, title, BUF_SIZE);
+ log.error("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
+ if (len) {
+ log.info("title="+title.readString());
+ }
+
+/*
+ let consoleWin = kernel32.GetConsoleWindow();
+ log.error("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
+ log.info("consoleWin="+consoleWin);
+ len = user32.GetWindowTextW(consoleWin, title, 127);
+ log.error("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
+ log.debug("len="+len);
+ log.info("title="+title.readString());
+
+ len = kernel32.GetConsoleTitleW(title, win_t.DWORD(127));
+ log.error("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
+ log.debug("len="+len);
+ log.debug("len type="+typeof(len)); // "object" ???
+ if (len) {
+ log.info("consoleTitle="+title.readString());
+ }
+*/
+
+ let result = user32.SendMessageW(hwnd, user32.WM_GETICON, user32.ICON_SMALL, 0);
+ // result is a ctypes.Int64. So we need to create a CData from it before
+ // casting it.
+ let icon = ctypes.cast(win_t.LRESULT(result), win_t.HICON);
+ let NULL = win_t.HICON(null);
+ log.debug("SendMessageW winLastError="+ctypes.winLastError);
+ if (firetray.js.strEquals(icon, NULL)) { // OS default icon
+ result = user32.GetClassLong(hwnd, user32.GCLP_HICONSM);
+ icon = ctypes.cast(win_t.ULONG_PTR(result), win_t.HICON);
+ log.debug("GetClassLong winLastError="+ctypes.winLastError);
+ }
+ if (firetray.js.strEquals(icon, NULL)) { // from the first resource -> ERROR_RESOURCE_TYPE_NOT_FOUND(1813)
+ icon = user32.LoadIconW(kernel32.GetModuleHandleW(null),
+ win_t.MAKEINTRESOURCE(0));
+ log.debug("LoadIconW module winLastError="+ctypes.winLastError);
+ }
+ if (firetray.js.strEquals(icon, NULL)) { // OS default icon
+ icon = user32.LoadIconW(null, win_t.MAKEINTRESOURCE(user32.IDI_APPLICATION));
+ log.debug("LoadIconW default winLastError="+ctypes.winLastError);
+ }
+ log.debug("icon="+icon);
+
+// BOOL mintrayr_CreateIcon(void *handle, mouseevent_callback_t callback)
+// {
+// HWND hwnd = (HWND)handle;
+// if (!hwnd) {
+// return FALSE;
+// }
+
+// SetupWnd(hwnd);
+
+// NOTIFYICONDATAW *iconData = new(std::nothrow) NOTIFYICONDATAW;
+// if (!iconData) {
+// return FALSE;
+// }
+// // Init the icon data according to MSDN
+// iconData->cbSize = sizeof(NOTIFYICONDATAW);
+
+// // Copy the title
+// if (GetWindowText(hwnd, iconData->szTip, 127)) {
+// iconData->szTip[127] = '\0'; // Better be safe than sorry :p
+// }
+// else{
+// iconData->szTip[0] = '\0';
+// }
+
+// // Get the window icon
+// HICON icon = reinterpret_cast(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
+// if (icon == 0) {
+// // Alternative method. Get from the window class
+// icon = reinterpret_cast(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
+// }
+// // Alternative method: get the first icon from the main module (executable image of the process)
+// if (icon == 0) {
+// icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
+// }
+// // Alternative method. Use OS default icon
+// if (icon == 0) {
+// icon = ::LoadIcon(0, IDI_APPLICATION);
+// }
+// iconData->hIcon = icon;
+
+// // Set the rest of the members
+// iconData->hWnd = hwnd;
+// iconData->uCallbackMessage = WM_TRAYMESSAGE;
+// iconData->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+// iconData->uVersion = 5;
+
+// // Install the icon
+// ::Shell_NotifyIconW(NIM_ADD, iconData);
+// ::Shell_NotifyIconW(NIM_SETVERSION, iconData);
+
+// SetupWnd(hwnd);
+// ::SetPropW(hwnd, kIconData, reinterpret_cast(iconData));
+// ::SetPropW(hwnd, kIconMouseEventProc, reinterpret_cast(callback));
+// ::SetPropW(hwnd, kIcon, reinterpret_cast(0x1));
+
+ return;
+
+ // register
+ let [whndbaseWin, gtkWin, gdkWin, xid] = firetray.Window.getWindowsFromChromeWindow(win);
+ this.windows[xid] = {};
+ this.windows[xid].chromeWin = win;
+ this.windows[xid].baseWin = baseWin;
+ firetray.Window.checkSubscribedEventMasks(xid);
+ try {
+ this.gtkWindows.insert(xid, gtkWin);
+ this.gdkWindows.insert(xid, gdkWin);
+ firetray.PopupMenu.addWindowItem(xid);
+ } catch (x) {
+ if (x.name === "RangeError") // instanceof not working :-(
+ win.alert(x+"\n\nYou seem to have more than "+FIRETRAY_WINDOW_COUNT_MAX
+ +" windows open. This breaks FireTray and most probably "
+ +firetray.Handler.appName+".");
+ }
+ this.windowsCount += 1;
+ // NOTE: no need to check for window state to set visibility because all
+ // windows *are* shown at startup
+ firetray.Window.updateVisibility(xid, true);
+ log.debug("window "+xid+" registered");
+ // NOTE: shouldn't be necessary to gtk_widget_add_events(gtkWin, gdk.GDK_ALL_EVENTS_MASK);
+
+ try {
+ // 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
+
+ this.windows[xid].filterWindowCb = gdk.GdkFilterFunc_t(firetray.Window.filterWindow);
+ gdk.gdk_window_add_filter(gdkWin, this.windows[xid].filterWindowCb, null);
+ if (!firetray.Handler.appStarted) {
+ this.windows[xid].startupFilterCb = gdk.GdkFilterFunc_t(firetray.Window.startupFilter);
+ gdk.gdk_window_add_filter(gdkWin, this.windows[xid].startupFilterCb, null);
+ }
+
+ firetray.Window.attachOnFocusInCallback(xid);
+ if (firetray.Handler.isChatEnabled() && firetray.Chat.initialized) {
+ firetray.Chat.attachSelectListeners(win);
+ }
+
+ } catch (x) {
+ firetray.Window.unregisterWindowByXID(xid);
+ log.error(x);
+ return null;
+ }
+
+ log.debug("AFTER"); firetray.Handler.dumpWindows();
+ return xid;
+};
+
+firetray.Handler.unregisterWindow = function(win) {
+ log.debug("unregister window");
+ let xid = firetray.Window.getXIDFromChromeWindow(win);
+ return firetray.Window.unregisterWindowByXID(xid);
+};
+
+firetray.Handler.showWindow = firetray.Window.show;
+firetray.Handler.hideWindow = firetray.Window.hide;
+
+firetray.Handler.showHideAllWindows = function(gtkStatusIcon, userData) {
+ log.debug("showHideAllWindows: "+userData);
+ // NOTE: showHideAllWindows being a callback, we need to use
+ // 'firetray.Handler' explicitely instead of 'this'
+
+ log.debug("visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
+ log.debug("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();
+ }
+
+ let stopPropagation = true;
+ return stopPropagation;
+};
diff --git a/testing/xtypes.c b/testing/xtypes.c
index 26e8841..307533a 100644
--- a/testing/xtypes.c
+++ b/testing/xtypes.c
@@ -7,6 +7,7 @@
int main(int argc, char **argv) {
printf("sizeof(void*)=%d\n",sizeof(void*));
printf("sizeof(char)=%d\n",sizeof(char));
+ printf("sizeof(short)=%d\n",sizeof(short));
printf("sizeof(int)=%d\n",sizeof(int));
printf("sizeof(long)=%d\n",sizeof(long));
printf("sizeof(unsigned_long)=%d\n",sizeof(unsigned long));