comparison src/sys/win32/dark_theme.cc @ 202:71832ffe425a

animia: re-add kvm fd source this is all being merged from my wildly out-of-date laptop. SORRY! in other news, I edited the CI file to install the wayland client as well, so the linux CI build might finally get wayland stuff.
author Paper <paper@paper.us.eu.org>
date Tue, 02 Jan 2024 06:05:06 -0500
parents f0ff06a45c42
children 862d0d8619f6
comparison
equal deleted inserted replaced
201:8f6f8dd2eb23 202:71832ffe425a
1 #include "sys/win32/dark_theme.h" 1 #include "sys/win32/dark_theme.h"
2
2 #include <QApplication> 3 #include <QApplication>
3 #include <QDebug>
4 #include <QOperatingSystemVersion> 4 #include <QOperatingSystemVersion>
5 #include <QSettings> 5 #include <QSettings>
6 #include <QWidget> 6 #include <QWidget>
7
7 #include <iostream> 8 #include <iostream>
9 #include <memory>
10
8 #include <dwmapi.h> 11 #include <dwmapi.h>
9 12
10 /* let's make a class wrapper around HINSTANCE, 13 struct LibraryDeconstructor {
11 so we don't fuck anything up :). */ 14 using pointer = HINSTANCE;
12 class Library { 15 void operator()(pointer t) const { ::FreeLibrary(t); };
13 public:
14 Library() {}
15 ~Library() {
16 Unload();
17 }
18 void Unload() {
19 if (hInstance) {
20 FreeLibrary(hInstance);
21 hInstance = nullptr;
22 }
23 loaded = false;
24 }
25 void Load(LPCWSTR name) {
26 if (loaded)
27 Unload();
28 hInstance = LoadLibraryW(name);
29 if (hInstance)
30 loaded = true;
31 }
32 HINSTANCE GetInstance() {
33 return hInstance;
34 }
35 bool IsLoaded() {
36 return loaded;
37 }
38 private:
39 HINSTANCE hInstance = nullptr;
40 bool loaded = false;
41 }; 16 };
42 17
43 Library dwmapi; 18 using Library = std::unique_ptr<HINSTANCE, LibraryDeconstructor>;
19
20 class Dwmapi {
21 public:
22 Dwmapi() { library.reset( ::LoadLibraryW(L"dwmapi.dll")); }
23
24 HRESULT SetWindowAttribute(HWND hWnd, DWORD key, LPCVOID data, DWORD sz_data) {
25 if (!library.get())
26 return E_POINTER;
27
28 // GCC throws a fit here because C/C++ lacks a "generic" function pointer type.
29 // Ignore.
30 auto set_wind_attrib = reinterpret_cast<decltype(::DwmSetWindowAttribute)*>(GetProcAddress(library.get(), "DwmSetWindowAttribute"));
31 if (!set_wind_attrib)
32 return E_POINTER;
33
34 return set_wind_attrib(hWnd, key, data, sz_data);
35 }
36
37 protected:
38 Library library = nullptr;
39 };
40
41 Dwmapi dwmapi;
44 42
45 namespace win32 { 43 namespace win32 {
46 44
47 #define GET_FUNCTION(f, i) \ 45 bool SetTitleBarToBlack(QWidget* win, bool enabled) {
48 reinterpret_cast<decltype(::f)*>(GetProcAddress(i, #f)) 46 /* 19 and 20 are *both* DWMWA_USE_IMMERSIVE_DARK_MODE.
47 *
48 * It's 20 on newer versions of windows (i.e. win11 and late win10),
49 * but it's 19 on very old versions of win10 nobody ought to be using anymore.
50 */
51 static constexpr DWORD DWMWA_USE_IMMERSIVE_DARK_MODE_OLD = 19;
52 static constexpr DWORD DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
49 53
50 static HRESULT SetWindowAttribute(HWND hWnd, DWORD key, LPCVOID data, DWORD sz_data) {
51 if (!dwmapi.IsLoaded()) {
52 dwmapi.Load(L"dwmapi.dll");
53 if (!dwmapi.IsLoaded())
54 return false;
55 }
56
57 HINSTANCE hInstance = dwmapi.GetInstance();
58 if (!hInstance)
59 return false;
60
61 auto set_wind_attrib = GET_FUNCTION(DwmSetWindowAttribute, hInstance);
62 if (!set_wind_attrib)
63 return false;
64
65 return set_wind_attrib(hWnd, key, data, sz_data);
66 }
67
68 bool SetTitleBarToBlack(QWidget* win, bool enabled) {
69 BOOL b = enabled; 54 BOOL b = enabled;
70 55
71 /* MAGIC NUMBERS: 19 and 20 are both DWMWA_USE_IMMERSIVE_DARK_MODE.
72 clarification: it's 20 on newer versions of windows (i.e. win11 and late win10),
73 but it's 19 on very old versions of win10 nobody ought to be using. */
74 { 56 {
75 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 20, &b, sizeof(b)); 57 HRESULT result = dwmapi.SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), DWMWA_USE_IMMERSIVE_DARK_MODE, &b, sizeof(b));
76 if (result == S_OK) 58 if (result == S_OK)
77 return b; 59 return b;
78 } 60 }
79 61
80 { 62 {
81 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 19, &b, sizeof(b)); 63 HRESULT result = dwmapi.SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), DWMWA_USE_IMMERSIVE_DARK_MODE_OLD, &b, sizeof(b));
82 if (result == S_OK) 64 if (result == S_OK)
83 return b; 65 return b;
84 } 66 }
85 67
86 return b; 68 return b;