Mercurial > minori
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); }