Mercurial > minori
comparison 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 |
comparison
equal
deleted
inserted
replaced
104:27455104ea37 | 105:6d8da6e64d61 |
---|---|
1 #include "sys/win32/dark_theme.h" | 1 #include "sys/win32/dark_theme.h" |
2 #include <QApplication> | |
3 #include <QDebug> | |
2 #include <QOperatingSystemVersion> | 4 #include <QOperatingSystemVersion> |
3 #include <QSettings> | 5 #include <QSettings> |
6 #include <QWidget> | |
7 #include <iostream> | |
8 #include <dwmapi.h> | |
9 | |
10 /* let's make a class wrapper around HINSTANCE, | |
11 so we don't fuck anything up :). */ | |
12 class Library { | |
13 public: | |
14 Library() {} | |
15 ~Library() { | |
16 Unload(); | |
17 } | |
18 void Unload() { | |
19 if (hInstance) | |
20 FreeLibrary(hInstance); | |
21 loaded = false; | |
22 } | |
23 void Load(LPCWSTR name) { | |
24 if (loaded) | |
25 Unload(); | |
26 hInstance = LoadLibraryW(name); | |
27 if (hInstance) | |
28 loaded = true; | |
29 } | |
30 HINSTANCE GetInstance() { | |
31 return hInstance; | |
32 } | |
33 bool IsLoaded() { | |
34 return loaded; | |
35 } | |
36 private: | |
37 HINSTANCE hInstance = nullptr; | |
38 bool loaded = false; | |
39 }; | |
40 | |
41 Library dwmapi; | |
4 | 42 |
5 namespace win32 { | 43 namespace win32 { |
6 | 44 |
45 #define GET_FUNCTION(f, i) \ | |
46 reinterpret_cast<decltype(::f)*>(GetProcAddress(i, #f)) | |
47 | |
48 static HRESULT SetWindowAttribute(HWND hWnd, DWORD key, LPCVOID data, DWORD sz_data) { | |
49 if (!dwmapi.IsLoaded()) { | |
50 dwmapi.Load(L"dwmapi.dll"); | |
51 if (!dwmapi.IsLoaded()) | |
52 return false; | |
53 } | |
54 | |
55 HINSTANCE hInstance = dwmapi.GetInstance(); | |
56 if (!hInstance) | |
57 return false; | |
58 | |
59 auto set_wind_attrib = GET_FUNCTION(DwmSetWindowAttribute, hInstance); | |
60 if (!set_wind_attrib) | |
61 return false; | |
62 | |
63 return set_wind_attrib(hWnd, key, data, sz_data); | |
64 } | |
65 | |
66 /* Ok, so this doesn't work. Woohoo! :) */ | |
67 bool SetTitleBarToBlack(QWidget* win, bool enabled) { | |
68 BOOL b = enabled; | |
69 | |
70 /* MAGIC NUMBERS: 19 and 20 are both DWMWA_USE_IMMERSIVE_DARK_MODE. | |
71 clarification: it's 20 on newer versions of windows (i.e. win11 and late win10), | |
72 but it's 19 on very old versions of win10 nobody ought to be using. */ | |
73 { | |
74 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 20, &b, sizeof(b)); | |
75 if (result == S_OK) | |
76 return b; | |
77 } | |
78 | |
79 { | |
80 /* It's 19 in older Windows 10 versions. Yeah, stupid. */ | |
81 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 19, &b, sizeof(b)); | |
82 if (result == S_OK) | |
83 return b; | |
84 } | |
85 | |
86 return b; | |
87 } | |
88 | |
89 void SetTitleBarsToBlack(bool enabled) { | |
90 for (QWidget* widget : qApp->topLevelWidgets()) { | |
91 SetTitleBarToBlack(widget, enabled); | |
92 } | |
93 } | |
94 | |
7 bool DarkThemeAvailable() { | 95 bool DarkThemeAvailable() { |
8 // dark mode supported Windows 10 1809 10.0.17763 onward | |
9 // https://stackoverflow.com/questions/53501268/win10-dark-theme-how-to-use-in-winapi | |
10 const auto& ver = QOperatingSystemVersion::current(); | 96 const auto& ver = QOperatingSystemVersion::current(); |
11 return (ver.majorVersion() > 10) ? true : (ver.majorVersion() == 10 && ver.microVersion() >= 17763); | 97 return (ver.majorVersion() > 10) ? true : (ver.majorVersion() == 10 && ver.microVersion() >= 17763); |
12 } | 98 } |
13 | 99 |
14 bool IsInDarkTheme() { | 100 bool IsInDarkTheme() { |