2013-11-16 09:39:57 -05:00
|
|
|
/* -*- 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/ctypesMap.jsm");
|
2013-11-17 17:11:17 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/winnt/win32.jsm");
|
2013-11-16 09:39:57 -05:00
|
|
|
Cu.import("resource://firetray/ctypes/winnt/user32.jsm");
|
2013-11-22 17:05:43 -05:00
|
|
|
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
2013-11-24 08:25:27 -05:00
|
|
|
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
2013-11-16 09:39:57 -05:00
|
|
|
Cu.import("resource://firetray/commons.js");
|
2014-01-19 17:02:23 -05:00
|
|
|
firetray.Handler.subscribeLibsForClosing([user32]);
|
2013-11-16 09:39:57 -05:00
|
|
|
|
|
|
|
let log = firetray.Logging.getLogger("firetray.Window");
|
|
|
|
|
|
|
|
if ("undefined" == typeof(firetray.Handler))
|
|
|
|
log.error("This module MUST be imported from/after FiretrayHandler !");
|
|
|
|
|
|
|
|
const FIRETRAY_XWINDOW_HIDDEN = 1 << 0; // when minimized also
|
|
|
|
const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
// 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.
|
|
|
|
firetray.Handler.wndProcs = new ctypesMap(user32.WNDPROC);
|
|
|
|
firetray.Handler.wndProcsOrig = new ctypesMap(user32.WNDPROC);
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2013-11-24 08:25:27 -05:00
|
|
|
firetray.Window = new FiretrayWindow();
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2013-11-24 08:25:27 -05:00
|
|
|
firetray.Window.init = function() {
|
2013-11-16 09:39:57 -05:00
|
|
|
this.initialized = true;
|
2013-11-24 08:25:27 -05:00
|
|
|
};
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2013-11-24 08:25:27 -05:00
|
|
|
firetray.Window.shutdown = function() {
|
|
|
|
this.initialized = false;
|
|
|
|
};
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2014-02-05 16:48:14 -05:00
|
|
|
firetray.Window.getVisibility = function(hwnd) {
|
|
|
|
let style = user32.GetWindowLongW(hwnd, user32.GWL_STYLE);
|
|
|
|
let visible = ((style & user32.WS_VISIBLE) != 0); // user32.IsWindowVisible(hwnd);
|
|
|
|
log.debug("visible="+visible);
|
|
|
|
return visible;
|
2013-11-24 08:25:27 -05:00
|
|
|
};
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2014-02-05 16:48:14 -05:00
|
|
|
// firetray.Window.{show,hide} useless
|
|
|
|
firetray.Window.setVisibility = function(wid, visible) {
|
|
|
|
log.debug("setVisibility="+visible);
|
|
|
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
|
|
|
let ret = user32.ShowWindow(hwnd, visible ? user32.SW_SHOW : user32.SW_HIDE);
|
|
|
|
log.debug(" ShowWindow="+ret+" winLastError="+ctypes.winLastError);
|
|
|
|
this.updateVisibility(wid, visible);
|
2013-11-24 08:25:27 -05:00
|
|
|
};
|
2014-02-05 16:48:14 -05:00
|
|
|
// firetray.Window.updateVisibility inherited
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2013-12-01 12:26:36 -05:00
|
|
|
firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
|
2014-01-19 17:02:23 -05:00
|
|
|
// log.debug("wndProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
|
|
|
log.debug("wndProc CALLED with WM_TRAYMESSAGE");
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
|
|
|
|
log.debug("wndProc CALLED with WM_TRAYMESSAGEFWD");
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
} else if (uMsg === win32.WM_USER) {
|
|
|
|
log.debug("wndProc CALLED with WM_USER");
|
2013-12-01 12:26:36 -05:00
|
|
|
}
|
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
|
|
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
|
|
|
return user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam);
|
2013-12-01 12:26:36 -05:00
|
|
|
};
|
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
firetray.Window.restoreWndProc = function(wid) {
|
|
|
|
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
2014-02-05 16:48:14 -05:00
|
|
|
let hwnd = firetray.Win32.hexStrToHwnd(wid);
|
2014-01-19 17:02:23 -05:00
|
|
|
log.debug("hwnd="+hwnd);
|
|
|
|
let proc = user32.WNDPROC(
|
|
|
|
user32.SetWindowLongW(hwnd, user32.GWLP_WNDPROC,
|
|
|
|
ctypes.cast(procPrev, win32.LONG_PTR))
|
|
|
|
);
|
|
|
|
firetray.js.assert(proc == firetray.Handler.wndProcs.get(wid),
|
|
|
|
"Wrong WndProc replaced.");
|
|
|
|
firetray.Handler.wndProcs.remove(wid);
|
|
|
|
firetray.Handler.wndProcsOrig.remove(wid);
|
2013-12-01 18:31:45 -05:00
|
|
|
};
|
|
|
|
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2013-11-16 09:39:57 -05:00
|
|
|
///////////////////////// firetray.Handler overriding /////////////////////////
|
|
|
|
|
|
|
|
/** debug facility */
|
|
|
|
firetray.Handler.dumpWindows = function() {
|
2013-11-24 08:25:27 -05:00
|
|
|
let dumpStr = ""+firetray.Handler.windowsCount;
|
|
|
|
for (let wid in firetray.Handler.windows) {
|
2013-12-01 12:26:36 -05:00
|
|
|
dumpStr += " "+wid;
|
2013-11-24 08:25:27 -05:00
|
|
|
}
|
|
|
|
log.info(dumpStr);
|
2013-11-16 09:39:57 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.registerWindow = function(win) {
|
|
|
|
log.debug("register window");
|
|
|
|
|
|
|
|
let baseWin = firetray.Handler.getWindowInterface(win, "nsIBaseWindow");
|
2013-11-17 17:11:17 -05:00
|
|
|
let nativeHandle = baseWin.nativeHandle;
|
|
|
|
let hwnd = nativeHandle ?
|
2014-01-19 17:02:23 -05:00
|
|
|
new win32.HWND(ctypes.UInt64(nativeHandle)) :
|
2013-11-17 17:11:17 -05:00
|
|
|
user32.FindWindowW("MozillaWindowClass", win.document.title);
|
2013-12-01 18:31:45 -05:00
|
|
|
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
2013-11-24 08:25:27 -05:00
|
|
|
log.debug("=== hwnd="+hwnd+" wid="+wid+" win.document.title: "+win.document.title);
|
|
|
|
|
|
|
|
if (this.windows.hasOwnProperty(wid)) {
|
|
|
|
let msg = "Window ("+wid+") already registered.";
|
|
|
|
log.error(msg);
|
|
|
|
Cu.reportError(msg);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.windows[wid] = {};
|
|
|
|
this.windows[wid].chromeWin = win;
|
|
|
|
this.windows[wid].baseWin = baseWin;
|
2013-11-17 17:11:17 -05:00
|
|
|
|
2013-11-16 09:39:57 -05:00
|
|
|
// SetupWnd(hwnd);
|
|
|
|
|
2013-12-01 18:31:45 -05:00
|
|
|
try {
|
2014-01-19 17:02:23 -05:00
|
|
|
this.windowsCount += 1;
|
2014-02-05 16:48:14 -05:00
|
|
|
firetray.Window.updateVisibility(wid, true); // windows *are* visible at startup
|
2014-01-19 17:02:23 -05:00
|
|
|
log.debug("window "+wid+" registered");
|
|
|
|
|
|
|
|
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);
|
2013-12-01 18:31:45 -05:00
|
|
|
|
|
|
|
} 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);
|
2013-11-16 09:39:57 -05:00
|
|
|
}
|
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
firetray.Win32.acceptAllMessages(hwnd);
|
|
|
|
|
2013-11-16 09:39:57 -05:00
|
|
|
log.debug("AFTER"); firetray.Handler.dumpWindows();
|
2013-11-24 08:25:27 -05:00
|
|
|
return wid;
|
2013-11-16 09:39:57 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
firetray.Handler.unregisterWindow = function(win) {
|
|
|
|
log.debug("unregister window");
|
2013-12-01 12:26:36 -05:00
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
let wid = firetray.Window.getRegisteredWinIdFromChromeWindow(win);
|
2013-12-01 12:26:36 -05:00
|
|
|
if (!firetray.Handler.windows.hasOwnProperty(wid)) {
|
|
|
|
log.error("can't unregister unknown window "+wid);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-19 17:02:23 -05:00
|
|
|
firetray.Window.restoreWndProc(wid);
|
|
|
|
|
2013-12-01 12:26:36 -05:00
|
|
|
if (!delete firetray.Handler.windows[wid])
|
|
|
|
throw new DeleteError();
|
|
|
|
firetray.Handler.windowsCount -= 1;
|
|
|
|
firetray.Handler.visibleWindowsCount -= 1;
|
|
|
|
|
|
|
|
log.debug("window "+wid+" unregistered");
|
|
|
|
return true;
|
2013-11-16 09:39:57 -05:00
|
|
|
};
|
|
|
|
|
2014-02-05 16:48:14 -05:00
|
|
|
firetray.Handler.showWindow = function(wid) {
|
|
|
|
return firetray.Window.setVisibility(wid, true);
|
|
|
|
};
|
|
|
|
firetray.Handler.hideWindow = function(wid) {
|
|
|
|
return firetray.Window.setVisibility(wid, false);
|
|
|
|
};
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2014-02-05 16:48:14 -05:00
|
|
|
firetray.Handler.showHideAllWindows = function() {
|
|
|
|
log.debug("showHideAllWindows");
|
2013-11-16 09:39:57 -05:00
|
|
|
|
2014-02-05 16:48:14 -05:00
|
|
|
log.debug(" visibleWindowsCount="+firetray.Handler.visibleWindowsCount);
|
|
|
|
log.debug(" windowsCount="+firetray.Handler.windowsCount);
|
2013-11-16 09:39:57 -05:00
|
|
|
let visibilityRate = firetray.Handler.visibleWindowsCount/firetray.Handler.windowsCount;
|
2014-02-05 16:48:14 -05:00
|
|
|
log.debug(" visibilityRate="+visibilityRate);
|
2013-11-16 09:39:57 -05:00
|
|
|
if ((0.5 < visibilityRate) && (visibilityRate < 1)
|
|
|
|
|| visibilityRate === 0) { // TODO: should be configurable
|
|
|
|
firetray.Handler.showAllWindows();
|
|
|
|
} else {
|
|
|
|
firetray.Handler.hideAllWindows();
|
|
|
|
}
|
|
|
|
};
|