[EXPLORER] Add fullscreen handling (#8105)

Adds support for handling fullscreen
applications (a.k.a. “rude apps”) so
the taskbar can hide or show
appropriately.

JIRA issue: CORE-11242, CORE-15681,
CORE-16056, CORE-16063, CORE-16131,
CORE-16132, CORE-16192, CORE-16196,
CORE-16249, CORE-16290, CORE-16313,
CORE-16320, CORE-16322, CORE-16347,
CORE-16584, CORE-19795, CORE-9862,
CORE-16230, CORE-10738, 
and CORE-12263.

- Removes legacy pulse/timer logic in
  the tray window and adds a fullscreen
  notification workflow.
- Implements fullscreen detection
  across monitors in the task switcher,
  using a sequence of validation timers.
- Defines a new ITrayWindow::
  NotifyFullScreenToAppBars interface
  method to broadcast fullscreen state
  to appbars.
This commit is contained in:
Katayama Hirofumi MZ 2025-06-15 21:20:45 +09:00 committed by GitHub
parent 7ec3a7e98b
commit 4e7702a6a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 258 additions and 77 deletions

View file

@ -133,7 +133,6 @@ HRESULT WINAPI _CBandSite_CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void
#define TWM_OPENSTARTMENU (WM_USER + 260) #define TWM_OPENSTARTMENU (WM_USER + 260)
#define TWM_SETTINGSCHANGED (WM_USER + 300) #define TWM_SETTINGSCHANGED (WM_USER + 300)
#define TWM_SETZORDER (WM_USER + 338) #define TWM_SETZORDER (WM_USER + 338)
#define TWM_PULSE (WM_USER + 400)
extern const GUID IID_IShellDesktopTray; extern const GUID IID_IShellDesktopTray;
@ -154,6 +153,7 @@ DECLARE_INTERFACE_(ITrayWindow, IUnknown)
STDMETHOD_(BOOL, ExecContextMenuCmd) (THIS_ UINT uiCmd) PURE; STDMETHOD_(BOOL, ExecContextMenuCmd) (THIS_ UINT uiCmd) PURE;
STDMETHOD_(BOOL, Lock) (THIS_ BOOL bLock) PURE; STDMETHOD_(BOOL, Lock) (THIS_ BOOL bLock) PURE;
STDMETHOD_(BOOL, IsTaskWnd) (THIS_ HWND hWnd) PURE; STDMETHOD_(BOOL, IsTaskWnd) (THIS_ HWND hWnd) PURE;
STDMETHOD_(HRESULT, NotifyFullScreenToAppBars)(THIS_ HMONITOR hMonitor, BOOL bFullOpening) PURE;
}; };
#undef INTERFACE #undef INTERFACE
@ -172,6 +172,7 @@ DECLARE_INTERFACE_(ITrayWindow, IUnknown)
#define ITrayWindow_ExecContextMenuCmd(p,a) (p)->lpVtbl->ExecContextMenuCmd(p,a) #define ITrayWindow_ExecContextMenuCmd(p,a) (p)->lpVtbl->ExecContextMenuCmd(p,a)
#define ITrayWindow_Lock(p,a) (p)->lpVtbl->Lock(p,a) #define ITrayWindow_Lock(p,a) (p)->lpVtbl->Lock(p,a)
#define ITrayWindow_IsTaskWnd(p,a) (p)->lpVtbl->IsTaskWnd(p,a) #define ITrayWindow_IsTaskWnd(p,a) (p)->lpVtbl->IsTaskWnd(p,a)
#define ITrayWindow_NotifyFullScreenToAppBars(p,a,b) (p)->lpVtbl->NotifyFullScreenToAppBars(p,a,b)
#endif #endif
HRESULT CreateTrayWindow(ITrayWindow ** ppTray); HRESULT CreateTrayWindow(ITrayWindow ** ppTray);

View file

