From 5083673dbec9bff295839d426816fc7aa3193d9e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 22 Nov 2024 18:06:44 +0000
Subject: [PATCH] deploy: 23d47eaa50c0dd34b1bd7b843c4652f684198f14
---
catalog.json | 22 ++
...segit-progress-animation-background-fix.md | 3 +
...t-progress-animation-background-fix.wh.cpp | 312 ++++++++++++++++++
updates.atom | 32 +-
4 files changed, 357 insertions(+), 12 deletions(-)
create mode 100644 changelogs/tortoisegit-progress-animation-background-fix.md
create mode 100644 mods/tortoisegit-progress-animation-background-fix.wh.cpp
diff --git a/catalog.json b/catalog.json
index 536de97b2..3acfa3f14 100644
--- a/catalog.json
+++ b/catalog.json
@@ -3225,6 +3225,28 @@
"version": "1.0"
}
},
+ "tortoisegit-progress-animation-background-fix": {
+ "details": {
+ "defaultSorting": 0,
+ "published": 1732298725000,
+ "rating": 0,
+ "ratingUsers": 0,
+ "updated": 1732298725000,
+ "users": 0
+ },
+ "metadata": {
+ "author": "Roland Pihlakas",
+ "compilerOptions": "-lgdi32",
+ "description": "Fixes progress animation background in classic dark theme by replacing white background with a classic button face colour",
+ "github": "https://github.com/levitation",
+ "homepage": "https://www.simplify.ee/",
+ "include": [
+ "TortoiseGitProc.exe"
+ ],
+ "name": "TortoiseGit progress animation background fix for classic dark theme",
+ "version": "1.0.0"
+ }
+ },
"transparent-screensaver-fix": {
"details": {
"defaultSorting": 2280,
diff --git a/changelogs/tortoisegit-progress-animation-background-fix.md b/changelogs/tortoisegit-progress-animation-background-fix.md
new file mode 100644
index 000000000..977847800
--- /dev/null
+++ b/changelogs/tortoisegit-progress-animation-background-fix.md
@@ -0,0 +1,3 @@
+## 1.0.0 ([Nov 22, 2024](https://github.com/ramensoftware/windhawk-mods/blob/23d47eaa50c0dd34b1bd7b843c4652f684198f14/mods/tortoisegit-progress-animation-background-fix.wh.cpp))
+
+Initial release.
diff --git a/mods/tortoisegit-progress-animation-background-fix.wh.cpp b/mods/tortoisegit-progress-animation-background-fix.wh.cpp
new file mode 100644
index 000000000..03e1787af
--- /dev/null
+++ b/mods/tortoisegit-progress-animation-background-fix.wh.cpp
@@ -0,0 +1,312 @@
+// ==WindhawkMod==
+// @id tortoisegit-progress-animation-background-fix
+// @name TortoiseGit progress animation background fix for classic dark theme
+// @description Fixes progress animation background in classic dark theme by replacing white background with a classic button face colour
+// @version 1.0.0
+// @author Roland Pihlakas
+// @github https://github.com/levitation
+// @homepage https://www.simplify.ee/
+// @compilerOptions -lgdi32
+// @include TortoiseGitProc.exe
+// ==/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/levitation-opensource/my-windhawk-mods/issues
+//
+// For pull requests, development takes place here:
+// https://github.com/levitation-opensource/my-windhawk-mods/
+
+// ==WindhawkModReadme==
+/*
+# TortoiseGit progress animation background fix for classic dark theme
+
+Under classic dark theme, TortoiseGit progress animation has a white background, thus looking as if something is broken.
+
+This mod fixes the progress animation background in classic dark theme by replacing the white background with a classic button face colour.
+
+Before:
+
+![Before](https://raw.githubusercontent.com/levitation-opensource/my-windhawk-mods/main/screenshots/before-tortoisegit-progress-animation-background.png)
+
+After:
+
+![After](https://raw.githubusercontent.com/levitation-opensource/my-windhawk-mods/main/screenshots/after-tortoisegit-progress-animation-background.png)
+
+
+## Known limitations
+
+There is still a brief flash of a white coloured box before the progress animation starts. I have tried various ways, but have been unable to get rid of that. If you have an idea how to fix that, please let me know!
+*/
+// ==/WindhawkModReadme==
+
+
+#include
+#include
+#include //std::nothrow
+
+
+template
+BOOL Wh_SetFunctionHookT(
+ FARPROC targetFunction,
+ T hookFunction,
+ T* originalFunction
+) {
+ return Wh_SetFunctionHook((void*)targetFunction, (void*)hookFunction, (void**)originalFunction);
+}
+
+
+const COLORREF white = RGB(255, 255, 255);
+
+
+std::atomic g_hookRefCount;
+
+
+using BitBlt_t = decltype(&BitBlt);
+BitBlt_t pOriginalBitBlt;
+
+
+bool ControlNeedsBackgroundRepaint(HWND hWnd) {
+
+ WCHAR szClassName[32];
+ if (
+ hWnd
+ && GetClassNameW(hWnd, szClassName, ARRAYSIZE(szClassName))
+ && _wcsicmp(szClassName, L"SysAnimate32") == 0
+ ) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void ConditionalFillRect(HDC hdc, const RECT& rect, COLORREF oldColor, COLORREF newColor, int newColorIndex, bool useFloodFill) {
+
+ int pixelCount = (rect.right - rect.left) * (rect.bottom - rect.top);
+ if (pixelCount == 0) {
+ //Wh_Log(L"pixelCount == 0");
+ return;
+ }
+
+ //Create a compatible DC and bitmap
+ HDC memDC = CreateCompatibleDC(hdc);
+ if (!memDC) {
+ Wh_Log(L"CreateCompatibleDC failed");
+ return;
+ }
+
+ HBITMAP memBitmap = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
+ if (!memBitmap) {
+ Wh_Log(L"CreateCompatibleBitmap failed");
+ }
+ else {
+ HGDIOBJ oldBitmap = SelectObject(memDC, memBitmap);
+ if (!oldBitmap) {
+ Wh_Log(L"SelectObject for memBitmap failed");
+ }
+ else {
+ //copy the existing content from hdc
+ if (!pOriginalBitBlt(memDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left, rect.top, SRCCOPY)) {
+ Wh_Log(L"BitBlt to memDC failed");
+ }
+ else {
+ if (useFloodFill) {
+
+ HBRUSH newBrush = GetSysColorBrush(newColorIndex);
+ if (!newBrush) {
+ Wh_Log(L"GetSysColorBrush failed - is the colour supported by current OS?");
+ }
+ else {
+ HGDIOBJ oldBrush = SelectObject(memDC, newBrush);
+ if (!oldBrush) {
+ Wh_Log(L"SelectObject for newBrush failed");
+ }
+ else {
+ if (!ExtFloodFill(
+ memDC,
+ //start from top left corner
+ 0, //left
+ 0, //top
+ oldColor,
+ FLOODFILLSURFACE
+ )) {
+ //Wh_Log(L"ExtFloodFill failed");
+ }
+ else {
+ //blit the modified content back to hdc
+ if (!pOriginalBitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, memDC, 0, 0, SRCCOPY))
+ Wh_Log(L"BitBlt to hdc failed");
+ }
+
+ SelectObject(memDC, oldBrush);
+ }
+ }
+ }
+ else { //use conditional colour replacement on all pixels
+
+ //get pixels array from bitmap
+ BITMAPINFO bmi = {};
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = rect.right - rect.left;
+ bmi.bmiHeader.biHeight = rect.bottom - rect.top;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32; //32-bit color depth
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ COLORREF* pixels = new (std::nothrow) COLORREF[pixelCount];
+ if (!pixels) {
+ Wh_Log(L"Allocating pixels array failed");
+ }
+ else {
+ int getDIBitsResult = GetDIBits(memDC, memBitmap, 0, rect.bottom - rect.top, pixels, &bmi, DIB_RGB_COLORS);
+ if (getDIBitsResult == NULL || getDIBitsResult == ERROR_INVALID_PARAMETER) {
+ Wh_Log(L"GetDIBits failed");
+ delete[] pixels;
+ }
+ else {
+ //modify the pixels
+ for (int i = 0; i < pixelCount; ++i) {
+ if (pixels[i] == oldColor)
+ pixels[i] = newColor;
+ }
+
+ //save pixels array back to bitmap
+ int setDIBitsResult = SetDIBits(memDC, memBitmap, 0, rect.bottom - rect.top, pixels, &bmi, DIB_RGB_COLORS);
+ delete[] pixels;
+
+ if (setDIBitsResult == NULL || setDIBitsResult == ERROR_INVALID_PARAMETER) {
+ Wh_Log(L"SetDIBits failed");
+ }
+ else {
+ //blit the modified content back to hdc
+ if (!pOriginalBitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, memDC, 0, 0, SRCCOPY))
+ Wh_Log(L"BitBlt to hdc failed");
+ }
+ }
+ }
+ }
+ }
+
+ //clean up
+ SelectObject(memDC, oldBitmap);
+ DeleteObject(memBitmap);
+ }
+
+ DeleteDC(memDC);
+ }
+}
+
+BOOL WINAPI BitBltHook(
+ IN HDC hdcDest,
+ IN int x,
+ IN int y,
+ IN int cx,
+ IN int cy,
+ IN HDC hdcSrc,
+ IN int xSrc,
+ IN int ySrc,
+ IN DWORD rop
+) {
+ g_hookRefCount++;
+
+ //Wh_Log(L"BitBltHook called");
+
+
+ if (
+ hdcSrc
+ && hdcDest
+ ) {
+ HWND hwndDest = WindowFromDC(hdcDest);
+
+ if (ControlNeedsBackgroundRepaint(hwndDest)) {
+
+ int colorIndex = COLOR_3DFACE;
+
+ if (!GetSysColorBrush(colorIndex)) { //Verify that the brush is supported by the current system. GetSysColor() does not have return value, so need to use GetSysColorBrush() for verification purposes.
+ Wh_Log(L"GetSysColorBrush failed - is the colour supported by current OS?");
+ }
+ else {
+ RECT rcPaint;
+ rcPaint.left = x;
+ rcPaint.top = y;
+ rcPaint.right = x + cx;
+ rcPaint.bottom = y + cy;
+
+ COLORREF buttonFace = GetSysColor(colorIndex);
+ if (buttonFace != white) {
+ ConditionalFillRect(hdcSrc, rcPaint, white, buttonFace, colorIndex, /*useFloodFill*/true);
+
+ //Wh_Log(L"ConditionalFillRect called");
+ }
+ }
+ }
+ }
+
+
+ BOOL result = pOriginalBitBlt(
+ hdcDest,
+ x,
+ y,
+ cx,
+ cy,
+ hdcSrc,
+ xSrc,
+ ySrc,
+ rop
+ );
+
+
+ g_hookRefCount--;
+
+ return result;
+}
+
+void Wh_ModAfterInit(void) {
+
+ Wh_Log(L"Initialising hooks done");
+}
+
+BOOL Wh_ModInit() {
+
+ Wh_Log(L"Init");
+
+
+ HMODULE hGdi32 = GetModuleHandleW(L"gdi32.dll");
+ if (!hGdi32) {
+ Wh_Log(L"Loading gdi32.dll failed");
+ return FALSE;
+ }
+
+ FARPROC pBitBlt = GetProcAddress(hGdi32, "BitBlt");
+ if (!pBitBlt) {
+ Wh_Log(L"Finding hookable functions from gdi32.dll failed");
+ return FALSE;
+ }
+
+
+ Wh_Log(L"Initialising hooks...");
+
+ Wh_SetFunctionHookT(pBitBlt, BitBltHook, &pOriginalBitBlt);
+
+ return TRUE;
+}
+
+void Wh_ModUninit() {
+
+ Wh_Log(L"Uniniting...");
+
+
+ //Wait for the hooked calls to exit. I have seen programs crashing during this mod's unload without this.
+ do { //first sleep, then check g_hookRefCount since some hooked function might have a) entered, but not increased g_hookRefCount yet, or b) has decremented g_hookRefCount but not returned to the caller yet
+ if (g_hookRefCount)
+ Wh_Log(L"g_hookRefCount: %lli", (long long)g_hookRefCount);
+
+ Sleep(1000); //NB! Sleep always at least once. See the comment at the "do" keyword.
+
+ } while (g_hookRefCount > 0);
+
+
+ Wh_Log(L"Uninit complete");
+}
diff --git a/updates.atom b/updates.atom
index d435462be..036ac23e6 100644
--- a/updates.atom
+++ b/updates.atom
@@ -2,12 +2,31 @@
https://windhawk.net/Windhawk Mod Updates
- 2024-11-22T00:42:56.000Z
+ 2024-11-22T18:05:25.000Zhttps://github.com/jpmonette/feedUpdates in the official collection of Windhawk modshttps://windhawk.net/favicon.icoRamen Software
+
+
+ https://windhawk.net/mods/tortoisegit-progress-animation-background-fix#23d47eaa50c0dd34b1bd7b843c4652f684198f14
+
+ 2024-11-22T18:05:25.000Z
+ TortoiseGit progress animation background fix for classic dark theme
+
Under classic dark theme, TortoiseGit progress animation has a white background, thus looking as if something is broken.
+
This mod fixes the progress animation background in classic dark theme by replacing the white background with a classic button face colour.
+
Before:
+
+
After:
+
+
Known limitations
+
There is still a brief flash of a white coloured box before the progress animation starts. I have tried various ways, but have been unable to get rid of that. If you have an idea how to fix that, please let me know!
]]>
+
+ Roland Pihlakas
+ https://github.com/levitation
+
+ https://windhawk.net/mods/visual-studio-anti-rich-header#5c2c1aee4460b052b77496e4cbb4f00bddba510b
@@ -274,15 +293,4 @@ center, etc. to another monitor.
https://github.com/m417z
-
-
- https://windhawk.net/mods/legacy-alt-tab#b3712cc03e6f39212f8e7e79b91acb36e87b2507
-
- 2024-11-09T00:55:38.000Z
- Add info on supported Windows versions.]]>
-
- Anixx
- https://github.com/Anixx
-
-
\ No newline at end of file