mirror of
https://github.com/moparisthebest/FireTray
synced 2025-01-07 19:48:03 -05:00
* refactor testing code
* create hidden proxy window (corresponding to our unique tray icon)
This commit is contained in:
parent
d358416414
commit
083304cd56
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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() {
|
||||
|
52
src/modules/winnt/FiretrayWin32.jsm
Normal file
52
src/modules/winnt/FiretrayWin32.jsm
Normal 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();
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user