|
@@ -1,13 +1,31 @@
|
|
|
#include "win32_window.h"
|
|
|
|
|
|
+#include <dwmapi.h>
|
|
|
#include <flutter_windows.h>
|
|
|
|
|
|
#include "resource.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
+/// Window attribute that enables dark mode window decorations.
|
|
|
+///
|
|
|
+/// Redefined in case the developer's machine has a Windows SDK older than
|
|
|
+/// version 10.0.22000.0.
|
|
|
+/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
|
|
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
|
|
+#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
|
|
+#endif
|
|
|
+
|
|
|
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
|
|
|
|
|
|
+/// Registry key for app theme preference.
|
|
|
+///
|
|
|
+/// A value of 0 indicates apps should use dark mode. A non-zero or missing
|
|
|
+/// value indicates apps should use light mode.
|
|
|
+constexpr const wchar_t kGetPreferredBrightnessRegKey[] =
|
|
|
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
|
|
|
+constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme";
|
|
|
+
|
|
|
// The number of Win32Window objects that currently exist.
|
|
|
static int g_active_window_count = 0;
|
|
|
|
|
@@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) {
|
|
|
GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
|
|
|
if (enable_non_client_dpi_scaling != nullptr) {
|
|
|
enable_non_client_dpi_scaling(hwnd);
|
|
|
- FreeLibrary(user32_module);
|
|
|
}
|
|
|
+ FreeLibrary(user32_module);
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
@@ -42,7 +60,7 @@ class WindowClassRegistrar {
|
|
|
public:
|
|
|
~WindowClassRegistrar() = default;
|
|
|
|
|
|
- // Returns the singleton registar instance.
|
|
|
+ // Returns the singleton registrar instance.
|
|
|
static WindowClassRegistrar* GetInstance() {
|
|
|
if (!instance_) {
|
|
|
instance_ = new WindowClassRegistrar();
|
|
@@ -102,9 +120,9 @@ Win32Window::~Win32Window() {
|
|
|
Destroy();
|
|
|
}
|
|
|
|
|
|
-bool Win32Window::CreateAndShow(const std::wstring& title,
|
|
|
- const Point& origin,
|
|
|
- const Size& size) {
|
|
|
+bool Win32Window::Create(const std::wstring& title,
|
|
|
+ const Point& origin,
|
|
|
+ const Size& size) {
|
|
|
Destroy();
|
|
|
|
|
|
const wchar_t* window_class =
|
|
@@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title,
|
|
|
double scale_factor = dpi / 96.0;
|
|
|
|
|
|
HWND window = CreateWindow(
|
|
|
- window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
|
+ window_class, title.c_str(), WS_OVERLAPPEDWINDOW,
|
|
|
Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
|
|
|
Scale(size.width, scale_factor), Scale(size.height, scale_factor),
|
|
|
nullptr, nullptr, GetModuleHandle(nullptr), this);
|
|
@@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ UpdateTheme(window);
|
|
|
+
|
|
|
return OnCreate();
|
|
|
}
|
|
|
|
|
|
+bool Win32Window::Show() {
|
|
|
+ return ShowWindow(window_handle_, SW_SHOWNORMAL);
|
|
|
+}
|
|
|
+
|
|
|
// static
|
|
|
LRESULT CALLBACK Win32Window::WndProc(HWND const window,
|
|
|
UINT const message,
|
|
@@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd,
|
|
|
SetFocus(child_content_);
|
|
|
}
|
|
|
return 0;
|
|
|
+
|
|
|
+ case WM_DWMCOLORIZATIONCOLORCHANGED:
|
|
|
+ UpdateTheme(hwnd);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
return DefWindowProc(window_handle_, message, wparam, lparam);
|
|
@@ -243,3 +271,18 @@ bool Win32Window::OnCreate() {
|
|
|
void Win32Window::OnDestroy() {
|
|
|
// No-op; provided for subclasses.
|
|
|
}
|
|
|
+
|
|
|
+void Win32Window::UpdateTheme(HWND const window) {
|
|
|
+ DWORD light_mode;
|
|
|
+ DWORD light_mode_size = sizeof(light_mode);
|
|
|
+ LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey,
|
|
|
+ kGetPreferredBrightnessRegValue,
|
|
|
+ RRF_RT_REG_DWORD, nullptr, &light_mode,
|
|
|
+ &light_mode_size);
|
|
|
+
|
|
|
+ if (result == ERROR_SUCCESS) {
|
|
|
+ BOOL enable_dark_mode = light_mode == 0;
|
|
|
+ DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
|
|
+ &enable_dark_mode, sizeof(enable_dark_mode));
|
|
|
+ }
|
|
|
+}
|