destroy tray icon, hidden window and window class on shutdown

This commit is contained in:
foudfou 2013-11-23 01:37:57 +01:00
parent 083304cd56
commit 8e78f45d56
5 changed files with 64 additions and 54 deletions

View File

@ -42,7 +42,7 @@ new ctypes_library(KERNEL32_LIBNAME, KERNEL32_ABIS, kernel32_defines, this);
let osvi = new kernel32.OSVERSIONINFOEXW();
osvi.dwOSVersionInfoSize = kernel32.OSVERSIONINFOEXW.size;
if (kernel32.GetVersionExW(osvi.address())) {
win32.WINVER = osvi.dwMajorVersion*10 + osvi.dwMinorVersion;
win32.WINVER = (+osvi.dwMajorVersion)*10 + (+osvi.dwMinorVersion); // ctypes.UInt64 objects!
} else {
Cu.ReportError("win version not found");
}

View File

@ -90,7 +90,9 @@ function user32_defines(lib) {
]);
lib.lazy_bind("RegisterClassExW", win32.ATOM, this.WNDCLASSEXW.ptr);
lib.lazy_bind("UnregisterClassW", win32.BOOL, win32.LPCTSTR, win32.HINSTANCE);
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);
lib.lazy_bind("DestroyWindow", win32.BOOL, win32.HWND);
this.CW_USEDEFAULT = ctypes.int(0x80000000); // -2147483648

View File

@ -26,13 +26,10 @@ if ("undefined" == typeof(firetray.Handler))
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,
notifyIconData: null,
hwndHidden: null,
WNDCLASS_NAME: "FireTrayHiddenWindowClass",
WNDCLASS_ATOM: null,
init: function() {
this.FILENAME_BLANK = firetray.Utils.chromeToPath(
@ -46,6 +43,9 @@ firetray.StatusIcon = {
shutdown: function() {
log.debug("Disabling StatusIcon");
this.destroy();
this.initialized = false;
},
@ -56,8 +56,7 @@ firetray.StatusIcon = {
let hwnd_hidden_moz = user32.FindWindowW("MozillaHiddenWindowClass", null);
log.debug("=== hwnd_hidden_moz="+hwnd_hidden_moz);
let nid = new shell32.NOTIFYICONDATAW();
nid = new shell32.NOTIFYICONDATAW();
nid.cbSize = shell32.NOTIFYICONDATAW_SIZE();
log.debug("SIZE="+nid.cbSize);
nid.szTip = firetray.Handler.appName;
@ -67,29 +66,23 @@ firetray.StatusIcon = {
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());
rv = shell32.Shell_NotifyIconW(shell32.NIM_SETVERSION, nid.address());
log.debug("Shell_NotifyIcon SETVERSION="+rv+" winLastError="+ctypes.winLastError);
this.notifyIconData = nid;
this.hwndHidden = hwnd_hidden;
},
createHiddenWindow: function() {
this.registerWindowClass();
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)
0, win32.LPCTSTR(this.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);
@ -99,11 +92,23 @@ firetray.StatusIcon = {
ctypes.cast(this.callbacks.hiddenWinProc, win32.LONG_PTR));
log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError);
firetray.Win32.acceptAllMessages(hwnd_hidden);
return hwnd_hidden;
},
hiddenWindowProc: function(hWnd, uMsg, wParam, lParam) {
registerWindowClass: function() {
let wndClass = new user32.WNDCLASSEXW();
wndClass.cbSize = user32.WNDCLASSEXW.size;
wndClass.lpfnWndProc = ctypes.cast(user32.DefWindowProcW, user32.WNDPROC);
wndClass.hInstance = firetray.Win32.hInstance;
wndClass.lpszClassName = win32._T(this.WNDCLASS_NAME);
this.WNDCLASS_ATOM = user32.RegisterClassExW(wndClass.address());
log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM);
},
hiddenWindowProc: function(hWnd, uMsg, wParam, lParam) {
log.debug("HiddenWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
// ... do something smart with this event!
return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam);
@ -131,6 +136,23 @@ firetray.StatusIcon = {
}
log.debug("=== icon="+icon);
return icon;
},
destroyHiddenWindow: function() {
let rv = user32.DestroyWindow(this.hwndHidden);
rv = this.unregisterWindowClass();
log.debug("Hidden window removed");
},
unregisterWindowClass: function() {
return user32.UnregisterClassW(win32.LPCTSTR(this.WNDCLASS_ATOM), firetray.Win32.hInstance);
},
destroy: function() {
let rv = shell32.Shell_NotifyIconW(shell32.NIM_DELETE, this.notifyIconData.address());
log.debug("Shell_NotifyIcon DELETE="+rv+" winLastError="+ctypes.winLastError);
this.destroyHiddenWindow();
}
}; // firetray.StatusIcon

View File

@ -32,21 +32,23 @@ function Win32Env() {
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);
*/
/* if Administrator, accept messages from applications running in a lower
privilege level */
this.acceptAllMessages = function(hwnd) {
let rv = null;
log.info(win32.WINVER+" >= "+win32.WIN_VERSIONS["7"]);
if (win32.WINVER >= win32.WIN_VERSIONS["7"]) {
rv = user32.ChangeWindowMessageFilterEx(hwnd, firetray.Win32.WM_TASKBARCREATED, user32.MSGFLT_ALLOW, null);
log.debug("ChangeWindowMessageFilterEx res="+rv+" winLastError="+ctypes.winLastError);
} else if (win32.WINVER >= win32.WINVER["Vista"]) {
rv = user32.ChangeWindowMessageFilter(firetray.Win32.WM_TASKBARCREATED, user32.MSGFLT_ADD);
log.debug("ChangeWindowMessageFilter res="+rv+" winLastError="+ctypes.winLastError);
} else {
// no UIPI
}
return rv;
};
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

@ -64,22 +64,6 @@ 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