Merge pull request #7173 from electron/windows-system-color
Add an app API method to fetch the system ColorizationColor
This commit is contained in:
commit
77fdc67235
6 changed files with 169 additions and 13 deletions
|
@ -9,27 +9,20 @@
|
|||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/base/win/shell.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
SystemPreferences::SystemPreferences(v8::Isolate* isolate) {
|
||||
Init(isolate);
|
||||
#if defined(OS_WIN)
|
||||
InitializeWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
SystemPreferences::~SystemPreferences() {
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
||||
return ui::win::IsAeroGlassEnabled();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
return false;
|
||||
|
@ -48,6 +41,7 @@ void SystemPreferences::BuildPrototype(
|
|||
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
||||
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
||||
#elif defined(OS_MACOSX)
|
||||
.SetMethod("postNotification",
|
||||
|
|
|
@ -29,6 +29,17 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
|||
|
||||
#if defined(OS_WIN)
|
||||
bool IsAeroGlassEnabled();
|
||||
|
||||
typedef HRESULT (STDAPICALLTYPE *DwmGetColorizationColor)(DWORD *, BOOL *);
|
||||
DwmGetColorizationColor dwmGetColorizationColor =
|
||||
(DwmGetColorizationColor) GetProcAddress(LoadLibraryW(L"dwmapi.dll"),
|
||||
"DwmGetColorizationColor");
|
||||
|
||||
std::string GetAccentColor();
|
||||
|
||||
void InitializeWindow();
|
||||
|
||||
|
||||
#elif defined(OS_MACOSX)
|
||||
using NotificationCallback = base::Callback<
|
||||
void(const std::string&, const base::DictionaryValue&)>;
|
||||
|
@ -64,6 +75,25 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
|||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_WIN)
|
||||
// Static callback invoked when a message comes in to our messaging window.
|
||||
static LRESULT CALLBACK
|
||||
WndProcStatic(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
LRESULT CALLBACK
|
||||
WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
|
||||
// The window class of |window_|.
|
||||
ATOM atom_;
|
||||
|
||||
// The handle of the module that contains the window procedure of |window_|.
|
||||
HMODULE instance_;
|
||||
|
||||
// The window used for processing events.
|
||||
HWND window_;
|
||||
|
||||
std::string current_color_;
|
||||
#endif
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
|
||||
};
|
||||
|
||||
|
|
93
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
93
atom/browser/api/atom_api_system_preferences_win.cc
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_system_preferences.h"
|
||||
|
||||
#include "base/win/wrapped_window_proc.h"
|
||||
#include "ui/base/win/shell.h"
|
||||
#include "ui/gfx/win/hwnd_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const wchar_t kSystemPreferencesWindowClass[] =
|
||||
L"Electron_SystemPreferencesHostWindow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace api {
|
||||
|
||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
||||
return ui::win::IsAeroGlassEnabled();
|
||||
}
|
||||
|
||||
std::string hexColorDWORDToRGBA(DWORD color) {
|
||||
std::ostringstream stream;
|
||||
stream << std::hex << color;
|
||||
std::string hexColor = stream.str();
|
||||
return hexColor.substr(2) + hexColor.substr(0, 2);
|
||||
}
|
||||
|
||||
std::string SystemPreferences::GetAccentColor() {
|
||||
DWORD color = 0;
|
||||
BOOL opaque = FALSE;
|
||||
|
||||
if (FAILED(dwmGetColorizationColor(&color, &opaque))) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return hexColorDWORDToRGBA(color);
|
||||
}
|
||||
|
||||
void SystemPreferences::InitializeWindow() {
|
||||
WNDCLASSEX window_class;
|
||||
base::win::InitializeWindowClass(
|
||||
kSystemPreferencesWindowClass,
|
||||
&base::win::WrappedWindowProc<SystemPreferences::WndProcStatic>,
|
||||
0, 0, 0, NULL, NULL, NULL, NULL, NULL,
|
||||
&window_class);
|
||||
instance_ = window_class.hInstance;
|
||||
atom_ = RegisterClassEx(&window_class);
|
||||
|
||||
// Create an offscreen window for receiving broadcast messages for the system
|
||||
// colorization color. Create a hidden WS_POPUP window instead of an
|
||||
// HWND_MESSAGE window, because only top-level windows such as popups can
|
||||
// receive broadcast messages like "WM_DWMCOLORIZATIONCOLORCHANGED".
|
||||
window_ = CreateWindow(MAKEINTATOM(atom_),
|
||||
0, WS_POPUP, 0, 0, 0, 0, 0, 0, instance_, 0);
|
||||
gfx::CheckWindowCreated(window_);
|
||||
gfx::SetWindowUserData(window_, this);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
SystemPreferences* msg_wnd = reinterpret_cast<SystemPreferences*>(
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (msg_wnd)
|
||||
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
|
||||
else
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK SystemPreferences::WndProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
if (message == WM_DWMCOLORIZATIONCOLORCHANGED) {
|
||||
DWORD new_color = (DWORD) wparam;
|
||||
std::string new_color_string = hexColorDWORDToRGBA(new_color);
|
||||
if (new_color_string != current_color_) {
|
||||
Emit("accent-color-changed", hexColorDWORDToRGBA(new_color));
|
||||
current_color_ = new_color_string;
|
||||
}
|
||||
}
|
||||
return ::DefWindowProc(hwnd, message, wparam, lparam);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
|
@ -7,6 +7,19 @@ const {systemPreferences} = require('electron')
|
|||
console.log(systemPreferences.isDarkMode())
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
The `systemPreferences` object emits the following events:
|
||||
|
||||
### Event: 'accent-color-changed' _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `newColor` String - The new RGBA color the user assigned to be there system
|
||||
accent color.
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
### `systemPreferences.isDarkMode()` _macOS_
|
||||
|
@ -124,3 +137,16 @@ if (browserOptions.transparent) {
|
|||
```
|
||||
|
||||
[dwm-composition]:https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx
|
||||
|
||||
### `SystemPreferences.getAccentColor()` _Windows_
|
||||
|
||||
Returns the users current system wide color preference in the form of an RGBA
|
||||
hexadecimal string.
|
||||
|
||||
```js
|
||||
const color = app.getSystemAccentColor() // `"aabbccdd"`
|
||||
const red = color.substr(0, 2) // "aa"
|
||||
const green = color.substr(2, 2) // "bb"
|
||||
const blue = color.substr(4, 2) // "cc"
|
||||
const alpha = color.substr(6, 2) // "dd"
|
||||
```
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
'atom/browser/api/atom_api_system_preferences.cc',
|
||||
'atom/browser/api/atom_api_system_preferences.h',
|
||||
'atom/browser/api/atom_api_system_preferences_mac.mm',
|
||||
'atom/browser/api/atom_api_system_preferences_win.cc',
|
||||
'atom/browser/api/atom_api_tray.cc',
|
||||
'atom/browser/api/atom_api_tray.h',
|
||||
'atom/browser/api/atom_api_web_contents.cc',
|
||||
|
|
|
@ -3,11 +3,23 @@ const {remote} = require('electron')
|
|||
const {systemPreferences} = remote
|
||||
|
||||
describe('systemPreferences module', function () {
|
||||
describe('systemPreferences.getAccentColor', function () {
|
||||
if (process.platform !== 'win32') {
|
||||
return
|
||||
}
|
||||
|
||||
it('should return a non-empty string', function () {
|
||||
let accentColor = systemPreferences.getAccentColor()
|
||||
assert.notEqual(accentColor, null)
|
||||
assert(accentColor.length > 0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('systemPreferences.getUserDefault(key, type)', function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
return
|
||||
}
|
||||
|
||||
describe('systemPreferences.getUserDefault(key, type)', function () {
|
||||
it('returns values for known user defaults', function () {
|
||||
let locale = systemPreferences.getUserDefault('AppleLocale', 'string')
|
||||
assert.notEqual(locale, null)
|
||||
|
|
Loading…
Reference in a new issue