[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
This commit is contained in:
Katayama Hirofumi MZ 2019-06-02 19:17:50 +09:00 committed by GitHub
parent 9c3c0d123b
commit f7fc10c17c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View 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;
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);
hwndOwner = GetWindow(hwnd, GW_OWNER);
if (!IsWindowVisible(hwndOwner) || (ExStyle & WS_EX_APPWINDOW))
// 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?
}
static BOOL CALLBACK
EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsAltTabWindow(hwnd))
{
if (!EnumerateCallback(hwnd, lParam))
return FALSE;
}
return TRUE;
}