mirror of
https://github.com/moparisthebest/FireTray
synced 2025-01-08 12:08:05 -05:00
Add 'start_hidden' capability for winnt.
This commit is contained in:
parent
74ac8d54d7
commit
f1c5c02c8f
@ -68,8 +68,8 @@ var firetrayUIOptions = {
|
||||
|
||||
hideUnsupportedOptions: function() { // full_feat
|
||||
// windows prefs
|
||||
['ui_hides_last_only', 'ui_start_hidden', 'ui_show_activates',
|
||||
'ui_remember_desktop'].forEach(function(id){
|
||||
['ui_hides_last_only', 'ui_show_activates', 'ui_remember_desktop']
|
||||
.forEach(function(id){
|
||||
document.getElementById(id).hidden = true;
|
||||
});
|
||||
|
||||
|
@ -143,7 +143,6 @@ var firetrayChrome = { // each new window gets a new firetrayChrome !
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
// should be sufficient for a delayed Startup (no need for window.setTimeout())
|
||||
|
@ -319,7 +319,7 @@ firetray.Handler = {
|
||||
} else {
|
||||
for (let winId in firetray.Handler.windows) {
|
||||
firetray.Chat.detachSelectListeners(firetray.Handler.windows[winId].chromeWin);
|
||||
firetray.ChatStatusIcon.detachOnFocusInCallback(winId);
|
||||
firetray.ChatStatusIcon.detachOnFocusInCallback(winId); // FIXME: to be removed
|
||||
}
|
||||
firetray.Chat.shutdown();
|
||||
}
|
||||
@ -709,7 +709,7 @@ firetray.VersionChangeHandler = {
|
||||
"hide_show_mm_key", "accounts_to_exclude" ];
|
||||
let v0_4_0b2_Opts = [ 'mail_notification' ];
|
||||
let v0_5_0b1_Opts = [ 'mail_urgency_hint', 'app_icon_filename', 'custom_mail_icon' ];
|
||||
let oldOpt = v0_3_Opts.concat(v0_4_0b2_Opts).concat(v0_5_0b1_Opts);
|
||||
let oldOpts = v0_3_Opts.concat(v0_4_0b2_Opts).concat(v0_5_0b1_Opts);
|
||||
|
||||
for (let i = 0, length = oldOpts.length; i<length; ++i) {
|
||||
try {
|
||||
|
@ -362,6 +362,19 @@ function user32_defines(lib) {
|
||||
lib.lazy_bind("GetCursorPos", win32.BOOL, win32.LPPOINT);
|
||||
lib.lazy_bind("GetMessagePos", win32.DWORD);
|
||||
|
||||
this.WINDOWPLACEMENT = ctypes.StructType("WINDOWPLACEMENT", [
|
||||
{ "length": win32.UINT },
|
||||
{ "flags": win32.UINT },
|
||||
{ "showCmd": win32.UINT },
|
||||
{ "ptMinPosition": win32.POINT },
|
||||
{ "ptMaxPosition": win32.POINT },
|
||||
{ "rcNormalPosition": win32.RECT }
|
||||
]);
|
||||
this.PWINDOWPLACEMENT = this.LPWINDOWPLACEMENT = this.WINDOWPLACEMENT.ptr;
|
||||
|
||||
lib.lazy_bind("GetWindowPlacement", win32.BOOL, win32.HWND, this.WINDOWPLACEMENT.ptr);
|
||||
lib.lazy_bind("SetWindowPlacement", win32.BOOL, win32.HWND, this.WINDOWPLACEMENT.ptr);
|
||||
|
||||
}
|
||||
|
||||
new ctypes_library(USER32_LIBNAME, USER32_ABIS, user32_defines, this);
|
||||
|
@ -121,6 +121,15 @@ var win32 = new function() {
|
||||
this.WM_SHOWWINDOW = 0x0018;
|
||||
this.WM_WININICHANGE = 0x001A;
|
||||
this.WM_SETTINGCHANGE = this.WM_WININICHANGE;
|
||||
this.WM_DEVMODECHANGE = 0x001B;
|
||||
this.WM_ACTIVATEAPP = 0x001C;
|
||||
this.WM_FONTCHANGE = 0x001D;
|
||||
this.WM_TIMECHANGE = 0x001E;
|
||||
this.WM_CANCELMODE = 0x001F;
|
||||
this.WM_SETCURSOR = 0x0020;
|
||||
this.WM_MOUSEACTIVATE = 0x0021;
|
||||
this.WM_CHILDACTIVATE = 0x0022;
|
||||
this.WM_QUEUESYNC = 0x0023;
|
||||
this.WM_COMMAND = 0x0111;
|
||||
this.WM_SYSCOMMAND = 0x0112;
|
||||
this.WM_HSCROLL = 0x0114;
|
||||
@ -153,6 +162,12 @@ var win32 = new function() {
|
||||
this.SC_MINIMIZE = 0xF020;
|
||||
this.SC_CLOSE = 0xF060;
|
||||
|
||||
this.SIZE_RESTORED = 0;
|
||||
this.SIZE_MINIMIZED = 1;
|
||||
this.SIZE_MAXIMIZED = 2;
|
||||
this.SIZE_MAXSHOW = 3;
|
||||
this.SIZE_MAXHIDE = 4;
|
||||
|
||||
this.BITMAP = ctypes.StructType("BITMAP", [
|
||||
{ "bmType": this.LONG },
|
||||
{ "bmWidth": this.LONG },
|
||||
|
@ -563,6 +563,9 @@ firetray.Window.startupFilter = function(xev, gdkEv, data) {
|
||||
let xany = ctypes.cast(xev, x11.XAnyEvent.ptr);
|
||||
let xid = xany.contents.window;
|
||||
|
||||
// MapRequest already taken by window manager. Not sure we could be notified
|
||||
// *before* the window is actually mapped, in order to minimize it before
|
||||
// it's shown.
|
||||
if (xany.contents.type === x11.MapNotify) {
|
||||
gdk.gdk_window_remove_filter(firetray.Handler.gdkWindows.get(xid),
|
||||
firetray.Handler.windows[xid].startupFilterCb, null);
|
||||
|
@ -228,12 +228,11 @@ firetray.StatusIcon = {
|
||||
proxyWndProc: function(hWnd, uMsg, wParam, lParam) {
|
||||
// log.debug("ProxyWindowProc CALLED: hWnd="+hWnd+", uMsg="+uMsg+", wParam="+wParam+", lParam="+lParam);
|
||||
|
||||
// FIXME: WM_TASKBARCREATED is needed in case of explorer crash
|
||||
// http://twigstechtips.blogspot.fr/2011/02/c-detect-when-windows-explorer-has.html
|
||||
if (uMsg === firetray.Win32.WM_TASKBARCREATED) {
|
||||
log.info("____________TASKBARCREATED");
|
||||
|
||||
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGEFWD) {
|
||||
log.debug("ProxyWindowProc WM_TRAYMESSAGEFWD reached!");
|
||||
|
||||
} else if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
||||
|
||||
switch (win32.LOWORD(lParam)) {
|
||||
|
@ -16,11 +16,11 @@ firetray.Handler.subscribeLibsForClosing([kernel32, user32]);
|
||||
let log = firetray.Logging.getLogger("firetray.Win32");
|
||||
|
||||
const kMessageTray = "_FIRETRAY_Tray";
|
||||
const kMessageTrayFwd = "_FIRETRAY_TrayFwd";
|
||||
|
||||
if ("undefined" == typeof(firetray.Handler))
|
||||
log.error("This module MUST be imported from/after FiretrayHandler !");
|
||||
|
||||
|
||||
function Win32Env() {
|
||||
|
||||
this.hInstance = kernel32.GetModuleHandleW("xul"); // ordinary windows are created from xul.dll
|
||||
@ -29,7 +29,6 @@ function Win32Env() {
|
||||
// we use our own messages because we create a different window class than Moz
|
||||
this.WM_TASKBARCREATED = user32.RegisterWindowMessageW("TaskbarCreated");
|
||||
this.WM_TRAYMESSAGE = user32.RegisterWindowMessageW(kMessageTray);
|
||||
this.WM_TRAYMESSAGEFWD = user32.RegisterWindowMessageW(kMessageTrayFwd);
|
||||
log.debug("WM_*="+this.WM_TASKBARCREATED+" "+this.WM_TRAYMESSAGE+" "+this.WM_TRAYCALLBACK);
|
||||
|
||||
/* if Administrator, accept messages from applications running in a lower
|
||||
|
@ -8,12 +8,13 @@ const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
Cu.import("resource://firetray/ctypes/ctypesMap.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/win32.jsm");
|
||||
Cu.import("resource://firetray/winnt/FiretrayWin32.jsm");
|
||||
Cu.import("resource://firetray/FiretrayWindow.jsm");
|
||||
Cu.import("resource://firetray/commons.js");
|
||||
firetray.Handler.subscribeLibsForClosing([user32]);
|
||||
firetray.Handler.subscribeLibsForClosing([user32, kernel32]);
|
||||
|
||||
let log = firetray.Logging.getLogger("firetray.Window");
|
||||
|
||||
@ -27,6 +28,8 @@ const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
|
||||
// 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);
|
||||
firetray.Handler.procHooks = new ctypesMap(win32.HHOOK);
|
||||
firetray.Handler.procHooksRegistred = new ctypesMap(win32.HHOOK);
|
||||
|
||||
|
||||
firetray.Window = new FiretrayWindow();
|
||||
@ -54,23 +57,10 @@ firetray.Window.setVisibility = function(wid, visible) {
|
||||
};
|
||||
|
||||
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=0x"+uMsg.toString(16)+", wParam="+wParam+", lParam="+lParam);
|
||||
let wid = firetray.Win32.hwndToHexStr(hWnd);
|
||||
|
||||
if (uMsg === firetray.Win32.WM_TRAYMESSAGE) {
|
||||
log.debug("wndProc CALLED with WM_TRAYMESSAGE");
|
||||
|
||||
} 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");
|
||||
|
||||
} else if (uMsg === win32.WM_CLOSE) {
|
||||
log.debug("wndProc CALLED with WM_CLOSE");
|
||||
|
||||
} else if (uMsg === win32.WM_SYSCOMMAND) {
|
||||
// FIXME: not work with window.minimize() (menubar hidden)
|
||||
if (uMsg === win32.WM_SYSCOMMAND) {
|
||||
log.debug("wndProc CALLED with WM_SYSCOMMAND wParam="+wParam);
|
||||
if (wParam === win32.SC_MINIMIZE) {
|
||||
log.debug("GOT ICONIFIED");
|
||||
@ -78,21 +68,67 @@ firetray.Window.wndProc = function(hWnd, uMsg, wParam, lParam) { // filterWindow
|
||||
return 0; // processed => preventDefault
|
||||
}
|
||||
}
|
||||
|
||||
} else if (uMsg === win32.WM_DESTROY) {
|
||||
log.debug("wndProc CALLED with WM_DESTROY "+wid);
|
||||
|
||||
} else if (uMsg === win32.WM_MOVE) {
|
||||
log.debug("wndProc CALLED with WM_MOVE "+wid);
|
||||
|
||||
} else if (uMsg === win32.WM_ACTIVATE) {
|
||||
log.debug("wndProc CALLED with WM_ACTIVATE "+wid);
|
||||
}
|
||||
|
||||
let procPrev = firetray.Handler.wndProcsOrig.get(wid);
|
||||
return user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam); // or DefWindowProcW
|
||||
};
|
||||
|
||||
// We could chain wndProcs, but adding a hook looks simpler.
|
||||
firetray.Window.showCount = 0;
|
||||
firetray.Window.startupHook = function(nCode, wParam, lParam) { // WH_CALLWNDPROC, WH_GETMESSAGE
|
||||
// log.debug("startupHook CALLED: nCode="+nCode+", wParam="+wParam+", lParam="+lParam);
|
||||
if (nCode < 0) return user32.CallNextHookEx(null, nCode, wParam, lParam); // user32.HC_ACTION
|
||||
|
||||
let cwpstruct = ctypes.cast(win32.LPARAM(lParam), user32.CWPSTRUCT.ptr).contents;
|
||||
let uMsg = cwpstruct.message;
|
||||
let hwnd = cwpstruct.hwnd;
|
||||
let wid = firetray.Win32.hwndToHexStr(hwnd);
|
||||
let wparam = cwpstruct.wParam;
|
||||
let lparam = cwpstruct.lParam;
|
||||
|
||||
if (uMsg === win32.WM_SHOWWINDOW && wparam == 1 && lparam == 0) { // shown and ShowWindow called
|
||||
log.debug("startupHook CALLED with WM_SHOWWINDOW wparam="+wparam+" lparam="+lparam);
|
||||
firetray.Window.showCount += 1;
|
||||
|
||||
if (firetray.Utils.prefService.getBoolPref('start_hidden')) {
|
||||
log.debug("start_hidden");
|
||||
|
||||
/* Compared to ShowWindow, SetWindowPlacement seems to bypass window
|
||||
animations. http://stackoverflow.com/a/6087214 */
|
||||
let placement = new user32.WINDOWPLACEMENT;
|
||||
let ret = user32.GetWindowPlacement(hwnd, placement.address());
|
||||
log.debug(" GetWindowPlacement="+ret+" winLastError="+ctypes.winLastError);
|
||||
log.debug(" PLACEMENT="+placement);
|
||||
|
||||
if (firetray.Window.showCount < 2) {
|
||||
// we can't prevent ShowWindow, so we mitigate the effect by minimizing
|
||||
// it before. This is why we'll have to restore it when unhidden.
|
||||
placement.showCmd = user32.SW_SHOWMINNOACTIVE;
|
||||
ret = user32.SetWindowPlacement(hwnd, placement.address());
|
||||
log.debug(" SetWindowPlacement="+ret+" winLastError="+ctypes.winLastError);
|
||||
|
||||
firetray.Utils.timer(
|
||||
FIRETRAY_DELAY_NOWAIT_MILLISECONDS,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT, function(){firetray.Handler.hideWindow(wid);}
|
||||
); // looks like CData (hwnd) cannot be closured
|
||||
|
||||
} else { // restore
|
||||
firetray.Window.detachHook(wid);
|
||||
|
||||
placement.showCmd = user32.SW_RESTORE;
|
||||
user32.SetWindowPlacement(hwnd, placement.address());
|
||||
}
|
||||
|
||||
} else {
|
||||
firetray.Window.detachHook(wid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return user32.CallNextHookEx(null, nCode, wParam, lParam);
|
||||
};
|
||||
|
||||
firetray.Window.attachWndProc = function(wid, hwnd) {
|
||||
try {
|
||||
let wndProc = user32.WNDPROC(firetray.Window.wndProc);
|
||||
@ -103,8 +139,8 @@ firetray.Window.attachWndProc = function(wid, hwnd) {
|
||||
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.
|
||||
/* we can't store WNDPROC callbacks (JS ctypes objects) with SetPropW(), as
|
||||
we need long-living refs. */
|
||||
firetray.Handler.wndProcsOrig.insert(wid, procPrev);
|
||||
|
||||
} catch (x) {
|
||||
@ -135,6 +171,28 @@ firetray.Window.detachWndProc = function(wid) {
|
||||
firetray.Handler.wndProcsOrig.remove(wid);
|
||||
};
|
||||
|
||||
firetray.Window.attachHook = function(wid) { // detaches itself alone
|
||||
let startupHook = user32.HOOKPROC(firetray.Window.startupHook);
|
||||
log.debug("callhk="+startupHook);
|
||||
firetray.Handler.procHooks.insert(wid, startupHook);
|
||||
// Global hooks must reside in a dll (hence hInst). This is important for
|
||||
// the scope of variables.
|
||||
let hhook = user32.SetWindowsHookExW(
|
||||
user32.WH_CALLWNDPROC, startupHook, null, kernel32.GetCurrentThreadId());
|
||||
log.debug(" hhook="+hhook+" winLastError="+ctypes.winLastError);
|
||||
firetray.Handler.procHooksRegistred.insert(wid, hhook);
|
||||
};
|
||||
|
||||
firetray.Window.detachHook = function(wid) { // detaches itself alone
|
||||
let hook = firetray.Handler.procHooksRegistred.get(wid);
|
||||
if (!user32.UnhookWindowsHookEx(hook)) {
|
||||
log.error("UnhookWindowsHookEx for window "+wid+" failed: winLastError="+ctypes.winLastError);
|
||||
return;
|
||||
}
|
||||
firetray.Handler.procHooks.remove(wid);
|
||||
firetray.Handler.procHooksRegistred.remove(wid);
|
||||
};
|
||||
|
||||
|
||||
///////////////////////// firetray.Handler overriding /////////////////////////
|
||||
|
||||
@ -170,10 +228,12 @@ firetray.Handler.registerWindow = function(win) {
|
||||
Object.defineProperties(this.windows[wid], {
|
||||
"visible": { get: function(){return firetray.Window.getVisibility(wid);} }
|
||||
});
|
||||
|
||||
log.debug("window "+wid+" registered");
|
||||
|
||||
firetray.Window.attachWndProc(wid, hwnd);
|
||||
if (!firetray.Handler.appStarted) {
|
||||
firetray.Window.attachHook(wid);
|
||||
}
|
||||
|
||||
firetray.Win32.acceptAllMessages(hwnd);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user