diff --git a/src/modules/FiretrayHandler.jsm b/src/modules/FiretrayHandler.jsm index 162254b..993c8d9 100644 --- a/src/modules/FiretrayHandler.jsm +++ b/src/modules/FiretrayHandler.jsm @@ -327,7 +327,6 @@ firetray.Handler = { setIconVisibility: function(visible) {}, registerWindow: function(win) {}, unregisterWindow: function(win) {}, - getWindowIdFromChromeWindow: function(win) {}, hideWindow: function(winId) {}, showWindow: function(winId) {}, showHideAllWindows: function() {}, diff --git a/src/modules/FiretrayWindow.jsm b/src/modules/FiretrayWindow.jsm index 98bb1a5..4312267 100644 --- a/src/modules/FiretrayWindow.jsm +++ b/src/modules/FiretrayWindow.jsm @@ -29,4 +29,11 @@ FiretrayWindow.prototype = { win.visible = visibility; // nsIBaseWin.visibility always true :-( }, + getRegisteredWinIdFromChromeWindow: function(win) { + for (let wid in firetray.Handler.windows) + if (firetray.Handler.windows[wid].chromeWin === win) return wid; + log.error("unknown window while lookup"); + return null; + }, + }; diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm index 1a1d9c9..1f90dc8 100644 --- a/src/modules/ctypes/winnt/user32.jsm +++ b/src/modules/ctypes/winnt/user32.jsm @@ -57,6 +57,11 @@ function user32_defines(lib) { this.LR_SHARED = 0x00008000; this.LR_VGACOLOR = 0x00000080; + lib.lazy_bind("GetPropW", win32.HANDLE, win32.HWND, win32.LPCTSTR); + lib.lazy_bind("SetPropW", win32.BOOL, win32.HWND, win32.LPCTSTR, win32.HANDLE); + + lib.lazy_bind("GetWindowLongW", win32.LONG_PTR, win32.HWND, ctypes.int); + lib.lazy_bind("SetWindowLongW", win32.LONG_PTR , win32.HWND, ctypes.int, win32.LONG_PTR); // 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); @@ -71,7 +76,8 @@ function user32_defines(lib) { WinCbABI, win32.LRESULT, [win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM]).ptr; - lib.lazy_bind("CallWindowProcW", win32.LRESULT, this.WNDPROC, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM); + // lib.lazy_bind("CallWindowProcW", win32.LRESULT, this.WNDPROC, win32.HWND, win32.UINT, win32.WPARAM, win32.LPARAM); + lib.lazy_bind("CallWindowProcW", win32.LRESULT, ctypes.voidptr_t, 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", [ diff --git a/src/modules/ctypes/winnt/win32.jsm b/src/modules/ctypes/winnt/win32.jsm index 790ab23..af33350 100644 --- a/src/modules/ctypes/winnt/win32.jsm +++ b/src/modules/ctypes/winnt/win32.jsm @@ -5,97 +5,95 @@ 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 = { +var win32 = new function() { - WIN_VERSIONS: { // maj*10 + min + this.WIN_VERSIONS = { // maj*10 + min '8': 62, // 2012 '7': 61, // 2009 'Vista': 60, // 2007 'XP': 51, // 2001 '2K': 50, // 2000 - }, - WINVER: null, // initialized in kernel32.jsm + }; + this.WINVER = null; // initialized in kernel32.jsm - BOOL: ctypes.bool, - BYTE: ctypes.unsigned_char, - UINT: ctypes.unsigned_int, - 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, - 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, - FARPROC: ctypes.voidptr_t, // typedef INT_PTR (FAR WINAPI *FARPROC)(); + this.BOOL = ctypes.bool; + this.BYTE = ctypes.unsigned_char; + this.INT_PTR = is64bit ? ctypes.int64_t : ctypes.int; + this.UINT = ctypes.unsigned_int; + this.UINT_PTR = is64bit ? ctypes.uint64_t : ctypes.unsigned_int; + this.WORD = ctypes.unsigned_short; + this.DWORD = ctypes.unsigned_long; + this.PVOID = ctypes.voidptr_t; + this.LPVOID = ctypes.voidptr_t; + this.LONG = ctypes.long; + this.LONG_PTR = is64bit ? ctypes.int64_t : ctypes.long; + this.ULONG_PTR = is64bit ? ctypes.uint64_t : ctypes.unsigned_long; + this.SIZE_T = this.ULONG_PTR; + this.ATOM = this.WORD; + this.HANDLE = ctypes.voidptr_t; + this.HWND = this.HANDLE; + this.HICON = this.HANDLE; + this.HINSTANCE = this.HANDLE; + this.HMODULE = this.HANDLE; + this.HMENU = this.HANDLE; + this.HBRUSH = this.HICON; + this.HCURSOR = this.HANDLE; + this.TCHAR = ctypes.jschar, // Mozilla compiled with UNICODE/_UNICODE macros and wchar_t = jschar + this.LPSTR = ctypes.char.ptr; + this.LPCSTR = ctypes.char.ptr; + this.LPTSTR = ctypes.jschar.ptr; // UNICODE + this.LPCTSTR = ctypes.jschar.ptr; + this.LPCWSTR = ctypes.jschar.ptr; + this.LPWSTR = ctypes.jschar.ptr; // WCHAR + this.LRESULT = this.LONG_PTR; + this.WPARAM = this.UINT_PTR; + this.LPARAM = this.LONG_PTR; + this.FARPROC = ctypes.voidptr_t; // typedef INT_PTR (FAR WINAPI *FARPROC)(); - GUID: ctypes.StructType("GUID", [ + this.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); }, + this.MAKEINTRESOURCE = function(i) {return this.LPWSTR(i);}; - _T: function(str) { + this._T = function(str) { return ctypes.jschar.array()(str); - }, + }; - ERROR_INVALID_WINDOW_HANDLE: 1400, - ERROR_RESOURCE_TYPE_NOT_FOUND: 1813, + this.ERROR_INVALID_WINDOW_HANDLE = 1400; + this.ERROR_RESOURCE_TYPE_NOT_FOUND = 1813; // WinUser.h - WM_USER: 0x0400, + this.WM_USER = 0x0400; + this.WM_APP = 0x8000; - WM_CONTEXTMENU: 0x007B, + this.WM_CONTEXTMENU = 0x007B; - WM_MOUSEFIRST: 0x0200, - WM_MOUSEMOVE: 0x0200, - WM_LBUTTONDOWN: 0x0201, - WM_LBUTTONUP: 0x0202, - WM_LBUTTONDBLCLK: 0x0203, - WM_RBUTTONDOWN: 0x0204, - WM_RBUTTONUP: 0x0205, - WM_RBUTTONDBLCLK: 0x0206, - WM_MBUTTONDOWN: 0x0207, - WM_MBUTTONUP: 0x0208, - WM_MBUTTONDBLCLK: 0x0209, - WM_MOUSEWHEEL: 0x020A, - WM_XBUTTONDOWN: 0x020B, - WM_XBUTTONUP: 0x020C, - WM_XBUTTONDBLCLK: 0x020D, - WM_MOUSELAST: 0x020D, - WM_MOUSELAST: 0x020A, + this.WM_MOUSEFIRST = 0x0200; + this.WM_MOUSEMOVE = 0x0200; + this.WM_LBUTTONDOWN = 0x0201; + this.WM_LBUTTONUP = 0x0202; + this.WM_LBUTTONDBLCLK = 0x0203; + this.WM_RBUTTONDOWN = 0x0204; + this.WM_RBUTTONUP = 0x0205; + this.WM_RBUTTONDBLCLK = 0x0206; + this.WM_MBUTTONDOWN = 0x0207; + this.WM_MBUTTONUP = 0x0208; + this.WM_MBUTTONDBLCLK = 0x0209; + this.WM_MOUSEWHEEL = 0x020A; + this.WM_XBUTTONDOWN = 0x020B; + this.WM_XBUTTONUP = 0x020C; + this.WM_XBUTTONDBLCLK = 0x020D; + this.WM_MOUSELAST = 0x020D; + this.WM_MOUSELAST = 0x020A; }; diff --git a/src/modules/linux/FiretrayWindow.jsm b/src/modules/linux/FiretrayWindow.jsm index 1986776..3ff7ec5 100644 --- a/src/modules/linux/FiretrayWindow.jsm +++ b/src/modules/linux/FiretrayWindow.jsm @@ -53,13 +53,12 @@ var _find_data_t = ctypes.StructType("_find_data_t", [ // 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.Handler.gdkWindows = new ctypesMap(gdk.GdkWindow.ptr), -firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr), +firetray.Handler.gtkWindows = new ctypesMap(gtk.GtkWindow.ptr); +firetray.Handler.gdkWindows = new ctypesMap(gdk.GdkWindow.ptr); +firetray.Handler.gtkPopupMenuWindowItems = new ctypesMap(gtk.GtkImageMenuItem.ptr); firetray.Window = new FiretrayWindow(); - firetray.Window.signals = {'focus-in': {callback: {}, handler: {}}}; firetray.Window.init = function() { @@ -187,7 +186,7 @@ firetray.Window.getGtkWindowFromGdkWindow = function(gdkWin) { return gtkw; }; -/* consider using getXIDFromChromeWindow() if you only need the XID */ +/* consider using getRegisteredWinIdFromChromeWindow() if you only need the XID */ firetray.Window.getWindowsFromChromeWindow = function(win) { let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow"); let nativeHandle = baseWin.nativeHandle; // Moz' private pointer to the GdkWindow @@ -205,13 +204,6 @@ firetray.Window.getWindowsFromChromeWindow = function(win) { return [baseWin, gtkWin, gdkWin, xid]; }; -firetray.Window.getXIDFromChromeWindow = function(win) { - for (let xid in firetray.Handler.windows) - if (firetray.Handler.windows[xid].chromeWin === win) return xid; - log.error("unknown window while lookup"); - return null; -}; - firetray.Window.unregisterWindowByXID = function(xid) { if (!firetray.Handler.windows.hasOwnProperty(xid)) { log.error("can't unregister unknown window "+xid); @@ -656,8 +648,6 @@ firetray.Handler.dumpWindows = function() { 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"); @@ -713,7 +703,7 @@ firetray.Handler.registerWindow = function(win) { firetray.Handler.unregisterWindow = function(win) { log.debug("unregister window"); - let xid = firetray.Window.getXIDFromChromeWindow(win); + let xid = firetray.Window.getRegisteredWinIdFromChromeWindow(win); return firetray.Window.unregisterWindowByXID(xid); }; diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm index 53055b5..8c64283 100644 --- a/src/modules/winnt/FiretrayStatusIcon.jsm +++ b/src/modules/winnt/FiretrayStatusIcon.jsm @@ -20,9 +20,6 @@ Cu.import("resource://firetray/winnt/FiretrayWin32.jsm"); Cu.import("resource://firetray/commons.js"); firetray.Handler.subscribeLibsForClosing([kernel32, shell32, user32]); -const kMessageTray = "_FIRETRAY_TrayMessage"; -const kMessageCallback = "_FIRETRAY_TrayCallback"; - let log = firetray.Logging.getLogger("firetray.StatusIcon"); if ("undefined" == typeof(firetray.Handler)) @@ -33,7 +30,6 @@ firetray.StatusIcon = { initialized: false, callbacks: {}, // pointers to JS functions. MUST LIVE DURING ALL THE EXECUTION notifyIconData: null, - msg: {WM_TASKBARCREATED:null, WM_TRAYMESSAGE:null, WM_TRAYCALLBACK:null}, hwndProxy: null, WNDCLASS_NAME: "FireTrayHiddenWindowClass", WNDCLASS_ATOM: null, @@ -42,7 +38,6 @@ firetray.StatusIcon = { this.FILENAME_BLANK = firetray.Utils.chromeToPath( "chrome://firetray/skin/blank-icon.png"); - this.registerMessages(); this.create(); this.initialized = true; @@ -57,17 +52,6 @@ firetray.StatusIcon = { this.initialized = false; }, - registerMessages: function() { - this.msg.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated"); - this.msg.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray); - this.msg.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback); - log.debug("WM_*="+this.msg.WM_TASKBARCREATED+" "+this.msg.WM_TRAYMESSAGE+" "+this.msg.WM_TRAYCALLBACK); - }, - - unregisterMessages: function() { - // FIXME: TODO: - }, - create: function() { let hwnd_hidden = this.createProxyWindow(); @@ -81,7 +65,7 @@ firetray.StatusIcon = { nid.szTip = firetray.Handler.appName; nid.hIcon = this.getIconFromWindow(hwnd_hidden_moz); nid.hWnd = hwnd_hidden; - nid.uCallbackMessage = this.msg.WM_TRAYMESSAGE; + nid.uCallbackMessage = firetray.Win32.WM_TRAYMESSAGE; nid.uFlags = shell32.NIF_ICON | shell32.NIF_MESSAGE | shell32.NIF_TIP; nid.uVersion = shell32.NOTIFYICON_VERSION_4; @@ -98,8 +82,6 @@ firetray.StatusIcon = { createProxyWindow: function() { this.registerWindowClass(); - this.callbacks.hiddenWinProc = user32.WNDPROC(firetray.StatusIcon.proxyWindowProc); - let hwnd_hidden = user32.CreateWindowExW( 0, win32.LPCTSTR(this.WNDCLASS_ATOM), // lpClassName can also be _T(WNDCLASS_NAME) "Firetray Message Window", 0, @@ -107,8 +89,18 @@ firetray.StatusIcon = { null, null, firetray.Win32.hInstance, null); log.debug("CreateWindow="+!hwnd_hidden.isNull()+" winLastError="+ctypes.winLastError); + this.callbacks.proxyWndProc = user32.WNDPROC(firetray.StatusIcon.proxyWndProc); +/* + // TESTING + let proc = user32.GetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC); + log.debug(" proc="+proc.toString(16)+" winLastError="+ctypes.winLastError); + this.callbacks.procPrev = user32.WNDPROC( + user32.SetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC, + ctypes.cast(this.callbacks.proxyWndProc, win32.LONG_PTR)) + ); +*/ let procPrev = user32.SetWindowLongW(hwnd_hidden, user32.GWLP_WNDPROC, - ctypes.cast(this.callbacks.hiddenWinProc, win32.LONG_PTR)); + ctypes.cast(this.callbacks.proxyWndProc, win32.LONG_PTR)); log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError); firetray.Win32.acceptAllMessages(hwnd_hidden); @@ -126,13 +118,13 @@ firetray.StatusIcon = { log.debug("WNDCLASS_ATOM="+this.WNDCLASS_ATOM); }, - proxyWindowProc: function(hWnd, uMsg, wParam, lParam) { + proxyWndProc: function(hWnd, uMsg, wParam, lParam) { // log.debug("ProxyWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam); - if (uMsg === firetray.StatusIcon.msg.WM_TASKBARCREATED) { + if (uMsg === firetray.Win32.WM_TASKBARCREATED) { log.info("____________TASKBARCREATED"); - } else if (uMsg === firetray.StatusIcon.msg.WM_TRAYMESSAGE) { + } else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) { switch (+lParam) { case win32.WM_LBUTTONUP: @@ -152,6 +144,15 @@ firetray.StatusIcon = { } +/* + // CallWindowProcW() on a non-moz window works fine + let procPrev = firetray.StatusIcon.callbacks.procPrev; + log.debug(" procPrev="+procPrev); + let rv = user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam); + log.debug(" CallWindowProc="+rv); + return rv; +*/ + return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam); }, diff --git a/src/modules/winnt/FiretrayWin32.jsm b/src/modules/winnt/FiretrayWin32.jsm index 07b24ab..74d8c72 100644 --- a/src/modules/winnt/FiretrayWin32.jsm +++ b/src/modules/winnt/FiretrayWin32.jsm @@ -15,6 +15,9 @@ firetray.Handler.subscribeLibsForClosing([kernel32, user32]); let log = firetray.Logging.getLogger("firetray.Win32"); +const kMessageTray = "_FIRETRAY_TrayMessage"; +const kMessageCallback = "_FIRETRAY_TrayCallback"; + if ("undefined" == typeof(firetray.Handler)) log.error("This module MUST be imported from/after FiretrayHandler !"); @@ -23,11 +26,16 @@ function Win32Env() { this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll log.debug("hInstance="+this.hInstance); + this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated"); + this.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray); + this.WM_TRAYCALLBACK = user32.RegisterWindowMessageW(kMessageCallback); + log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK); + /* 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"]); + log.debug(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); diff --git a/src/modules/winnt/FiretrayWindow.jsm b/src/modules/winnt/FiretrayWindow.jsm index fe712d5..aeee4ba 100644 --- a/src/modules/winnt/FiretrayWindow.jsm +++ b/src/modules/winnt/FiretrayWindow.jsm @@ -6,8 +6,6 @@ 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/win32.jsm"); @@ -22,17 +20,17 @@ 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; +const kPropProcPrev = "_FIRETRAY_OLD_PROC"; + +// 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.wndProcs = new ctypesMap(user32.WNDPROC); +firetray.Handler.wndProcsOrig = new ctypesMap(user32.WNDPROC); + firetray.Window = new FiretrayWindow(); @@ -59,6 +57,50 @@ firetray.Window.startupHide = function(xid) { firetray.Window.setVisibility = function(xid, visibility) { }; +// wid will be used as a string most of the time (through f.Handler.windows mainly) +firetray.Window.hwndToHexStr = function(hWnd) { + return "0x" + ctypes.cast(hWnd, ctypes.uintptr_t).value.toString(16); +}; + +firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow + log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam); + + let proc = user32.GetWindowLongW(hWnd, user32.GWLP_WNDPROC); + log.debug(" proc="+proc.toString(16)+" winLastError="+ctypes.winLastError); + +try { + + let wid = firetray.Window.hwndToHexStr(hWnd); + // let procPrev = firetray.Handler.wndProcsOrig.get(wid); + // let procPrev = ctypes.cast(user32.GetPropW(hWnd, win32._T(kPropProcPrev)), user32.WNDPROC); + // let procPrev = user32.GetPropW(hWnd, win32._T(kPropProcPrev)); + log.debug(" wid="+wid+" prev="+procPrev); + + /* + * https://bugzilla.mozilla.org/show_bug.cgi?id=598679 + * https://bugzilla.mozilla.org/show_bug.cgi?id=671266 + */ + // let rv = user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam); + let rv = procPrev(hWnd, uMsg, wParam, lParam); + log.debug(" CallWindowProc="+rv); + return rv; + + } catch(error) { +log.error(error); + } + + // user32.SetWindowLongW(hWnd, user32.GWLP_WNDPROC, ctypes.cast(procPrev, win32.LONG_PTR)); + + // if (uMsg === win32.WM_USER) { + // log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam); + + // // return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam); + // } + + // return user32.DefWindowProcW(hWnd, uMsg, wParam, lParam); +}; + + ///////////////////////// firetray.Handler overriding ///////////////////////// @@ -66,13 +108,11 @@ firetray.Window.setVisibility = function(xid, visibility) { firetray.Handler.dumpWindows = function() { let dumpStr = ""+firetray.Handler.windowsCount; for (let wid in firetray.Handler.windows) { - dumpStr += " 0x"+wid; + dumpStr += " "+wid; } log.info(dumpStr); }; -firetray.Handler.getWindowIdFromChromeWindow = firetray.Window.getXIDFromChromeWindow; - firetray.Handler.registerWindow = function(win) { log.debug("register window"); @@ -81,8 +121,7 @@ firetray.Handler.registerWindow = function(win) { let hwnd = nativeHandle ? new ctypes.voidptr_t(ctypes.UInt64(nativeHandle)) : user32.FindWindowW("MozillaWindowClass", win.document.title); - // wid will be used as a string most of the time (through f.Handler.windows mainly) - let wid = ctypes.cast(hwnd, ctypes.uintptr_t).value.toString(16); + let wid = firetray.Window.hwndToHexStr(hwnd); log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title); if (this.windows.hasOwnProperty(wid)) { @@ -104,33 +143,40 @@ firetray.Handler.registerWindow = function(win) { // NOTE: no need to check for window state to set visibility because all // windows *are* shown at startup firetray.Window.updateVisibility(wid, true); - log.debug("window 0x"+wid+" registered"); + log.debug("window "+wid+" 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 + // try { +try { + let wndProc = user32.WNDPROC(firetray.Window.wndProc); + log.debug("proc="+wndProc); + this.wndProcs.insert(wid, wndProc); + let procPrev = user32.WNDPROC( + user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC, ctypes.cast(wndProc, win32.LONG_PTR)) + ); + log.debug("procPrev="+procPrev+" winLastError="+ctypes.winLastError); + this.wndProcsOrig.insert(wid, procPrev); // could be set as a window prop (SetPropW) - 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; + procPrev = ctypes.cast(procPrev, win32.HANDLE); + user32.SetPropW(hwnd, win32._T(kPropProcPrev), procPrev); + log.debug("SetPropW: "+procPrev+" winLastError="+ctypes.winLastError); + } catch(error) { +log.error(error); } */ + // firetray.Win32.acceptAllMessages(hwnd); + + // } 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+"."); + // else win.alert(x); + // } + + // TODO: check wndproc chaining http://stackoverflow.com/a/8835843/421846 if + // needed for startupFilter log.debug("AFTER"); firetray.Handler.dumpWindows(); return wid; @@ -138,8 +184,23 @@ firetray.Handler.registerWindow = function(win) { firetray.Handler.unregisterWindow = function(win) { log.debug("unregister window"); - let xid = firetray.Window.getXIDFromChromeWindow(win); - return firetray.Window.unregisterWindowByXID(xid); + + let wid = firetray.Window.getWIDFromChromeWindow(win); + + if (!firetray.Handler.windows.hasOwnProperty(wid)) { + log.error("can't unregister unknown window "+wid); + return false; + } + + if (!delete firetray.Handler.windows[wid]) + throw new DeleteError(); + // firetray.Handler.wndProcs.remove(wid); + // firetray.Handler.wndProcsOrig.remove(wid); + firetray.Handler.windowsCount -= 1; + firetray.Handler.visibleWindowsCount -= 1; + + log.debug("window "+wid+" unregistered"); + return true; }; firetray.Handler.showWindow = firetray.Window.show;