[WIN32SS][USER32] Fix Task Switcher more (#1602)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sun, 2 Jun 2019 10:17:50 +0000 (19:17 +0900)
committerGitHub <noreply@github.com>
Sun, 2 Jun 2019 10:17:50 +0000 (19:17 +0900)
This PR will fix task switcher (Alt+Tab) as Win2k3. It became more reliable. CORE-15653
c.f. Raymond Chen's article: http://blogs.msdn.com/b/oldnewthing/archive/2007/10/08/5351207.aspx

win32ss/user/user32/controls/appswitch.c

index ee9c106..ac9c5d0 100644 (file)
@@ -209,15 +209,52 @@ BOOL CALLBACK EnumerateCallback(HWND window, LPARAM lParam)
    return TRUE;
 }
 
-static BOOL CALLBACK
-EnumWindowsProc(HWND hwnd, LPARAM lParam)
+static HWND GetNiceRootOwner(HWND hwnd)
 {
     HWND hwndOwner;
-    WCHAR szClass[64];
+    DWORD ExStyle, OwnerExStyle;
+
+    for (;;)
+    {
+        // A window with WS_EX_APPWINDOW is treated as if it has no owner
+        ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+        if (ExStyle & WS_EX_APPWINDOW)
+            break;
+
+        // Is the owner visible?
+        // An window with WS_EX_TOOLWINDOW is treated as if it weren't visible
+        hwndOwner = GetWindow(hwnd, GW_OWNER);
+        OwnerExStyle = GetWindowLong(hwndOwner, GWL_EXSTYLE);
+        if (!IsWindowVisible(hwndOwner) || (OwnerExStyle & WS_EX_TOOLWINDOW))
+            break;
+
+        hwnd = hwndOwner;
+    }
+
+    return hwnd;
+}
+
+// c.f. http://blogs.msdn.com/b/oldnewthing/archive/2007/10/08/5351207.aspx
+BOOL IsAltTabWindow(HWND hwnd)
+{
     DWORD ExStyle;
+    RECT rc;
+    HWND hwndTry, hwndWalk;
+    WCHAR szClass[64];
 
+    // must be visible
     if (!IsWindowVisible(hwnd))
-        return TRUE;
+        return FALSE;
+
+    // must not be WS_EX_TOOLWINDOW
+    ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+    if (ExStyle & WS_EX_TOOLWINDOW)
+        return FALSE;
+
+    // must be not empty rect
+    GetWindowRect(hwnd, &rc);
+    if (IsRectEmpty(&rc))
+        return FALSE;
 
     // check special windows
     if (!GetClassNameW(hwnd, szClass, _countof(szClass)) ||
@@ -227,17 +264,34 @@ EnumWindowsProc(HWND hwnd, LPARAM lParam)
         return TRUE;
     }
 
-    ExStyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
-    if (ExStyle & WS_EX_TOOLWINDOW)
-        return TRUE;
+    // get 'nice' root owner
+    hwndWalk = GetNiceRootOwner(hwnd);
+
+    // walk back from hwndWalk toward hwnd
+    for (;;)
+    {
+        hwndTry = GetLastActivePopup(hwndWalk);
+        if (hwndTry == hwndWalk)
+            break;
+
+        ExStyle = GetWindowLong(hwndTry, GWL_EXSTYLE);
+        if (IsWindowVisible(hwndTry) && !(ExStyle & WS_EX_TOOLWINDOW))
+            break;
+
+        hwndWalk = hwndTry;
+    }
+
+    return hwnd == hwndTry;     // Reached?
+}
 
-    hwndOwner = GetWindow(hwnd, GW_OWNER);
-    if (!IsWindowVisible(hwndOwner) || (ExStyle & WS_EX_APPWINDOW))
+static BOOL CALLBACK
+EnumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+    if (IsAltTabWindow(hwnd))
     {
         if (!EnumerateCallback(hwnd, lParam))
             return FALSE;
     }
-
     return TRUE;
 }