From 9fb911398e6158de79c22c65782a2c078861e845 Mon Sep 17 00:00:00 2001 From: Michael Maltsev <4129781+m417z@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:51:35 +0200 Subject: [PATCH] Taskbar Labels for Windows 11 v1.3.3 * The "Minimum taskbar item width" option can now be set to any value. Only 44 or larger values were previously supported. * Fixed a crash which could occur in some cases due to an incorrect running indicator width calculation. * Fixed taskbar settings (the "Combine taskbar buttons and hide labels" option) affecting some of the taskbar behavior, such as left click on combined items. --- mods/taskbar-labels.wh.cpp | 177 +++++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 68 deletions(-) diff --git a/mods/taskbar-labels.wh.cpp b/mods/taskbar-labels.wh.cpp index efae2ba1..7df9655e 100644 --- a/mods/taskbar-labels.wh.cpp +++ b/mods/taskbar-labels.wh.cpp @@ -2,7 +2,7 @@ // @id taskbar-labels // @name Taskbar Labels for Windows 11 // @description Customize text labels and combining for running programs on the taskbar (Windows 11 only) -// @version 1.3.2 +// @version 1.3.3 // @author m417z // @github https://github.com/m417z // @twitter https://twitter.com/m417z @@ -278,16 +278,12 @@ FrameworkElement FindChildByClassName(FrameworkElement element, } HWND GetTaskbarWnd() { - static HWND hTaskbarWnd; + HWND hTaskbarWnd = FindWindow(L"Shell_TrayWnd", nullptr); - if (!hTaskbarWnd) { - HWND hWnd = FindWindow(L"Shell_TrayWnd", nullptr); - - DWORD processId = 0; - if (hWnd && GetWindowThreadProcessId(hWnd, &processId) && - processId == GetCurrentProcessId()) { - hTaskbarWnd = hWnd; - } + DWORD processId = 0; + if (!hTaskbarWnd || !GetWindowThreadProcessId(hTaskbarWnd, &processId) || + processId != GetCurrentProcessId()) { + return nullptr; } return hTaskbarWnd; @@ -382,6 +378,8 @@ void RecalculateLabels() { g_applyingSettings = false; } +void* TaskbarSettings_GroupingMode_Original; + using TaskListButton_get_IsRunning_t = HRESULT(WINAPI*)(void* pThis, bool* running); TaskListButton_get_IsRunning_t TaskListButton_get_IsRunning_Original; @@ -1035,18 +1033,21 @@ void UpdateTaskListButtonWithLabelStyle( double minWidth = 0; - if (indicatorStyle == IndicatorStyle::centerFixed) { - // Without this, the indicator isn't centered. - minWidth = indicatorElement.Width(); - } else if (indicatorStyle == IndicatorStyle::centerDynamic) { - if (firstColumnWidthPixels > 0) { - minWidth = indicatorElement.Width() * taskListButtonWidth / - firstColumnWidthPixels; - } - } else if (indicatorStyle == IndicatorStyle::fullWidth) { - minWidth = taskListButtonWidth - 6; - if (minWidth < 0) { - minWidth = 0; + double indicatorElementWidth = indicatorElement.Width(); + if (indicatorElementWidth > 0) { + if (indicatorStyle == IndicatorStyle::centerFixed) { + // Without this, the indicator isn't centered. + minWidth = indicatorElementWidth; + } else if (indicatorStyle == IndicatorStyle::centerDynamic) { + if (firstColumnWidthPixels > 0) { + minWidth = indicatorElementWidth * taskListButtonWidth / + firstColumnWidthPixels; + } + } else if (indicatorStyle == IndicatorStyle::fullWidth) { + minWidth = taskListButtonWidth - 6; + if (minWidth < 0) { + minWidth = 0; + } } } @@ -1058,11 +1059,13 @@ void UpdateTaskListButtonWithLabelStyle( double currentMinWidth = indicatorElement.MinWidth(); if (minWidth != currentMinWidth) { indicatorElement.MinWidth(0); - indicatorElement.Dispatcher().TryRunAsync( - winrt::Windows::UI::Core::CoreDispatcherPriority::High, - [indicatorElement, minWidth]() { - indicatorElement.MinWidth(minWidth); - }); + if (minWidth > 0) { + indicatorElement.Dispatcher().TryRunAsync( + winrt::Windows::UI::Core::CoreDispatcherPriority::High, + [indicatorElement, minWidth]() { + indicatorElement.MinWidth(minWidth); + }); + } } } else { indicatorElement.MinWidth(minWidth); @@ -1387,36 +1390,6 @@ void WINAPI TaskListButton_Icon_Hook(void* pThis, LONG_PTR randomAccessStream) { } } -using TaskbarSettings_GroupingMode_t = DWORD(WINAPI*)(void* pThis); -TaskbarSettings_GroupingMode_t TaskbarSettings_GroupingMode_Original; -DWORD WINAPI TaskbarSettings_GroupingMode_Hook(void* pThis) { - Wh_Log(L">"); - - DWORD ret = TaskbarSettings_GroupingMode_Original(pThis); - - if (!g_unloading) { - // 0 - Always - // 1 - When taskbar is full - // 2 - Never - if (g_settings.mode == Mode::noLabelsWithCombining || - g_settings.mode == Mode::labelsWithCombining) { - ret = 0; - } else if (ret == 0) { - ret = 2; - } - } - - if (g_overrideGroupingMode) { - if (ret == 0) { - ret = 2; - } else { - ret = 0; - } - } - - return ret; -} - using ITaskbarButton_get_MinScalableWidth_t = HRESULT(WINAPI*)(void* pThis, float* minWidth); ITaskbarButton_get_MinScalableWidth_t @@ -1430,8 +1403,8 @@ HRESULT ITaskbarButton_get_MinScalableWidth_Hook(void* pThis, float* minWidth) { *minWidth > 0) { // Allow to create many taskbar items before overflow appears. int minimumTaskbarItemWidth = g_settings.minimumTaskbarItemWidth; - if (minimumTaskbarItemWidth < 44) { - minimumTaskbarItemWidth = 44; + if (minimumTaskbarItemWidth < 1) { + minimumTaskbarItemWidth = 1; Wh_Log(L"minimumTaskbarItemWidth too small, using %d", minimumTaskbarItemWidth); } @@ -1622,6 +1595,67 @@ TaskListGroupViewModel_ITaskbarAppItemViewModel_get_HasLabel_Hook( return ret; } +using RegGetValueW_t = decltype(&RegGetValueW); +RegGetValueW_t RegGetValueW_Original; +LONG WINAPI RegGetValueW_Hook(HKEY hkey, + LPCWSTR lpSubKey, + LPCWSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData) { + LONG ret = RegGetValueW_Original(hkey, lpSubKey, lpValue, dwFlags, pdwType, + pvData, pcbData); + + if (hkey == HKEY_CURRENT_USER && lpSubKey && + _wcsicmp( + lpSubKey, + LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced)") == + 0 && + lpValue && + (_wcsicmp(lpValue, L"TaskbarGlomLevel") == 0 || + _wcsicmp(lpValue, L"MMTaskbarGlomLevel") == 0) && + dwFlags == RRF_RT_REG_DWORD && pvData && pcbData && + *pcbData == sizeof(DWORD)) { + Wh_Log(L">"); + + DWORD taskbarGlomLevel = (ret = ERROR_SUCCESS) ? *(DWORD*)pvData : 0; + DWORD taskbarGlomLevelOriginal = taskbarGlomLevel; + + if (!g_unloading) { + // 0 - Always + // 1 - When taskbar is full + // 2 - Never + if (g_settings.mode == Mode::noLabelsWithCombining || + g_settings.mode == Mode::labelsWithCombining) { + taskbarGlomLevel = 0; + } else if (taskbarGlomLevel == 0) { + taskbarGlomLevel = 2; + } + } + + if (g_overrideGroupingMode) { + if (taskbarGlomLevel == 0) { + taskbarGlomLevel = 2; + } else { + taskbarGlomLevel = 0; + } + } + + Wh_Log(L"Overriding TaskbarGlomLevel: %u->%u", taskbarGlomLevelOriginal, + taskbarGlomLevel); + *(DWORD*)pvData = taskbarGlomLevel; + + if (pdwType) { + *pdwType = REG_DWORD; + } + + ret = ERROR_SUCCESS; + } + + return ret; +} + void* wil_Feature_GetImpl_Original; using WilFeatureTraits_Feature_29785186_IsEnabled_t = @@ -2142,6 +2176,15 @@ bool HookTaskbarViewDllSymbols(HMODULE module) { // Taskbar.View.dll, ExplorerExtensions.dll SYMBOL_HOOK symbolHooks[] = // { + { + { + LR"(public: __cdecl winrt::impl::consume_WindowsUdk_UI_Shell_ITaskbarSettings5::GroupingMode(void)const )", + LR"(public: __cdecl winrt::impl::consume_WindowsUdk_UI_Shell_ITaskbarSettings5::GroupingMode(void)const __ptr64)", + }, + (void**)&TaskbarSettings_GroupingMode_Original, + nullptr, + true, + }, { { LR"(public: virtual int __cdecl winrt::impl::produce::get_IsRunning(bool *))", @@ -2189,15 +2232,6 @@ bool HookTaskbarViewDllSymbols(HMODULE module) { (void**)&TaskListButton_Icon_Original, (void*)TaskListButton_Icon_Hook, }, - { - { - LR"(public: __cdecl winrt::impl::consume_WindowsUdk_UI_Shell_ITaskbarSettings5::GroupingMode(void)const )", - LR"(public: __cdecl winrt::impl::consume_WindowsUdk_UI_Shell_ITaskbarSettings5::GroupingMode(void)const __ptr64)", - }, - (void**)&TaskbarSettings_GroupingMode_Original, - (void*)TaskbarSettings_GroupingMode_Hook, - true, - }, { { LR"(public: virtual int __cdecl winrt::impl::produce::get_MinScalableWidth(float *))", @@ -2380,6 +2414,13 @@ BOOL ModInitWithTaskbarView(HMODULE taskbarViewModule) { if (!HookTaskbarDllSymbols()) { return FALSE; } + } else { + HMODULE kernelBaseModule = GetModuleHandle(L"kernelbase.dll"); + FARPROC pKernelBaseRegGetValueW = + GetProcAddress(kernelBaseModule, "RegGetValueW"); + Wh_SetFunctionHook((void*)pKernelBaseRegGetValueW, + (void*)RegGetValueW_Hook, + (void**)&RegGetValueW_Original); } return TRUE;