[Pkg-mozext-commits] [firetray] 47/84: Add 'start_hidden' capability for winnt.

David Prévot taffit at moszumanska.debian.org
Sun Jul 20 01:42:45 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository firetray.

commit f1c5c02c8fc2d22d4ee0f208c66e99722f04879c
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Sat Apr 12 15:16:09 2014 +0200

    Add 'start_hidden' capability for winnt.
---
 src/chrome/content/options.js            |   4 +-
 src/chrome/content/overlay.js            |   1 -
 src/modules/FiretrayHandler.jsm          |   4 +-
 src/modules/ctypes/winnt/user32.jsm      |  13 ++++
 src/modules/ctypes/winnt/win32.jsm       |  15 ++++
 src/modules/linux/FiretrayWindow.jsm     |   3 +
 src/modules/winnt/FiretrayStatusIcon.jsm |   5 +-
 src/modules/winnt/FiretrayWin32.jsm      |   3 +-
 src/modules/winnt/FiretrayWindow.jsm     | 120 +++++++++++++++++++++++--------
 9 files changed, 128 insertions(+), 40 deletions(-)

diff --git a/src/chrome/content/options.js b/src/chrome/content/options.js
index ffe619e..eca0060 100644
--- a/src/chrome/content/options.js
+++ b/src/chrome/content/options.js
@@ -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;
      });
 
diff --git a/src/chrome/content/overlay.js b/src/chrome/content/overlay.js
index f65306e..7f92236 100644
--- a/src/chrome/content/overlay.js
+++ b/src/chrome/content/overlay.js
@@ -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())
diff --git a/src/modules/FiretrayHandler.jsm b/src/modules/FiretrayHandler.jsm
index 88c4541..06fdf31 100644
--- a/src/modules/FiretrayHandler.jsm
+++ b/src/modules/FiretrayHandler.jsm
@@ -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 {
diff --git a/src/modules/ctypes/winnt/user32.jsm b/src/modules/ctypes/winnt/user32.jsm
index 8f4c783..103a68f 100644
--- a/src/modules/ctypes/winnt/user32.jsm
+++ b/src/modules/ctypes/winnt/user32.jsm
@@ -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);
diff --git a/src/modules/ctypes/winnt/win32.jsm b/src/modules/ctypes/winnt/win32.jsm
index 00be95f..15b57d6 100644
--- a/src/modules/ctypes/winnt/win32.jsm
+++ b/src/modules/ctypes/winnt/win32.jsm
@@ -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 },
diff --git a/src/modules/linux/FiretrayWindow.jsm b/src/modules/linux/FiretrayWindow.jsm
index 040c9f0..796ca8f 100644
--- a/src/modules/linux/FiretrayWindow.jsm
+++ b/src/modules/linux/FiretrayWindow.jsm
@@ -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);
diff --git a/src/modules/winnt/FiretrayStatusIcon.jsm b/src/modules/winnt/FiretrayStatusIcon.jsm
index f2fb13b..c901243 100644
--- a/src/modules/winnt/FiretrayStatusIcon.jsm
+++ b/src/modules/winnt/FiretrayStatusIcon.jsm
@@ -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)) {
diff --git a/src/modules/winnt/FiretrayWin32.jsm b/src/modules/winnt/FiretrayWin32.jsm
index 0d7c279..ea03459 100644
--- a/src/modules/winnt/FiretrayWin32.jsm
+++ b/src/modules/winnt/FiretrayWin32.jsm
@@ -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
diff --git a/src/modules/winnt/FiretrayWindow.jsm b/src/modules/winnt/FiretrayWindow.jsm
index 7750dab..d4999c7 100644
--- a/src/modules/winnt/FiretrayWindow.jsm
+++ b/src/modules/winnt/FiretrayWindow.jsm
@@ -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");
 
@@ -25,8 +26,10 @@ const FIRETRAY_XWINDOW_MAXIMIZED = 1 << 1;
 
 // 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);
+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,19 +68,65 @@ 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);
+  let procPrev = firetray.Handler.wndProcsOrig.get(wid);
+  return user32.CallWindowProcW(procPrev, hWnd, uMsg, wParam, lParam); // or DefWindowProcW
+};
 
-  } else if (uMsg === win32.WM_MOVE) {
-    log.debug("wndProc CALLED with WM_MOVE "+wid);
+// 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);
+    }
 
-  } 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
+  return user32.CallNextHookEx(null, nCode, wParam, lParam);
 };
 
 firetray.Window.attachWndProc = function(wid, hwnd) {
@@ -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);
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list