Skip to content

Commit

Permalink
Cycle through taskbar windows on click v1.0 (#950)
Browse files Browse the repository at this point in the history
  • Loading branch information
m417z authored Sep 13, 2024
1 parent e3bf280 commit 2588c1b
Showing 1 changed file with 228 additions and 0 deletions.
228 changes: 228 additions & 0 deletions mods/taskbar-left-click-cycle.wh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// ==WindhawkMod==
// @id taskbar-left-click-cycle
// @name Cycle through taskbar windows on click
// @description Makes clicking on combined taskbar items cycle through windows instead of opening thumbnail previews
// @version 1.0
// @author m417z
// @github https://github.com/m417z
// @twitter https://twitter.com/m417z
// @homepage https://m417z.com/
// @include explorer.exe
// @architecture x86-64
// @compilerOptions -lversion
// ==/WindhawkMod==

// Source code is published under The GNU General Public License v3.0.
//
// For bug reports and feature requests, please open an issue here:
// https://github.com/ramensoftware/windhawk-mods/issues
//
// For pull requests, development takes place here:
// https://github.com/m417z/my-windhawk-mods

// ==WindhawkModReadme==
/*
# Cycle through taskbar windows on click
Makes clicking on combined taskbar items cycle through windows instead of
opening thumbnail previews. It's still possible to open thumbnail previews by
holding the Ctrl key while clicking.
Only Windows 10 64-bit and Windows 11 are supported. For other Windows versions
check out [7+ Taskbar Tweaker](https://tweaker.ramensoftware.com/).
**Note:** To customize the old taskbar on Windows 11 (if using ExplorerPatcher
or a similar tool), enable the relevant option in the mod's settings.
![Demonstration](https://i.imgur.com/ecYYtGU.gif)
*/
// ==/WindhawkModReadme==

// ==WindhawkModSettings==
/*
- oldTaskbarOnWin11: false
$name: Customize the old taskbar on Windows 11
$description: >-
Enable this option to customize the old taskbar on Windows 11 (if using
ExplorerPatcher or a similar tool).
*/
// ==/WindhawkModSettings==

#include <windhawk_utils.h>

struct {
bool oldTaskbarOnWin11;
} g_settings;

enum class WinVersion {
Unsupported,
Win10,
Win11,
};

WinVersion g_winVersion;

using CTaskBtnGroup_GetGroupType_t = int(WINAPI*)(PVOID pThis);
CTaskBtnGroup_GetGroupType_t CTaskBtnGroup_GetGroupType_Original;

using CTaskListWnd__HandleClick_t = void(WINAPI*)(PVOID pThis,
PVOID taskBtnGroup,
int taskItemIndex,
int clickAction,
int param4,
int param5);
CTaskListWnd__HandleClick_t CTaskListWnd__HandleClick_Original;
void WINAPI CTaskListWnd__HandleClick_Hook(PVOID pThis,
PVOID taskBtnGroup,
int taskItemIndex,
int clickAction,
int param4,
int param5) {
Wh_Log(L"> %d", clickAction);

auto original = [&]() {
CTaskListWnd__HandleClick_Original(pThis, taskBtnGroup, taskItemIndex,
clickAction, param4, param5);
};

constexpr int kClick = 0;
constexpr int kShiftClick = 4;

if (clickAction != kClick && clickAction != kShiftClick) {
return original();
}

// Group types:
// 1 - Single item or multiple uncombined items
// 2 - Pinned item
// 3 - Multiple combined items
int groupType = CTaskBtnGroup_GetGroupType_Original(taskBtnGroup);
if (groupType != 3) {
return original();
}

CTaskListWnd__HandleClick_Original(
pThis, taskBtnGroup, taskItemIndex,
clickAction == kClick ? kShiftClick : kClick, param4, param5);
}

VS_FIXEDFILEINFO* GetModuleVersionInfo(HMODULE hModule, UINT* puPtrLen) {
void* pFixedFileInfo = nullptr;
UINT uPtrLen = 0;

HRSRC hResource =
FindResource(hModule, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
if (hResource) {
HGLOBAL hGlobal = LoadResource(hModule, hResource);
if (hGlobal) {
void* pData = LockResource(hGlobal);
if (pData) {
if (!VerQueryValue(pData, L"\\", &pFixedFileInfo, &uPtrLen) ||
uPtrLen == 0) {
pFixedFileInfo = nullptr;
uPtrLen = 0;
}
}
}
}

if (puPtrLen) {
*puPtrLen = uPtrLen;
}

return (VS_FIXEDFILEINFO*)pFixedFileInfo;
}

WinVersion GetExplorerVersion() {
VS_FIXEDFILEINFO* fixedFileInfo = GetModuleVersionInfo(nullptr, nullptr);
if (!fixedFileInfo) {
return WinVersion::Unsupported;
}

WORD major = HIWORD(fixedFileInfo->dwFileVersionMS);
WORD minor = LOWORD(fixedFileInfo->dwFileVersionMS);
WORD build = HIWORD(fixedFileInfo->dwFileVersionLS);
WORD qfe = LOWORD(fixedFileInfo->dwFileVersionLS);

Wh_Log(L"Version: %u.%u.%u.%u", major, minor, build, qfe);

switch (major) {
case 10:
if (build < 22000) {
return WinVersion::Win10;
} else {
return WinVersion::Win11;
}
break;
}

return WinVersion::Unsupported;
}

void LoadSettings() {
g_settings.oldTaskbarOnWin11 = Wh_GetIntSetting(L"oldTaskbarOnWin11");
}

BOOL Wh_ModInit() {
Wh_Log(L">");

LoadSettings();

g_winVersion = GetExplorerVersion();
if (g_winVersion == WinVersion::Unsupported) {
Wh_Log(L"Unsupported Windows version");
return FALSE;
}

if (g_winVersion >= WinVersion::Win11 && g_settings.oldTaskbarOnWin11) {
g_winVersion = WinVersion::Win10;
}

// Taskbar.dll, explorer.exe
WindhawkUtils::SYMBOL_HOOK symbolHooks[] = {
{
{
LR"(public: virtual enum eTBGROUPTYPE __cdecl CTaskBtnGroup::GetGroupType(void))",
LR"(public: virtual enum eTBGROUPTYPE __cdecl CTaskBtnGroup::GetGroupType(void) __ptr64)",
},
(void**)&CTaskBtnGroup_GetGroupType_Original,
},
{
{
LR"(protected: void __cdecl CTaskListWnd::_HandleClick(struct ITaskBtnGroup *,int,enum CTaskListWnd::eCLICKACTION,int,int))",
LR"(protected: void __cdecl CTaskListWnd::_HandleClick(struct ITaskBtnGroup * __ptr64,int,enum CTaskListWnd::eCLICKACTION,int,int) __ptr64)",
},
(void**)&CTaskListWnd__HandleClick_Original,
(void*)CTaskListWnd__HandleClick_Hook,
},
};

HMODULE module;
if (g_winVersion <= WinVersion::Win10) {
module = GetModuleHandle(nullptr);
} else {
module = LoadLibrary(L"taskbar.dll");
if (!module) {
Wh_Log(L"Couldn't load taskbar.dll");
return FALSE;
}
}

if (!HookSymbols(module, symbolHooks, ARRAYSIZE(symbolHooks))) {
return FALSE;
}

return TRUE;
}

BOOL Wh_ModSettingsChanged(BOOL* bReload) {
Wh_Log(L">");

bool prevOldTaskbarOnWin11 = g_settings.oldTaskbarOnWin11;

LoadSettings();

*bReload = g_settings.oldTaskbarOnWin11 != prevOldTaskbarOnWin11;

return TRUE;
}

0 comments on commit 2588c1b

Please sign in to comment.