diff src/sys/win32/dark_theme.cc @ 105:6d8da6e64d61

theme: add dark stylesheet, make it actually usable win32: make the titlebar black where available
author Paper <mrpapersonic@gmail.com>
date Sun, 05 Nov 2023 03:54:26 -0500
parents 9b2b41f83a5e
children c8c72278f6fd
line wrap: on
line diff
--- a/src/sys/win32/dark_theme.cc	Sun Nov 05 02:35:27 2023 -0500
+++ b/src/sys/win32/dark_theme.cc	Sun Nov 05 03:54:26 2023 -0500
@@ -1,12 +1,98 @@
 #include "sys/win32/dark_theme.h"
+#include <QApplication>
+#include <QDebug>
 #include <QOperatingSystemVersion>
 #include <QSettings>
+#include <QWidget>
+#include <iostream>
+#include <dwmapi.h>
+
+/* let's make a class wrapper around HINSTANCE, 
+   so we don't fuck anything up :). */
+class Library {
+	public:
+		Library() {}
+		~Library() {
+			Unload();
+		}
+		void Unload() {
+			if (hInstance)
+				FreeLibrary(hInstance);
+			loaded = false;
+		}
+		void Load(LPCWSTR name) {
+			if (loaded)
+				Unload();
+			hInstance = LoadLibraryW(name);
+			if (hInstance)
+				loaded = true;
+		}
+		HINSTANCE GetInstance() {
+			return hInstance;
+		}
+		bool IsLoaded() {
+			return loaded;
+		}
+	private:
+		HINSTANCE hInstance = nullptr;
+		bool loaded = false;
+};
+
+Library dwmapi;
 
 namespace win32 {
 
+#define GET_FUNCTION(f, i) \
+	reinterpret_cast<decltype(::f)*>(GetProcAddress(i, #f))
+
+static HRESULT SetWindowAttribute(HWND hWnd, DWORD key, LPCVOID data, DWORD sz_data) {
+	if (!dwmapi.IsLoaded()) {
+		dwmapi.Load(L"dwmapi.dll");
+		if (!dwmapi.IsLoaded())
+			return false;
+	}
+
+	HINSTANCE hInstance = dwmapi.GetInstance();
+	if (!hInstance)
+		return false;
+
+	auto set_wind_attrib = GET_FUNCTION(DwmSetWindowAttribute, hInstance);
+	if (!set_wind_attrib)
+		return false;
+
+	return set_wind_attrib(hWnd, key, data, sz_data);
+}
+
+/* Ok, so this doesn't work. Woohoo! :) */
+bool SetTitleBarToBlack(QWidget* win, bool enabled) {
+	BOOL b = enabled;
+
+	/* MAGIC NUMBERS: 19 and 20 are both DWMWA_USE_IMMERSIVE_DARK_MODE.
+	   clarification: it's 20 on newer versions of windows (i.e. win11 and late win10),
+	   but it's 19 on very old versions of win10 nobody ought to be using. */
+	{
+		HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 20, &b, sizeof(b));
+		if (result == S_OK)
+			return b;
+	}
+
+	{
+		/* It's 19 in older Windows 10 versions. Yeah, stupid. */
+		HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 19, &b, sizeof(b));
+		if (result == S_OK)
+			return b;
+	}
+
+	return b;
+}
+
+void SetTitleBarsToBlack(bool enabled) {
+	for (QWidget* widget : qApp->topLevelWidgets()) {
+		SetTitleBarToBlack(widget, enabled);
+	}
+}
+
 bool DarkThemeAvailable() {
-	// dark mode supported Windows 10 1809 10.0.17763 onward
-	// https://stackoverflow.com/questions/53501268/win10-dark-theme-how-to-use-in-winapi
 	const auto& ver = QOperatingSystemVersion::current();
 	return (ver.majorVersion() > 10) ? true : (ver.majorVersion() == 10 && ver.microVersion() >= 17763);
 }