Skip to content
This repository has been archived by the owner on Jun 12, 2023. It is now read-only.

Support for DWM with more accurate colors #50

Merged
merged 5 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.5.1

- Add support for DWM/Windows Aero's color ([#50](https://github.com/material-foundation/material-dynamic-color-flutter/pull/50))

## 1.5.0

- Add support for GTK's accent color on Linux ([#47](https://github.com/material-foundation/material-dynamic-color-flutter/pull/47))
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A Flutter package to create Material color schemes based on a platform's impleme
- Android S+: [color from user wallpaper](https://m3.material.io/styles/color/dynamic-color/user-generated-color)
- Linux: GTK+ theme's `@theme_selected_bg_color`
- macOS: [app accent color](https://developer.apple.com/design/human-interface-guidelines/macos/overview/whats-new-in-macos/#app-accent-colors)
- Windows: [accent color](https://docs.microsoft.com/en-us/windows/apps/design/style/color#accent-color)
- Windows: [accent color](https://docs.microsoft.com/en-us/windows/apps/design/style/color#accent-color) or [window/glass color](https://web.archive.org/web/20080812195923/http://www.microsoft.com/windows/windows-vista/features/aero.aspx?tabid=2&catid=4)

This package also supports color and color scheme harmonization.

Expand Down
5 changes: 3 additions & 2 deletions lib/src/dynamic_color_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ class DynamicColorPlugin {

/// Returns the OS' accent color asynchronously as a [Color].
///
/// Supported on macOS starting with 10.14 (Mojave), on Windows with
/// Windows 10, and on GTK-based Linux desktops.
/// Supported on macOS starting with 10.14 (Mojave), on Windows starting with
/// Vista, and on GTK-based Linux desktops.
///
/// See also:
///
/// * [Apple's introduction to macOS accent color](https://developer.apple.com/design/human-interface-guidelines/macos/overview/whats-new-in-macos/#app-accent-colors)
/// * [macOS's NSColor.controlAccentColor documentation](https://developer.apple.com/documentation/appkit/nscolor/3000782-controlaccentcolor)
/// * [Windows' accent color](https://docs.microsoft.com/en-us/windows/apps/design/style/color#accent-color)
/// * [Windows Aero](https://web.archive.org/web/20080812195923/http://www.microsoft.com/windows/windows-vista/features/aero.aspx?tabid=2&catid=4)
/// * [Change colors in Windows](https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe)
static Future<Color?> getAccentColor() async {
final result = await channel.invokeMethod(accentColorMethodName);
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: dynamic_color
description: A Flutter package to create Material color schemes based on a platform's implementation of dynamic color.
version: 1.5.0
version: 1.5.1
repository: https://github.com/material-foundation/material-dynamic-color-flutter

environment:
Expand Down
2 changes: 1 addition & 1 deletion windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
# dependencies here.
target_include_directories(${PLUGIN_NAME} INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin dwmapi.lib)

# List of absolute paths to libraries that should be bundled with the plugin.
# This list could contain prebuilt libraries, or libraries created by an
Expand Down
14 changes: 14 additions & 0 deletions windows/dwm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <windows.h>

typedef struct COLORIZATIONPARAMS
{
COLORREF clrColor;
COLORREF clrAftGlow;
UINT nIntensity;
UINT clrAftGlowBal;
UINT clrBlurBal;
UINT clrGlassReflInt;
BOOL fOpaque;
} COLORIZATIONPARAMS;

HRESULT (WINAPI *DwmGetColorizationParameters) (COLORIZATIONPARAMS *colorparam);
107 changes: 90 additions & 17 deletions windows/dynamic_color_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

// This must be included before many other Windows headers.
#include <windows.h>
#include <dwmapi.h>
#include "dwm.c"

// For getPlatformVersion; remove unless needed for your plugin implementation.
#include <VersionHelpers.h>
Expand Down Expand Up @@ -37,27 +39,98 @@ DynamicColorPlugin::DynamicColorPlugin() {}

DynamicColorPlugin::~DynamicColorPlugin() {}

static BOOL GetAccentColorViaRegistry(int64_t& argbColor) {
DWORD abgr = 0;
DWORD resultSize = sizeof (abgr);

if (
RegGetValue(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Accent",
L"AccentColorMenu",
RRF_RT_REG_DWORD,
nullptr,
&abgr,
&resultSize
) == S_OK
) {
argbColor = (abgr & 0xFF00FF00) + ((abgr & 0xFF) << 16) + ((abgr & 0xFF0000) >> 16);
return TRUE;
}

return FALSE;
}

static BOOL GetWindowColorViaDwmUndocd(int64_t& argbColor) {
HMODULE hDwmDll = LoadLibrary(L"dwmapi.dll");
if (!hDwmDll) {
return FALSE;
}

*(FARPROC *)&DwmGetColorizationParameters = GetProcAddress(hDwmDll,(LPCSTR)127);

COLORIZATIONPARAMS colorParams;
if (SUCCEEDED(DwmGetColorizationParameters(&colorParams))) {
argbColor = colorParams.clrColor;
FreeLibrary(hDwmDll);
return TRUE;
}

FreeLibrary(hDwmDll);
return FALSE;
}

static BOOL GetWindowColorViaDwmRegistry(int64_t& argbColor) {
DWORD argb = 0;
DWORD resultSize = sizeof(argb);

if (SUCCEEDED(
RegGetValue(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\DWM",
L"ColorizationColor",
RRF_RT_REG_DWORD,
nullptr,
&argb,
&resultSize
)
)) {
argbColor = argb;
return TRUE;
}

return FALSE;
}

void DynamicColorPlugin::HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if (!method_call.method_name().compare("getAccentColor")) {
int64_t argbColor = 0;
DWORD abgr = 0;
DWORD resultSize = sizeof (abgr);
if (
RegGetValue(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Accent",
L"AccentColorMenu",
RRF_RT_REG_DWORD,
nullptr,
&abgr,
&resultSize
) == S_OK
) {
argbColor = (abgr & 0xFF00FF00) + ((abgr & 0xFF) << 16) + ((abgr & 0xFF0000) >> 16);
result->Success(flutter::EncodableValue(argbColor));
} else result->Success(nullptr);
int64_t argb = 0;
BOOL successful = FALSE;

// Try one method after the other until one works
if (IsWindows10OrGreater()) {
successful = GetAccentColorViaRegistry(argb);
}
if (!successful && IsWindowsVistaOrGreater()) {
BOOL dwmEnabled = FALSE;
if (SUCCEEDED(DwmIsCompositionEnabled(&dwmEnabled)) && dwmEnabled == TRUE) {
successful = GetWindowColorViaDwmUndocd(argb);

// Our attempt at using the undocumented DWM
// function failed, let's retry using the registry.
if (!successful) {
successful = GetWindowColorViaDwmRegistry(argb);
}
}
}

if (successful) {
result->Success(flutter::EncodableValue(argb));
} else {
result->Success(nullptr);
}
} else {
result->NotImplemented();
}
Expand Down