22// @id taskbar-vertical
33// @name Vertical Taskbar for Windows 11
44// @description Finally, the missing vertical taskbar option for Windows 11! Move the taskbar to the left or right side of the screen.
5- // @version 1.3.11
5+ // @version 1.3.12
66// @author m417z
77// @github https://github.com/m417z
88// @twitter https://twitter.com/m417z
@@ -201,6 +201,10 @@ HWND g_notificationCenterWnd;
201201
202202std::vector<winrt::weak_ref<XamlRoot>> g_notifyIconsUpdated;
203203
204+ // XamlRoots (taskbars) that already have a deferred ApplyStyle queued, used to
205+ // coalesce redundant applies.
206+ std::vector<XamlRoot> g_applyStyleQueued;
207+
204208using FrameworkElementLoadedEventRevoker = winrt::impl::event_revoker<
205209 IFrameworkElement,
206210 &winrt::impl::abi<IFrameworkElement>::type::remove_Loaded>;
@@ -577,6 +581,7 @@ bool IsTaskbarWindow(HWND hWnd) {
577581
578582bool UpdateNotifyIcons (XamlRoot xamlRoot);
579583bool UpdateNotifyIconsIfNeeded (XamlRoot xamlRoot);
584+ bool ApplyStyleIfNeeded (XamlRoot xamlRoot);
580585
581586HWND FindCurrentProcessTaskbarWnd () {
582587 HWND hTaskbarWnd = nullptr ;
@@ -1112,7 +1117,7 @@ void WINAPI SystemTrayController_UpdateFrameSize_Hook(void* pThis) {
11121117 return 0 ;
11131118 }
11141119
1115- // Find the last height offset to reset the height value.
1120+ // Find the last height offset to reset the height value.
11161121#if defined(_M_X64)
11171122 // 66 0f 2e b3 b0 00 00 00 UCOMISD uVar4,qword ptr [RBX + 0xb0]
11181123 // 7a 4c JP LAB_180075641
@@ -1469,6 +1474,40 @@ bool ApplyStyle(XamlRoot xamlRoot) {
14691474 return true ;
14701475}
14711476
1477+ // Applies the style asynchronously, outside the measure pass that triggered it.
1478+ // Mutating layout properties from within MeasureOverride can cause an
1479+ // AG_E_LAYOUT_CYCLE fail-fast on some Taskbar.View.dll builds. At most one
1480+ // apply is queued per XamlRoot (taskbar) at a time, otherwise every measure
1481+ // pass of the taskbar and system tray frames would queue a redundant one.
1482+ void QueueApplyStyle (FrameworkElement element) {
1483+ auto xamlRoot = element.XamlRoot ();
1484+ if (!xamlRoot) {
1485+ return ;
1486+ }
1487+
1488+ if (std::find (g_applyStyleQueued.begin (), g_applyStyleQueued.end (),
1489+ xamlRoot) != g_applyStyleQueued.end ()) {
1490+ return ;
1491+ }
1492+
1493+ g_applyStyleQueued.push_back (xamlRoot);
1494+
1495+ element.Dispatcher ().TryRunAsync (
1496+ winrt::Windows::UI ::Core::CoreDispatcherPriority::Normal, [xamlRoot]() {
1497+ g_applyStyleQueued.erase (
1498+ std::remove (g_applyStyleQueued.begin (),
1499+ g_applyStyleQueued.end (), xamlRoot),
1500+ g_applyStyleQueued.end ());
1501+
1502+ try {
1503+ ApplyStyleIfNeeded (xamlRoot);
1504+ } catch (...) {
1505+ HRESULT hr = winrt::to_hresult ();
1506+ Wh_Log (L" Error %08X" , hr);
1507+ }
1508+ });
1509+ }
1510+
14721511using TaskbarFrame_MeasureOverride_t =
14731512 int (WINAPI *)(void * pThis,
14741513 winrt::Windows::Foundation::Size size,
@@ -1487,12 +1526,7 @@ int WINAPI TaskbarFrame_MeasureOverride_Hook(
14871526 ->QueryInterface (winrt::guid_of<FrameworkElement>(),
14881527 winrt::put_abi (taskbarFrame));
14891528 if (taskbarFrame) {
1490- try {
1491- ApplyStyle (taskbarFrame.XamlRoot ());
1492- } catch (...) {
1493- HRESULT hr = winrt::to_hresult ();
1494- Wh_Log (L" Error %08X" , hr);
1495- }
1529+ QueueApplyStyle (taskbarFrame);
14961530 }
14971531
14981532 int ret = TaskbarFrame_MeasureOverride_Original (pThis, size, resultSize);
@@ -1522,12 +1556,7 @@ int WINAPI SystemTrayFrame_MeasureOverride_Hook(
15221556 ->QueryInterface (winrt::guid_of<FrameworkElement>(),
15231557 winrt::put_abi (systemTrayFrame));
15241558 if (systemTrayFrame) {
1525- try {
1526- ApplyStyle (systemTrayFrame.XamlRoot ());
1527- } catch (...) {
1528- HRESULT hr = winrt::to_hresult ();
1529- Wh_Log (L" Error %08X" , hr);
1530- }
1559+ QueueApplyStyle (systemTrayFrame);
15311560 }
15321561
15331562 int ret = SystemTrayFrame_MeasureOverride_Original (pThis, size, resultSize);
@@ -1854,29 +1883,27 @@ void ApplySystemTrayIconStyle(FrameworkElement systemTrayIconElement) {
18541883 }
18551884 }
18561885
1857- SystemTrayIconType iconType = SystemTrayIconType::Other;
1858-
1859- auto iconContent =
1860- FindChildByClassName (contentGrid, L" SystemTray.TextIconContent" );
1861-
1862- if (!iconContent) {
1863- iconContent =
1864- FindChildByClassName (contentGrid, L" SystemTray.BatteryIconContent" );
1865- if (iconContent) {
1866- iconType = SystemTrayIconType::Battery;
1867- }
1868- }
1869-
1870- if (!iconContent) {
1871- iconContent = FindChildByClassName (
1872- contentGrid, L" SystemTray.LanguageTextIconContent" );
1873- }
1886+ static const struct {
1887+ PCWSTR className;
1888+ SystemTrayIconType iconType;
1889+ } iconContentTypes[] = {
1890+ {L" SystemTray.TextIconContent" , SystemTrayIconType::Other},
1891+ {L" SystemTray.BatteryIconContent" , SystemTrayIconType::Battery},
1892+ {L" SystemTray.DateTimeIconContent" , SystemTrayIconType::DateTime},
1893+ // Language bar main icon.
1894+ {L" SystemTray.LanguageTextIconContent" , SystemTrayIconType::Other},
1895+ {L" SystemTray.LanguageImageIconContent" , SystemTrayIconType::Other},
1896+ // Language bar supplementary icon.
1897+ {L" SystemTray.ImageIconContent" , SystemTrayIconType::Other},
1898+ };
18741899
1875- if (!iconContent) {
1876- iconContent = FindChildByClassName (contentGrid,
1877- L" SystemTray.DateTimeIconContent" );
1900+ FrameworkElement iconContent = nullptr ;
1901+ SystemTrayIconType iconType = SystemTrayIconType::Other;
1902+ for (const auto & [className, type] : iconContentTypes) {
1903+ iconContent = FindChildByClassName (contentGrid, className);
18781904 if (iconContent) {
1879- iconType = SystemTrayIconType::DateTime;
1905+ iconType = type;
1906+ break ;
18801907 }
18811908 }
18821909
@@ -2001,11 +2028,6 @@ void WINAPI DateTimeIconContent_OnApplyTemplate_Hook(void* pThis) {
20012028}
20022029
20032030bool ApplyStyleIfNeeded (XamlRoot xamlRoot) {
2004- // Calling this when unloading causes a crash with a secondary taskbar.
2005- if (g_unloading) {
2006- return true ;
2007- }
2008-
20092031 FrameworkElement contentGrid =
20102032 xamlRoot.Content ().try_as <FrameworkElement>();
20112033
0 commit comments