Skip to content

Commit

Permalink
Taskbar Background Helper v1.0.2 (#1188)
Browse files Browse the repository at this point in the history
* Fixed the background not updating in some cases, e.g. when exiting Firefox.
* Added support for Win+Tab and other fullscreen windows.
  • Loading branch information
m417z authored Nov 1, 2024
1 parent f44455f commit 177e874
Showing 1 changed file with 120 additions and 65 deletions.
185 changes: 120 additions & 65 deletions mods/taskbar-background-helper.wh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @id taskbar-background-helper
// @name Taskbar Background Helper
// @description Sets the taskbar background for the transparent parts, always or only when there's a maximized window, designed to be used with Windows 11 Taskbar Styler
// @version 1.0.1
// @version 1.0.2
// @author m417z
// @github https://github.com/m417z
// @twitter https://twitter.com/m417z
Expand Down Expand Up @@ -86,6 +86,8 @@ a workaround.

#include <dwmapi.h>

#include <atomic>
#include <mutex>
#include <optional>
#include <unordered_set>

Expand All @@ -106,10 +108,19 @@ struct {
std::optional<TaskbarStyle> darkModeStyle;
} g_settings;

HANDLE g_winObjectLocationChangeThread;
std::mutex g_winEventHookThreadMutex;
std::atomic<HANDLE> g_winEventHookThread;
std::unordered_set<HMONITOR> g_pendingMonitors;
UINT_PTR g_pendingMonitorsTimer;

// Missing in older MinGW headers.
#ifndef EVENT_OBJECT_CLOAKED
#define EVENT_OBJECT_CLOAKED 0x8017
#endif
#ifndef EVENT_OBJECT_UNCLOAKED
#define EVENT_OBJECT_UNCLOAKED 0x8018
#endif

enum WINDOWCOMPOSITIONATTRIB {
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
Expand Down Expand Up @@ -303,7 +314,13 @@ HWND GetTaskbarForMonitor(HMONITOR monitor) {
bool DoesMonitorHaveMaximizedWindow(HMONITOR monitor) {
bool hasMaximized = false;

auto enumWindowsProc = [monitor, &hasMaximized](HWND hWnd) -> BOOL {
MONITORINFO monitorInfo{
.cbSize = sizeof(monitorInfo),
};
GetMonitorInfo(monitor, &monitorInfo);

auto enumWindowsProc = [monitor, &monitorInfo,
&hasMaximized](HWND hWnd) -> BOOL {
if (MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST) != monitor) {
return TRUE;
}
Expand All @@ -312,20 +329,27 @@ bool DoesMonitorHaveMaximizedWindow(HMONITOR monitor) {
return TRUE;
}

if (GetWindowLong(hWnd, GWL_EXSTYLE) &
(WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW)) {
if (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
return TRUE;
}

WINDOWPLACEMENT wp{
.length = sizeof(WINDOWPLACEMENT),
};
if (!GetWindowPlacement(hWnd, &wp) || wp.showCmd != SW_SHOWMAXIMIZED) {
return TRUE;
if (GetWindowPlacement(hWnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) {
hasMaximized = true;
return FALSE;
}

hasMaximized = true;
return FALSE;
RECT rc;
if (GetWindowRect(hWnd, &rc) &&
EqualRect(&rc, &monitorInfo.rcMonitor)) {
// Spans across the whole monitor, e.g. Win+Tab view.
hasMaximized = true;
return FALSE;
}

return TRUE;
};

EnumWindows(
Expand All @@ -338,13 +362,13 @@ bool DoesMonitorHaveMaximizedWindow(HMONITOR monitor) {
return hasMaximized;
}

void CALLBACK LocationChangeWinEventProc(HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hWnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime) {
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hWnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime) {
if (idObject != OBJID_WINDOW) {
return;
}
Expand Down Expand Up @@ -383,8 +407,71 @@ void CALLBACK LocationChangeWinEventProc(HWINEVENTHOOK hWinEventHook,
});
}

DWORD WINAPI WinEventHookThread(LPVOID lpThreadParameter) {
HWINEVENTHOOK winObjectEventHook1 =
SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE, nullptr,
WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
if (!winObjectEventHook1) {
Wh_Log(L"Error: SetWinEventHook");
}

HWINEVENTHOOK winObjectEventHook2 = SetWinEventHook(
EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, nullptr,
WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
if (!winObjectEventHook2) {
Wh_Log(L"Error: SetWinEventHook");
}

HWINEVENTHOOK winObjectEventHook3 =
SetWinEventHook(EVENT_OBJECT_CLOAKED, EVENT_OBJECT_UNCLOAKED, nullptr,
WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
if (!winObjectEventHook3) {
Wh_Log(L"Error: SetWinEventHook");
}

BOOL bRet;
MSG msg;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
msg.wParam = 0;
break;
}

if (msg.hwnd == NULL && msg.message == WM_APP) {
PostQuitMessage(0);
continue;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}

if (winObjectEventHook1) {
UnhookWinEvent(winObjectEventHook1);
}

if (winObjectEventHook2) {
UnhookWinEvent(winObjectEventHook2);
}

if (winObjectEventHook3) {
UnhookWinEvent(winObjectEventHook3);
}

return 0;
}

BOOL AdjustTaskbarStyle(HWND hWnd) {
if (g_settings.onlyWhenMaximized) {
if (!g_winEventHookThread) {
std::lock_guard<std::mutex> guard(g_winEventHookThreadMutex);

if (!g_winEventHookThread) {
g_winEventHookThread = CreateThread(
nullptr, 0, WinEventHookThread, nullptr, 0, nullptr);
}
}

HMONITOR monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
if (!DoesMonitorHaveMaximizedWindow(monitor)) {
return ResetTaskbarStyle(hWnd);
Expand Down Expand Up @@ -550,57 +637,22 @@ BOOL Wh_ModInit() {
}

void Wh_ModAfterInit() {
Wh_Log(L">");

WNDCLASS wndclass;
if (GetClassInfo(GetModuleHandle(NULL), L"Shell_TrayWnd", &wndclass)) {
AdjustAllTaskbarStyles();
}

if (g_settings.onlyWhenMaximized) {
g_winObjectLocationChangeThread = CreateThread(
nullptr, 0,
[](LPVOID lpParameter) WINAPI -> DWORD {
HWINEVENTHOOK winObjectLocationChangeEventHook =
SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE,
EVENT_OBJECT_LOCATIONCHANGE, nullptr,
LocationChangeWinEventProc, 0, 0,
WINEVENT_OUTOFCONTEXT);
if (!winObjectLocationChangeEventHook) {
Wh_Log(L"Error: SetWinEventHook");
return 0;
}

BOOL bRet;
MSG msg;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
msg.wParam = 0;
break;
}

if (msg.hwnd == NULL && msg.message == WM_APP) {
PostQuitMessage(0);
continue;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}

UnhookWinEvent(winObjectLocationChangeEventHook);
return 0;
},
nullptr, 0, nullptr);
}
}

void Wh_ModUninit() {
Wh_Log(L">");

if (g_winObjectLocationChangeThread) {
PostThreadMessage(GetThreadId(g_winObjectLocationChangeThread), WM_APP,
0, 0);
WaitForSingleObject(g_winObjectLocationChangeThread, INFINITE);
CloseHandle(g_winObjectLocationChangeThread);
if (g_winEventHookThread) {
PostThreadMessage(GetThreadId(g_winEventHookThread), WM_APP, 0, 0);
WaitForSingleObject(g_winEventHookThread, INFINITE);
CloseHandle(g_winEventHookThread);
g_winEventHookThread = nullptr;
}

std::unordered_set<HWND> secondaryTaskbarWindows;
Expand All @@ -614,18 +666,21 @@ void Wh_ModUninit() {
}
}

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

bool prevOnlyWhenMaximized = g_settings.onlyWhenMaximized;

LoadSettings();

*bReload = g_settings.onlyWhenMaximized != prevOnlyWhenMaximized;
if (!g_settings.onlyWhenMaximized) {
std::lock_guard<std::mutex> guard(g_winEventHookThreadMutex);

if (!*bReload) {
AdjustAllTaskbarStyles();
if (g_winEventHookThread) {
PostThreadMessage(GetThreadId(g_winEventHookThread), WM_APP, 0, 0);
WaitForSingleObject(g_winEventHookThread, INFINITE);
CloseHandle(g_winEventHookThread);
g_winEventHookThread = nullptr;
}
}

return TRUE;
AdjustAllTaskbarStyles();
}

0 comments on commit 177e874

Please sign in to comment.