https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f7fc10c17c7172aee040c1cb2f631d6824917d80

commit f7fc10c17c7172aee040c1cb2f631d6824917d80
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sun Jun 2 19:17:50 2019 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sun Jun 2 19:17:50 2019 +0900

    [WIN32SS][USER32] Fix Task Switcher more (#1602)
    
    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 | 74 +++++++++++++++++++++++++++-----
 1 file changed, 64 insertions(+), 10 deletions(-)

diff --git a/win32ss/user/user32/controls/appswitch.c 
b/win32ss/user/user32/controls/appswitch.c
index ee9c10677cc..ac9c5d0ee24 100644
--- a/win32ss/user/user32/controls/appswitch.c
+++ b/win32ss/user/user32/controls/appswitch.c
@@ -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;
 }
 

Reply via email to