@ -31,6 +31,89 @@
#define MAX_TASKS_COUNT (0x7FFF) #define MAX_TASKS_COUNT (0x7FFF)
#define TASK_ITEM_ARRAY_ALLOC 64 #define TASK_ITEM_ARRAY_ALLOC 64
//************************************************************************
// Fullscreen windows (a.k.a. rude apps) checker
#define TIMER_ID_VALIDATE_RUDE_APP 5
#define VALIDATE_RUDE_INTERVAL 1000
#define VALIDATE_RUDE_MAX_COUNT 5
static BOOL
SHELL_GetMonitorRect(
_In_opt_ HMONITOR hMonitor,
_Out_opt_ PRECT prcDest,
_In_ BOOL bWorkAreaOnly)
{
MONITORINFO mi = { sizeof(mi) };
if (!hMonitor || !::GetMonitorInfoW(hMonitor, &mi))
{
if (!prcDest)
return FALSE;
if (bWorkAreaOnly)
::SystemParametersInfoW(SPI_GETWORKAREA, 0, prcDest, 0);
else
::SetRect(prcDest, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
return FALSE;
}
if (prcDest)
*prcDest = (bWorkAreaOnly ? mi.rcWork : mi.rcMonitor);
return TRUE;
}
static BOOL
SHELL_IsParentOwnerOrSelf(_In_ HWND hwndTarget, _In_ HWND hWnd)
{
for (; hWnd; hWnd = ::GetParent(hWnd))
{
if (hWnd == hwndTarget)
return TRUE;
}
return FALSE;
}
static BOOL
SHELL_IsRudeWindowActive(_In_ HWND hWnd)
{
HWND hwndFore = ::GetForegroundWindow();
DWORD dwThreadId = ::GetWindowThreadProcessId(hWnd, NULL);
return dwThreadId == ::GetWindowThreadProcessId(hwndFore, NULL) ||
SHELL_IsParentOwnerOrSelf(hWnd, hwndFore);
}
static BOOL
SHELL_IsRudeWindow(_In_opt_ HMONITOR hMonitor, _In_ HWND hWnd, _In_ BOOL bDontCheckActive)
{
if (!::IsWindowVisible(hWnd) || hWnd == ::GetDesktopWindow())
return FALSE;
RECT rcMonitor;
SHELL_GetMonitorRect(hMonitor, &rcMonitor, FALSE);
DWORD style = ::GetWindowLongPtrW(hWnd, GWL_STYLE);
RECT rcWnd;
enum { CHECK_STYLE = WS_THICKFRAME | WS_DLGFRAME | WS_BORDER };
if ((style & CHECK_STYLE) == CHECK_STYLE)
{
::GetClientRect(hWnd, &rcWnd); // Ignore frame
::MapWindowPoints(hWnd, NULL, (PPOINT)&rcWnd, sizeof(RECT) / sizeof(POINT));
}
else
{
::GetWindowRect(hWnd, &rcWnd);
}
RECT rcUnion;
::UnionRect(&rcUnion, &rcWnd, &rcMonitor);
return ::EqualRect(&rcUnion, &rcWnd) && (bDontCheckActive || SHELL_IsRudeWindowActive(hWnd));
}
////////////////////////////////////////////////////////////////
const WCHAR szTaskSwitchWndClass[] = L"MSTaskSwWClass"; const WCHAR szTaskSwitchWndClass[] = L"MSTaskSwWClass";
const WCHAR szRunningApps[] = L"Running Applications"; const WCHAR szRunningApps[] = L"Running Applications";
@ -322,6 +405,8 @@ class CTaskSwitchWnd :
BOOL m_IsGroupingEnabled; BOOL m_IsGroupingEnabled;
BOOL m_IsDestroying; BOOL m_IsDestroying;
INT m_nRudeAppValidationCounter;
SIZE m_ButtonSize; SIZE m_ButtonSize;
UINT m_uHardErrorMsg; UINT m_uHardErrorMsg;
@ -340,7 +425,8 @@ public:
m_ButtonCount(0), m_ButtonCount(0),
m_ImageList(NULL), m_ImageList(NULL),
m_IsGroupingEnabled(FALSE), m_IsGroupingEnabled(FALSE),
m_IsDestroying(FALSE) m_IsDestroying(FALSE),
m_nRudeAppValidationCounter(0)
{ {
ZeroMemory(&m_ButtonSize, sizeof(m_ButtonSize)); ZeroMemory(&m_ButtonSize, sizeof(m_ButtonSize));
m_uHardErrorMsg = RegisterWindowMessageW(L"HardError"); m_uHardErrorMsg = RegisterWindowMessageW(L"HardError");
@ -1464,6 +1550,8 @@ public:
{ {
m_IsDestroying = TRUE; m_IsDestroying = TRUE;
KillTimer(TIMER_ID_VALIDATE_RUDE_APP);
/* Unregister the shell hook */ /* Unregister the shell hook */
RegisterShellHook(m_hWnd, FALSE); RegisterShellHook(m_hWnd, FALSE);
@ -1472,12 +1560,6 @@ public:
return TRUE; return TRUE;
} }
VOID SendPulseToTray(BOOL bDelete, HWND hwndActive)
{
HWND hwndTray = m_Tray->GetHWND();
::SendMessage(hwndTray, TWM_PULSE, bDelete, (LPARAM)hwndActive);
}
static BOOL InvokeRegistryAppKeyCommand(UINT uAppCmd) static BOOL InvokeRegistryAppKeyCommand(UINT uAppCmd)
{ {
BOOL bResult = FALSE; BOOL bResult = FALSE;
@ -1554,19 +1636,18 @@ public:
break; break;
case HSHELL_WINDOWCREATED: case HSHELL_WINDOWCREATED:
SendPulseToTray(FALSE, (HWND)lParam);
AddTask((HWND) lParam); AddTask((HWND) lParam);
break; break;
case HSHELL_WINDOWDESTROYED: case HSHELL_WINDOWDESTROYED:
/* The window still exists! Delay destroying it a bit */ /* The window still exists! Delay destroying it a bit */
SendPulseToTray(TRUE, (HWND)lParam); OnWindowDestroyed((HWND)lParam);
DeleteTask((HWND)lParam); DeleteTask((HWND)lParam);
break; break;
case HSHELL_RUDEAPPACTIVATED: case HSHELL_RUDEAPPACTIVATED:
case HSHELL_WINDOWACTIVATED: case HSHELL_WINDOWACTIVATED:
SendPulseToTray(FALSE, (HWND)lParam); OnWindowActivated((HWND)lParam);
ActivateTask((HWND)lParam); ActivateTask((HWND)lParam);
break; break;
@ -1674,7 +1755,6 @@ public:
TaskItem = FindTaskItemByIndex((INT) wIndex); TaskItem = FindTaskItemByIndex((INT) wIndex);
if (TaskItem != NULL) if (TaskItem != NULL)
{ {
SendPulseToTray(FALSE, TaskItem->hWnd);
HandleTaskItemClick(TaskItem); HandleTaskItemClick(TaskItem);
return TRUE; return TRUE;
} }
@ -1810,6 +1890,130 @@ public:
return Ret; return Ret;
} }
// Internal structure for IsRudeEnumProc
typedef struct tagRUDEAPPDATA
{
HMONITOR hTargetMonitor;
HWND hwndFound;
HWND hwndFirstCheck;
} RUDEAPPDATA, *PRUDEAPPDATA;
// Find any rude app
static BOOL CALLBACK
IsRudeEnumProc(_In_ HWND hwnd, _In_ LPARAM lParam)
{
PRUDEAPPDATA pData = (PRUDEAPPDATA)lParam;
HMONITOR hMon = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (!hMon ||
(pData->hTargetMonitor && pData->hTargetMonitor != hMon) ||
!SHELL_IsRudeWindow(hMon, hwnd, (hwnd == pData->hwndFirstCheck)))
{
return TRUE; // Continue
}
pData->hwndFound = hwnd;
return FALSE; // Finish
}
// Internal structure for FullScreenEnumProc
typedef struct tagFULLSCREENDATA
{
const RECT *pRect;
HMONITOR hTargetMonitor;
ITrayWindow *pTray;
} FULLSCREENDATA, *PFULLSCREENDATA;
// Notify ABN_FULLSCREENAPP for each monitor
static BOOL CALLBACK
FullScreenEnumProc(_In_ HMONITOR hMonitor, _In_opt_ HDC hDC, _In_ LPRECT prc, _In_ LPARAM lParam)
{
PFULLSCREENDATA pData = (PFULLSCREENDATA)lParam;
BOOL bFullOpening = (pData->hTargetMonitor == hMonitor);
if (!bFullOpening && pData->pRect)
{
RECT rc, rcMon;
SHELL_GetMonitorRect(hMonitor, &rcMon, FALSE);
::IntersectRect(&rc, &rcMon, pData->pRect);
bFullOpening = ::EqualRect(&rc, &rcMon);
}
// Notify ABN_FULLSCREENAPP to appbars
pData->pTray->NotifyFullScreenToAppBars(hMonitor, bFullOpening);
return TRUE;
}
void HandleFullScreenApp(_In_opt_ HWND hwndRude)
{
// Notify ABN_FULLSCREENAPP for every monitor
RECT rc;
FULLSCREENDATA Data = { NULL, NULL, NULL };
if (hwndRude && ::GetWindowRect(hwndRude, &rc))
{
Data.pRect = &rc;
Data.hTargetMonitor = ::MonitorFromWindow(hwndRude, MONITOR_DEFAULTTONULL);
}
Data.pTray = m_Tray;
::EnumDisplayMonitors(NULL, NULL, FullScreenEnumProc, (LPARAM)&Data);
// Make the taskbar bottom or top
UINT uFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER;
HWND hwndTray = m_Tray->GetHWND();
::SetWindowPos(hwndTray, (hwndRude ? HWND_BOTTOM : HWND_TOP), 0, 0, 0, 0, uFlags);
if (hwndRude)
{
DWORD exstyle = (DWORD)::GetWindowLongPtrW(hwndRude, GWL_EXSTYLE);
if (!(exstyle & WS_EX_TOPMOST) && !SHELL_IsRudeWindowActive(hwndRude))
::SwitchToThisWindow(hwndRude, TRUE);
}
// FIXME: NIN_BALLOONHIDE
// FIXME: NIN_POPUPCLOSE
}
HWND FindRudeApp(_In_opt_ HWND hwndFirstCheck)
{
// Quick check
HMONITOR hMon = MonitorFromWindow(hwndFirstCheck, MONITOR_DEFAULTTONEAREST);
RUDEAPPDATA data = { hMon, NULL, hwndFirstCheck };
if (::IsWindow(hwndFirstCheck) && !IsRudeEnumProc(hwndFirstCheck, (LPARAM)&data))
return hwndFirstCheck;
// Slow check
::EnumWindows(IsRudeEnumProc, (LPARAM)&data);
return data.hwndFound;
}
// WM_WINDOWPOSCHANGED
LRESULT OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// Re-start rude app validation
KillTimer(TIMER_ID_VALIDATE_RUDE_APP);
SetTimer(TIMER_ID_VALIDATE_RUDE_APP, VALIDATE_RUDE_INTERVAL, NULL);
m_nRudeAppValidationCounter = 0;
bHandled = FALSE;
return 0;
}
// HSHELL_WINDOWACTIVATED, HSHELL_RUDEAPPACTIVATED
void OnWindowActivated(_In_ HWND hwndTarget)
{
// Re-start rude app validation
KillTimer(TIMER_ID_VALIDATE_RUDE_APP);
SetTimer(TIMER_ID_VALIDATE_RUDE_APP, VALIDATE_RUDE_INTERVAL, NULL);
m_nRudeAppValidationCounter = 0;
}
// HSHELL_WINDOWDESTROYED
void OnWindowDestroyed(_In_ HWND hwndTarget)
{
HWND hwndRude = FindRudeApp(hwndTarget);
HandleFullScreenApp(hwndRude);
}
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
HDC hdc = (HDC) wParam; HDC hdc = (HDC) wParam;
@ -1963,14 +2167,32 @@ public:
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
#if DUMP_TASKS != 0
switch (wParam) switch (wParam)
{ {
#if DUMP_TASKS != 0
case 1: case 1:
DumpTasks(); DumpTasks();
break; break;
}
#endif #endif
case TIMER_ID_VALIDATE_RUDE_APP:
{
// Real activation of rude app might take some time after HSHELL_...ACTIVATED.
// Wait up to 5 seconds with validating the rude app at each second.
HWND hwndRude = FindRudeApp(NULL);
HandleFullScreenApp(hwndRude);
KillTimer(wParam);
++m_nRudeAppValidationCounter;
if (m_nRudeAppValidationCounter < VALIDATE_RUDE_MAX_COUNT && !hwndRude)
SetTimer(wParam, VALIDATE_RUDE_INTERVAL, NULL);
break;
}
default:
{
WARN("Unknown timer ID: %p\n", wParam);
break;
}
}
return TRUE; return TRUE;
} }
@ -2054,6 +2276,7 @@ public:
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
MESSAGE_HANDLER(WM_KLUDGEMINRECT, OnKludgeItemRect) MESSAGE_HANDLER(WM_KLUDGEMINRECT, OnKludgeItemRect)
MESSAGE_HANDLER(WM_COPYDATA, OnCopyData) MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
END_MSG_MAP() END_MSG_MAP()
DECLARE_NOT_AGGREGATABLE(CTaskSwitchWnd) DECLARE_NOT_AGGREGATABLE(CTaskSwitchWnd)

