From 8e78f45d56018538515bdc32df5f8c3f7e8e331f Mon Sep 17 00:00:00 2001 From: foudfou Date: Sat, 23 Nov 2013 01:37:57 +0100 Subject: [PATCH] destroy tray icon, hidden window and window class on shutdown --- src/modules/ctypes/winnt/kernel32.jsm | 2 +- src/modules/ctypes/winnt/user32.jsm | 2 + src/modules/winnt/FiretrayStatusIcon.jsm | 68 ++++++++++++++++-------- src/modules/winnt/FiretrayWin32.jsm | 30 ++++++----- src/modules/winnt/FiretrayWindow.jsm | 16 ------ 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/src/modules/ctypes/winnt/kernel32.jsm b/src/modules/ctypes/winnt/kernel32.jsm index 7b77d19..613523e 100644 --- a/src/modules/ctypes/winnt/kernel32.jsm +++ b/src/modules/ctypes/winnt/kernel32.jsm @@ -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"); } diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm index 45b686f..1a1d9c9 100644 --- a/src/modules/ctypes/winnt/user32.jsm +++ b/src/modules/ctypes/winnt/user32.jsm @@ -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 diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm index 52357e9..f92fe77 100644 --- a/src/modules/winnt/FiretrayStatusIcon.jsm +++ b/src/modules/winnt/FiretrayStatusIcon.jsm @@ -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 diff --git a/src/modules/winnt/FiretrayWin32.jsm b/src/modules/winnt/FiretrayWin32.jsm index 20175b3..2cfa089 100644 --- a/src/modules/winnt/FiretrayWin32.jsm +++ b/src/modules/winnt/FiretrayWin32.jsm @@ -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(); diff --git a/src/modules/winnt/FiretrayWindow.jsm b/src/modules/winnt/FiretrayWindow.jsm index 9a36619..6215a9b 100644 --- a/src/modules/winnt/FiretrayWindow.jsm +++ b/src/modules/winnt/FiretrayWindow.jsm @@ -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