* refactor testing code

* create hidden proxy window (corresponding to our unique tray icon)
This commit is contained in:
foudfou 2013-11-22 23:05:43 +01:00
parent d358416414
commit 083304cd56
8 changed files with 252 additions and 97 deletions

View File

@ -70,6 +70,8 @@ firetray.Handler = {
log.debug('FiretrayWindow imported');
break;
case "WINNT":
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
log.debug('FiretrayWin32 imported');
Cu.import("resource://firetray/winnt/FiretrayStatusIcon.jsm");
log.debug('FiretrayStatusIcon imported');
Cu.import("resource://firetray/winnt/FiretrayWindow.jsm");

View File

@ -31,6 +31,9 @@ function kernel32_defines(lib) {
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);
}
new ctypes_library(KERNEL32_LIBNAME, KERNEL32_ABIS, kernel32_defines, this);

View File

@ -54,6 +54,22 @@ function shell32_defines(lib) {
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

View File

@ -46,8 +46,7 @@ function user32_defines(lib) {
lib.lazy_bind("LoadIconW", win32.HICON, win32.HINSTANCE, win32.LPCTSTR); // superseeded by LoadImage
this.IDI_APPLICATION = 32512;
lib.lazy_bind("LoadImageW", win32.HANDLE, win32.HINSTANCE, win32.LPCTSTR,
win32.UINT, ctypes.int, ctypes.int, win32.UINT);
lib.lazy_bind("LoadImageW", win32.HANDLE, win32.HINSTANCE, win32.LPCTSTR, win32.UINT, ctypes.int, ctypes.int, win32.UINT);
this.LR_CREATEDIBSECTION = 0x00002000;
this.LR_DEFAULTCOLOR = 0x00000000;
this.LR_DEFAULTSIZE = 0x00000040;
@ -58,9 +57,9 @@ function user32_defines(lib) {
this.LR_SHARED = 0x00008000;
this.LR_VGACOLOR = 0x00000080;
lib.lazy_bind("SetWindowLongPtrW", win32.LONG_PTR , win32.HWND, ctypes.int, win32.LONG_PTR);
lib.lazy_bind("SetWindowLongW", win32.LONG , win32.HWND, ctypes.int, win32.LONG);
this.SetWindowLong = is64bit ? this.SetWindowLongPtrW : this.SetWindowLongW;
// SetWindowLongPtrW aliases SetWindowLongW with the correct signature thank
// win32.LONG_PTR
lib.lazy_bind("SetWindowLongW", win32.LONG_PTR , win32.HWND, ctypes.int, win32.LONG_PTR);
this.GWL_EXSTYLE = -20;
this.GWLP_HINSTANCE = -6;
this.GWLP_ID = -12;
@ -75,6 +74,58 @@ function user32_defines(lib) {
lib.lazy_bind("CallWindowProcW", win32.LRESULT, this.WNDPROC, 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("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);
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);
}
new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);

View File

@ -5,10 +5,12 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/ctypes.jsm");
Cu.import("resource://firetray/ctypes/ctypes-utils.jsm");
const INT_PTR_T = is64bit ? ctypes.int64_t : ctypes.int;
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, ctypes.int32_t ?
const WORD_T = ctypes.unsigned_short;
var win32 = {
@ -24,17 +26,22 @@ var win32 = {
BOOL: ctypes.bool,
BYTE: ctypes.unsigned_char,
UINT: ctypes.unsigned_int,
WORD: ctypes.unsigned_short,
WORD: WORD_T,
DWORD: ctypes.unsigned_long,
PVOID: ctypes.voidptr_t,
LPVOID: ctypes.voidptr_t,
LONG: ctypes.long,
LONG_PTR: LONG_PTR_T,
ULONG_PTR: ULONG_PTR_T,
SIZE_T: ULONG_PTR_T,
ATOM: WORD_T,
HWND: HANDLE_T,
HICON: HANDLE_T,
HINSTANCE: HANDLE_T,
HMODULE: HANDLE_T,
HMENU: HANDLE_T,
HBRUSH: HANDLE_T, // HICON
HCURSOR: HANDLE_T,
TCHAR: ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t: jschar
LPSTR: ctypes.char.ptr,
LPCSTR: ctypes.char.ptr,
@ -45,6 +52,7 @@ var win32 = {
LRESULT: LONG_PTR_T,
WPARAM: UINT_PTR_T,
LPARAM: LONG_PTR_T,
FARPROC: ctypes.voidptr_t, // typedef INT_PTR (FAR WINAPI *FARPROC)();
GUID: ctypes.StructType("GUID", [
{ "Data1": ctypes.unsigned_long },
@ -59,6 +67,10 @@ var win32 = {
*/
MAKEINTRESOURCE: function(i) {return this.LPWSTR(i); },
_T: function(str) {
return ctypes.jschar.array()(str);
},
ERROR_INVALID_WINDOW_HANDLE: 1400,
ERROR_RESOURCE_TYPE_NOT_FOUND: 1813,

View File

@ -9,9 +9,13 @@ 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/ctypes/winnt/win32.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([pangocairo]);
firetray.Handler.subscribeLibsForClosing([kernel32, shell32, user32]);
let log = firetray.Logging.getLogger("firetray.StatusIcon");
@ -34,7 +38,7 @@ firetray.StatusIcon = {
this.FILENAME_BLANK = firetray.Utils.chromeToPath(
"chrome://firetray/skin/blank-icon.png");
log.warn("YEAH! From Windobe!");
this.create();
this.initialized = true;
return true;
@ -44,6 +48,91 @@ firetray.StatusIcon = {
log.debug("Disabling StatusIcon");
this.initialized = false;
},
create: function() {
let hwnd_hidden = this.createHiddenWindow();
// 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);
let nid = new shell32.NOTIFYICONDATAW();
nid.cbSize = shell32.NOTIFYICONDATAW_SIZE();
log.debug("SIZE="+nid.cbSize);
nid.szTip = firetray.Handler.appName;
nid.hIcon = this.getIconFromWindow(hwnd_hidden_moz);
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;
/*
// string is truncate to size of buffer and null-terminated. nid.szTip is
// initialized automatically by ctypes
let nMaxCount = 127;
let len = user32.GetWindowTextW(hwnd, nid.szTip, nMaxCount);
log.debug("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
if (len != 0) {
log.info("nid.szTip="+nid.szTip.readString());
}
*/
// 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)
shell32.Shell_NotifyIconW(shell32.NIM_SETVERSION, nid.address());
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
},
createHiddenWindow: function() {
this.callbacks.hiddenWinProc = user32.WNDPROC(firetray.StatusIcon.hiddenWindowProc);
let hwnd_hidden = user32.CreateWindowExW(
0, win32.LPCTSTR(firetray.Win32.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);
let procPrev = user32.SetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC,
ctypes.cast(this.callbacks.hiddenWinProc, win32.LONG_PTR));
log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
return hwnd_hidden;
},
hiddenWindowProc: function(hWnd, uMsg, wParam, lParam) {
// ... do something smart with this event!
return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
},
getIconFromWindow: function(hwnd) {
rv = 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 to a HICON.
let icon = ctypes.cast(win32.LRESULT(rv), win32.HICON);
let NULL = win32.HICON(null); // for comparison only
log.debug("SendMessageW winLastError="+ctypes.winLastError);
if (firetray.js.strEquals(icon, NULL)) { // 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 (firetray.js.strEquals(icon, NULL)) { // 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 (firetray.js.strEquals(icon, NULL)) { // 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;
}
}; // firetray.StatusIcon
firetray.Handler.setIconImageDefault = function() {

View File

@ -0,0 +1,52 @@
/* -*- 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");
if ("undefined" == typeof(firetray.Handler))
log.error("This module MUST be imported from/after FiretrayHandler !");
const kMessageTray = "_FIRETRAY_TrayMessage";
const kMessageCallback = "_FIRETRAY_TrayCallback";
function Win32Env() {
this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
// We register this as well, as we cannot know which WM_USER values are
// already taken
this.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray);
this.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback);
log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK);
this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll
log.debug("hInstance="+this.hInstance);
/*
let hUser = kernel32.LoadLibraryW("user32");
let defWindowProcW = kernel32.GetProcAddress(hUser, "DefWindowProcW");
log.debug("defWindowProcW="+defWindowProcW);
log.debug("_______________DefWindowProcW="+user32.DefWindowProcW);
*/
this.WNDCLASS_NAME = "FireTrayHiddenWindowClass";
let wndClass = new user32.WNDCLASSEXW();
wndClass.cbSize = user32.WNDCLASSEXW.size;
wndClass.lpfnWndProc = ctypes.cast(user32.DefWindowProcW, user32.WNDPROC);
wndClass.hInstance = this.hInstance;
wndClass.lpszClassName = win32._T(this.WNDCLASS_NAME);
this.WNDCLASS_ATOM = user32.RegisterClassExW(wndClass.address());
log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM);
}
firetray.Win32 = new Win32Env();

View File

@ -1,12 +1,5 @@
/* -*- 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;
@ -18,11 +11,10 @@ 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/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([kernel32, shell32, user32]);
firetray.Handler.subscribeLibsForClosing([user32]);
let log = firetray.Logging.getLogger("firetray.Window");
@ -72,6 +64,22 @@ firetray.Window = {
setVisibility: function(xid, visibility) {
},
/* if Administrator, accept messages from applications running in a lower
privilege level */
acceptAllMessages: function(hwnd) {
let rv = null;
if (win32.WINVER >= win32.WIN_VERSIONS["7"]) {
rv = user32.ChangeWindowMessageFilterEx(hwnd, WM_TASKBARCREATED, user32.MSGFLT_ALLOW, null);
log.debug("ChangeWindowMessageFilterEx res="+rv+" winLastError="+ctypes.winLastError);
} else if (win32.WINVER >= win32.WINVER["Vista"]) {
rv = user32.ChangeWindowMessageFilter(WM_TASKBARCREATED, user32.MSGFLT_ADD);
log.debug("ChangeWindowMessageFilter res="+rv+" winLastError="+ctypes.winLastError);
} else {
log.error("Unsupported windoz version "+win32.WINVER);
}
return rv;
}
}; // firetray.Window
@ -95,84 +103,6 @@ firetray.Handler.registerWindow = function(win) {
user32.FindWindowW("MozillaWindowClass", win.document.title);
log.debug("=== hwnd="+hwnd);
// Get TaskbarCreated
const WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
// We register this as well, as we cannot know which WM_USER values are already taken
const kTrayMessage = "_MINTRAYR_TrayMessageW";
const kTrayCallback = "_MINTRAYR_TrayCallbackW";
const WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kTrayMessage);
const WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kTrayCallback);
log.debug("WM_*="+WM_TASKBARCREATED+" "+WM_TRAYMESSAGE+" "+WM_TRAYCALLBACK);
/* if Administrator, accept messages from applications running in a lower
privilege level */
let rv;
if (win32.WINVER >= win32.WIN_VERSIONS["7"]) {
rv = user32.ChangeWindowMessageFilterEx(hwnd, WM_TASKBARCREATED, user32.MSGFLT_ALLOW, null);
log.debug("ChangeWindowMessageFilterEx res="+rv+" winLastError="+ctypes.winLastError);
} else if (win32.WINVER >= win32.WINVER["Vista"]) {
rv = user32.ChangeWindowMessageFilter(WM_TASKBARCREATED, user32.MSGFLT_ADD);
log.debug("ChangeWindowMessageFilter res="+rv+" winLastError="+ctypes.winLastError);
} else {
log.error("Unsupported windoz version "+win32.WINVER);
}
let nid = new shell32.NOTIFYICONDATAW();
if (win32.WINVER >= win32.WIN_VERSIONS["Vista"]) {
nid.cbSize = shell32.NOTIFYICONDATAW.size;
} else if (win32.WINVER >= win32.WIN_VERSIONS["XP"]) {
nid.cbSize = shell32.NOTIFYICONDATAW_V3_SIZE;
} else if (win32.WINVER >= win32.WIN_VERSIONS["2K"]) {
nid.cbSize = shell32.NOTIFYICONDATAW_V2_SIZE;
} else {
nid.cbSize = shell32.NOTIFYICONDATAW_V1_SIZE;
}
log.debug("SIZE="+nid.cbSize);
// string is truncate to size of buffer and null-terminated. nid.szTip is
// initialized automatically by ctypes
let nMaxCount = 127;
let len = user32.GetWindowTextW(hwnd, nid.szTip, nMaxCount);
log.error("errno="+ctypes.errno+" winLastError="+ctypes.winLastError);
if (len != 0) {
log.info("nid.szTip="+nid.szTip.readString());
}
rv = 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 to a HICON.
let icon = ctypes.cast(win32.LRESULT(rv), win32.HICON);
let NULL = win32.HICON(null); // for comparison only
log.debug("SendMessageW winLastError="+ctypes.winLastError);
if (firetray.js.strEquals(icon, NULL)) { // 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 (firetray.js.strEquals(icon, NULL)) { // from the first resource -> ERROR_RESOURCE_TYPE_NOT_FOUND(1813)
icon = user32.LoadIconW(kernel32.GetModuleHandleW(null),
win32.MAKEINTRESOURCE(0));
log.debug("LoadIconW module winLastError="+ctypes.winLastError);
}
if (firetray.js.strEquals(icon, NULL)) { // OS default icon
icon = user32.LoadIconW(null, win32.MAKEINTRESOURCE(user32.IDI_APPLICATION));
log.debug("LoadIconW default winLastError="+ctypes.winLastError);
}
log.debug("=== icon="+icon);
nid.hIcon = icon;
nid.hwnd = hwnd;
nid.uCallbackMessage = WM_TRAYMESSAGE;
nid.uFlags = shell32.NIF_ICON | shell32.NIF_MESSAGE | shell32.NIF_TIP;
nid.uVersion = shell32.NOTIFYICON_VERSION_4; // 5 ?! niels
// 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)
shell32.Shell_NotifyIconW(shell32.NIM_SETVERSION, nid.address());
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
// SetupWnd(hwnd);
// ::SetPropW(hwnd, kIconData, reinterpret_cast<HANDLE>(iconData));
// ::SetPropW(hwnd, kIconMouseEventProc, reinterpret_cast<HANDLE>(callback));