mirror of
https://github.com/moparisthebest/FireTray
synced 2024-11-15 21:35:01 -05:00
* actually use a WndProc on moz windows
* include winnt files to .xpi WndProc crashes, mentioned in bugs 598679 and 671266, were recently fixed by 915613 (thx bholley!).
This commit is contained in:
parent
40cf41e97d
commit
b453b4fa74
@ -111,7 +111,9 @@ modules_sources := $(wildcard $(modules_dir)/*.js) \
|
|||||||
$(wildcard $(modules_dir)/*.jsm) \
|
$(wildcard $(modules_dir)/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/ctypes/*.jsm) \
|
$(wildcard $(modules_dir)/ctypes/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/ctypes/linux/*.jsm) \
|
$(wildcard $(modules_dir)/ctypes/linux/*.jsm) \
|
||||||
$(wildcard $(modules_dir)/linux/*.jsm)
|
$(wildcard $(modules_dir)/ctypes/winnt/*.jsm) \
|
||||||
|
$(wildcard $(modules_dir)/linux/*.jsm) \
|
||||||
|
$(wildcard $(modules_dir)/winnt/*.jsm)
|
||||||
|
|
||||||
# The components (JSM) dir.
|
# The components (JSM) dir.
|
||||||
components_dir := components
|
components_dir := components
|
||||||
|
@ -291,6 +291,12 @@ firetray.js = {
|
|||||||
// https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Working_with_data#Quirks_in_equality
|
// https://developer.mozilla.org/en/js-ctypes/Using_js-ctypes/Working_with_data#Quirks_in_equality
|
||||||
strEquals: function(obj1, obj2) {
|
strEquals: function(obj1, obj2) {
|
||||||
return obj1.toString() === obj2.toString();
|
return obj1.toString() === obj2.toString();
|
||||||
|
},
|
||||||
|
|
||||||
|
assert: function(condition, message) {
|
||||||
|
if (!condition) {
|
||||||
|
throw message || "Assertion failed";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ function user32_defines(lib) {
|
|||||||
|
|
||||||
lib.lazy_bind("GetPropW", win32.HANDLE, win32.HWND, win32.LPCTSTR);
|
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("SetPropW", win32.BOOL, win32.HWND, win32.LPCTSTR, win32.HANDLE);
|
||||||
|
lib.lazy_bind("RemovePropW", win32.HANDLE, win32.HWND, win32.LPCTSTR);
|
||||||
|
|
||||||
lib.lazy_bind("GetWindowLongW", win32.LONG_PTR, win32.HWND, ctypes.int);
|
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);
|
lib.lazy_bind("SetWindowLongW", win32.LONG_PTR , win32.HWND, ctypes.int, win32.LONG_PTR);
|
||||||
|
@ -9,12 +9,11 @@ const Cu = Components.utils;
|
|||||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
Cu.import("resource://firetray/ctypes/ctypesMap.jsm");
|
||||||
Cu.import("resource://firetray/ctypes/winnt/win32.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/ctypes/winnt/user32.jsm");
|
||||||
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||||
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
||||||
Cu.import("resource://firetray/commons.js");
|
Cu.import("resource://firetray/commons.js");
|
||||||
firetray.Handler.subscribeLibsForClosing([kernel32, user32]);
|
firetray.Handler.subscribeLibsForClosing([user32]);
|
||||||
|
|
||||||
let log = firetray.Logging.getLogger("firetray.Window");
|
let log = firetray.Logging.getLogger("firetray.Window");
|
||||||
|
|
||||||
@ -24,12 +23,10 @@ if ("undefined" == typeof(firetray.Handler))
|
|||||||
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
||||||
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
||||||
|
|
||||||
const kPropProcPrev = "_FIRETRAY_OLD_PROC";
|
// We need to keep long-living references to wndProcs callbacks. As they also
|
||||||
|
// happen to be ctypes pointers, we store them into real ctypes arrays.
|
||||||
// NOTE: storing ctypes pointers into a JS object doesn't work: pointers are
|
firetray.Handler.wndProcs = new ctypesMap(user32.WNDPROC);
|
||||||
// "evolving" after a while (maybe due to back and forth conversion). So we
|
firetray.Handler.wndProcsOrig = new ctypesMap(user32.WNDPROC);
|
||||||
// need to store them into a real ctypes array !
|
|
||||||
firetray.Handler.callProcHooks = new ctypesMap(win32.HHOOK);
|
|
||||||
|
|
||||||
|
|
||||||
firetray.Window = new FiretrayWindow();
|
firetray.Window = new FiretrayWindow();
|
||||||
@ -58,69 +55,38 @@ firetray.Window.setVisibility = function(xid, visibility) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
|
firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
|
||||||
log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
// log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
||||||
|
|
||||||
let proc = user32.GetWindowLongW(hWnd, user32.GWLP_WNDPROC);
|
if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
||||||
log.debug(" proc="+proc.toString(16)+" winLastError="+ctypes.winLastError);
|
log.debug("wndProc CALLED with WM_TRAYMESSAGE");
|
||||||
|
|
||||||
try {
|
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
|
||||||
|
log.debug("wndProc CALLED with WM_TRAYMESSAGEFWD");
|
||||||
|
|
||||||
|
} else if (uMsg === win32.WM_USER) {
|
||||||
|
log.debug("wndProc CALLED with WM_USER");
|
||||||
|
}
|
||||||
|
|
||||||
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
||||||
// let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
||||||
// let procPrev = ctypes.cast(user32.GetPropW(hWnd, win32._T(kPropProcPrev)), user32.WNDPROC);
|
return user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam);
|
||||||
// let procPrev = user32.GetPropW(hWnd, win32._T(kPropProcPrev));
|
|
||||||
log.debug(" wid="+wid+" prev="+procPrev);
|
|
||||||
|
|
||||||
// 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.Window.callProcHook = function(nCode, wParam, lParam) { // WH_CALLWNDPROC, WH_GETMESSAGE
|
firetray.Window.restoreWndProc = function(wid) {
|
||||||
// log.debug("callProcHook CALLED: nCode="+nCode+", wParam="+wParam+", lParam="+lParam);
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
||||||
let cwpstruct = ctypes.cast(win32.LPARAM(lParam), user32.CWPSTRUCT.ptr).contents;
|
let hwnd = new win32.HWND(ctypes.UInt64(wid));
|
||||||
let uMsg = cwpstruct.message;
|
log.debug("hwnd="+hwnd);
|
||||||
|
let proc = user32.WNDPROC(
|
||||||
if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
|
user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC,
|
||||||
log.debug("WM_TRAYMESSAGEFWD received!");
|
ctypes.cast(procPrev, win32.LONG_PTR))
|
||||||
|
);
|
||||||
if (wParam != 0) {
|
firetray.js.assert(proc == firetray.Handler.wndProcs.get(wid),
|
||||||
log.debug("message was sent by the current thread");
|
"Wrong WndProc replaced.");
|
||||||
}
|
firetray.Handler.wndProcs.remove(wid);
|
||||||
|
firetray.Handler.wndProcsOrig.remove(wid);
|
||||||
let hWnd = cwpstruct.hwnd;
|
|
||||||
log.debug("hWnd="+hWnd);
|
|
||||||
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
|
||||||
log.debug("wid="+wid);
|
|
||||||
|
|
||||||
if (nCode === user32.HC_ACTION) {
|
|
||||||
log.warn("*** must process the message ***");
|
|
||||||
} else if (nCode < 0) {
|
|
||||||
log.warn("*** must pass the message to the CallNextHookEx function without further processing ***");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return user32.CallNextHookEx(null, nCode, wParam, lParam);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////// firetray.Handler overriding /////////////////////////
|
///////////////////////// firetray.Handler overriding /////////////////////////
|
||||||
|
|
||||||
/** debug facility */
|
/** debug facility */
|
||||||
@ -138,7 +104,7 @@ firetray.Handler.registerWindow = function(win) {
|
|||||||
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
||||||
let nativeHandle = baseWin.nativeHandle;
|
let nativeHandle = baseWin.nativeHandle;
|
||||||
let hwnd = nativeHandle ?
|
let hwnd = nativeHandle ?
|
||||||
new ctypes.voidptr_t(ctypes.UInt64(nativeHandle)) :
|
new win32.HWND(ctypes.UInt64(nativeHandle)) :
|
||||||
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
||||||
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
||||||
log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
|
log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
|
||||||
@ -158,23 +124,24 @@ firetray.Handler.registerWindow = function(win) {
|
|||||||
// ::SetPropW(hwnd, kIconMouseEventProc, reinterpret_cast<HANDLE>(callback));
|
// ::SetPropW(hwnd, kIconMouseEventProc, reinterpret_cast<HANDLE>(callback));
|
||||||
// ::SetPropW(hwnd, kIcon, reinterpret_cast<HANDLE>(0x1));
|
// ::SetPropW(hwnd, kIcon, reinterpret_cast<HANDLE>(0x1));
|
||||||
|
|
||||||
this.windowsCount += 1;
|
|
||||||
// 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 "+wid+" registered");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let callProcHook = user32.HOOKPROC(firetray.Window.callProcHook);
|
this.windowsCount += 1;
|
||||||
log.debug("callhk="+callProcHook);
|
// NOTE: no need to check for window state to set visibility because all
|
||||||
// Global hooks must reside in a dll (hence hInst). This is important for
|
// windows *are* shown at startup
|
||||||
// the scope of variables.
|
firetray.Window.updateVisibility(wid, true);
|
||||||
let hhook = user32.SetWindowsHookExW(
|
log.debug("window "+wid+" registered");
|
||||||
user32.WH_CALLWNDPROC, callProcHook, null, kernel32.GetCurrentThreadId());
|
|
||||||
log.debug(" hhook="+hhook+" winLastError="+ctypes.winLastError);
|
|
||||||
this.callProcHooks.insert(wid, hhook);
|
|
||||||
|
|
||||||
firetray.Win32.acceptAllMessages(hwnd);
|
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);
|
||||||
|
// we can't store WNDPROC callbacks (JS ctypes objects) with SetPropW(), as
|
||||||
|
// we need long-living refs.
|
||||||
|
this.wndProcsOrig.insert(wid, procPrev);
|
||||||
|
|
||||||
} catch (x) {
|
} catch (x) {
|
||||||
if (x.name === "RangeError") // instanceof not working :-(
|
if (x.name === "RangeError") // instanceof not working :-(
|
||||||
@ -184,6 +151,8 @@ firetray.Handler.registerWindow = function(win) {
|
|||||||
else win.alert(x);
|
else win.alert(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firetray.Win32.acceptAllMessages(hwnd);
|
||||||
|
|
||||||
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
||||||
return wid;
|
return wid;
|
||||||
};
|
};
|
||||||
@ -191,17 +160,16 @@ firetray.Handler.registerWindow = function(win) {
|
|||||||
firetray.Handler.unregisterWindow = function(win) {
|
firetray.Handler.unregisterWindow = function(win) {
|
||||||
log.debug("unregister window");
|
log.debug("unregister window");
|
||||||
|
|
||||||
let wid = firetray.Window.getWIDFromChromeWindow(win);
|
let wid = firetray.Window.getRegisteredWinIdFromChromeWindow(win);
|
||||||
|
|
||||||
if (!firetray.Handler.windows.hasOwnProperty(wid)) {
|
if (!firetray.Handler.windows.hasOwnProperty(wid)) {
|
||||||
log.error("can't unregister unknown window "+wid);
|
log.error("can't unregister unknown window "+wid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
firetray.Window.restoreWndProc(wid);
|
||||||
|
|
||||||
if (!delete firetray.Handler.windows[wid])
|
if (!delete firetray.Handler.windows[wid])
|
||||||
throw new DeleteError();
|
throw new DeleteError();
|
||||||
user32.UnhookWindowsHookEx(firetray.Handler.callProcHooks.get(wid));
|
|
||||||
firetray.Handler.callProcHooks.remove(wid);
|
|
||||||
firetray.Handler.windowsCount -= 1;
|
firetray.Handler.windowsCount -= 1;
|
||||||
firetray.Handler.visibleWindowsCount -= 1;
|
firetray.Handler.visibleWindowsCount -= 1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user