comparison src/sys/win32/dark_theme.cc @ 178:bc8d2ccff09c

win32/dark: use existing STL classes for dwmapi
author Paper <mrpapersonic@gmail.com>
date Mon, 04 Dec 2023 11:51:30 -0500
parents c8c72278f6fd
children f0ff06a45c42
comparison
equal deleted inserted replaced
177:122fad646f81 178:bc8d2ccff09c
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 /* NOTE: explicit conversion from builtin `bool` and win32 `BOOL` IS allowed. */
48 reinterpret_cast<decltype(::f)*>(GetProcAddress(i, #f))
49
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) { 46 bool SetTitleBarToBlack(QWidget* win, bool enabled) {
69 BOOL b = enabled; 47 BOOL b = enabled;
70 48
71 /* MAGIC NUMBERS: 19 and 20 are both DWMWA_USE_IMMERSIVE_DARK_MODE. 49 /* 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), 50 For 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. */ 51 but it's 19 on very old versions of win10 nobody ought to be using anymore. */
74 { 52 {
75 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 20, &b, sizeof(b)); 53 HRESULT result = dwmapi.SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 20, &b, sizeof(b));
76 if (result == S_OK) 54 if (result == S_OK)
77 return b; 55 return b;
78 } 56 }
79 57
80 { 58 {
81 HRESULT result = SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 19, &b, sizeof(b)); 59 HRESULT result = dwmapi.SetWindowAttribute(reinterpret_cast<HWND>(win->winId()), 19, &b, sizeof(b));
82 if (result == S_OK) 60 if (result == S_OK)
83 return b; 61 return b;
84 } 62 }
85 63
86 return b; 64 return b;