View file

@ -300,7 +300,6 @@ public:
BEGIN_MSG_MAP(CStartButton) BEGIN_MSG_MAP(CStartButton)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
END_MSG_MAP() END_MSG_MAP()
}; };
class CTrayWindow : class CTrayWindow :
@ -362,7 +361,6 @@ public:
DWORD InSizeMove : 1; DWORD InSizeMove : 1;
DWORD IsDragging : 1; DWORD IsDragging : 1;
DWORD NewPosSize : 1; DWORD NewPosSize : 1;
DWORD IgnorePulse : 1;
}; };
}; };
@ -391,7 +389,6 @@ public:
ZeroMemory(&m_TraySize, sizeof(m_TraySize)); ZeroMemory(&m_TraySize, sizeof(m_TraySize));
ZeroMemory(&m_AutoHideOffset, sizeof(m_AutoHideOffset)); ZeroMemory(&m_AutoHideOffset, sizeof(m_AutoHideOffset));
ZeroMemory(&m_MouseTrackingInfo, sizeof(m_MouseTrackingInfo)); ZeroMemory(&m_MouseTrackingInfo, sizeof(m_MouseTrackingInfo));
IgnorePulse = TRUE;
} }
virtual ~CTrayWindow() virtual ~CTrayWindow()
@ -2392,12 +2389,8 @@ ChangePos:
return TRUE; return TRUE;
} }
#define TIMER_ID_IGNOREPULSERESET 888
#define TIMER_IGNOREPULSERESET_TIMEOUT 200
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
KillTimer(TIMER_ID_IGNOREPULSERESET);
return 0; return 0;
} }
@ -3035,39 +3028,6 @@ HandleTrayContextMenu:
return (LRESULT)m_TaskSwitch; return (LRESULT)m_TaskSwitch;
} }
void RestoreMinimizedNonTaskWnds(BOOL bDestroyed, HWND hwndActive)
{
for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
{
HWND hwnd = g_MinimizedAll[i].hwnd;
if (!hwnd || hwndActive == hwnd)
continue;
if (::IsWindowVisible(hwnd) && ::IsIconic(hwnd) &&
(!IsTaskWnd(hwnd) || !::IsWindowEnabled(hwnd)))
{
::SetWindowPlacement(hwnd, &g_MinimizedAll[i].wndpl); // Restore
}
}
if (bDestroyed)
g_MinimizedAll.RemoveAll();
else
::SetForegroundWindow(hwndActive);
}
LRESULT OnPulse(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (IgnorePulse)
return 0;
KillTimer(TIMER_ID_IGNOREPULSERESET);
IgnorePulse = TRUE;
RestoreMinimizedNonTaskWnds((BOOL)wParam, (HWND)lParam);
SetTimer(TIMER_ID_IGNOREPULSERESET, TIMER_IGNOREPULSERESET_TIMEOUT, NULL);
return 0;
}
// TWM_SETZORDER // TWM_SETZORDER
LRESULT OnSetZOrder(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnSetZOrder(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
@ -3075,6 +3035,12 @@ HandleTrayContextMenu:
SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
} }
STDMETHODIMP NotifyFullScreenToAppBars(HMONITOR hMonitor, BOOL bFullOpening) override
{
OnAppBarNotifyAll(hMonitor, NULL, ABN_FULLSCREENAPP, bFullOpening);
return S_OK;
}
LRESULT OnHotkey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnHotkey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
return HandleHotKey(wParam); return HandleHotKey(wParam);
@ -3126,9 +3092,6 @@ HandleTrayContextMenu:
VOID MinimizeAll(BOOL bShowDesktop = FALSE) VOID MinimizeAll(BOOL bShowDesktop = FALSE)
{ {
IgnorePulse = TRUE;
KillTimer(TIMER_ID_IGNOREPULSERESET);
MINIMIZE_INFO info; MINIMIZE_INFO info;
info.hwndDesktop = GetDesktopWindow();; info.hwndDesktop = GetDesktopWindow();;
info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL); info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
@ -3139,7 +3102,6 @@ HandleTrayContextMenu:
::SetForegroundWindow(m_DesktopWnd); ::SetForegroundWindow(m_DesktopWnd);
::SetFocus(m_DesktopWnd); ::SetFocus(m_DesktopWnd);
SetTimer(TIMER_ID_IGNOREPULSERESET, TIMER_IGNOREPULSERESET_TIMEOUT, NULL);
} }
VOID ShowDesktop() VOID ShowDesktop()
@ -3149,9 +3111,6 @@ HandleTrayContextMenu:
VOID RestoreAll() VOID RestoreAll()
{ {
IgnorePulse = TRUE;
KillTimer(TIMER_ID_IGNOREPULSERESET);
for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i) for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
{ {
HWND hwnd = g_MinimizedAll[i].hwnd; HWND hwnd = g_MinimizedAll[i].hwnd;
@ -3160,7 +3119,6 @@ HandleTrayContextMenu:
} }
g_MinimizedAll.RemoveAll(); g_MinimizedAll.RemoveAll();
SetTimer(TIMER_ID_IGNOREPULSERESET, TIMER_IGNOREPULSERESET_TIMEOUT, NULL);
} }
LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@ -3193,18 +3151,18 @@ HandleTrayContextMenu:
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
if (wParam == TIMER_ID_MOUSETRACK) switch (wParam)
{ {
case TIMER_ID_MOUSETRACK:
ProcessMouseTracking(); ProcessMouseTracking();
} break;
else if (wParam == TIMER_ID_AUTOHIDE) case TIMER_ID_AUTOHIDE:
{
ProcessAutoHide(); ProcessAutoHide();
} break;
else if (wParam == TIMER_ID_IGNOREPULSERESET) default:
{ WARN("Invalid timer ID: %u\n", (UINT)wParam);
KillTimer(TIMER_ID_IGNOREPULSERESET); bHandled = FALSE;
IgnorePulse = FALSE; break;
} }
return 0; return 0;
} }
@ -3453,7 +3411,6 @@ HandleTrayContextMenu:
MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows) MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows)
MESSAGE_HANDLER(TWM_GETTASKSWITCH, OnGetTaskSwitch) MESSAGE_HANDLER(TWM_GETTASKSWITCH, OnGetTaskSwitch)
MESSAGE_HANDLER(TWM_SETZORDER, OnSetZOrder) MESSAGE_HANDLER(TWM_SETZORDER, OnSetZOrder)
MESSAGE_HANDLER(TWM_PULSE, OnPulse)
ALT_MSG_MAP(1) ALT_MSG_MAP(1)
END_MSG_MAP() END_MSG_MAP()