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 "atom/common/node_includes.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
#include "ui/base/win/shell.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
|
||||||
SystemPreferences::SystemPreferences(v8::Isolate* isolate) {
|
SystemPreferences::SystemPreferences(v8::Isolate* isolate) {
|
||||||
Init(isolate);
|
Init(isolate);
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
InitializeWindow();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemPreferences::~SystemPreferences() {
|
SystemPreferences::~SystemPreferences() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
bool SystemPreferences::IsAeroGlassEnabled() {
|
|
||||||
return ui::win::IsAeroGlassEnabled();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(OS_MACOSX)
|
#if !defined(OS_MACOSX)
|
||||||
bool SystemPreferences::IsDarkMode() {
|
bool SystemPreferences::IsDarkMode() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -48,6 +41,7 @@ void SystemPreferences::BuildPrototype(
|
||||||
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
prototype->SetClassName(mate::StringToV8(isolate, "SystemPreferences"));
|
||||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
|
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
||||||
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
.SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
|
||||||
#elif defined(OS_MACOSX)
|
#elif defined(OS_MACOSX)
|
||||||
.SetMethod("postNotification",
|
.SetMethod("postNotification",
|
||||||
|
|
|
@ -29,6 +29,17 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
bool IsAeroGlassEnabled();
|
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)
|
#elif defined(OS_MACOSX)
|
||||||
using NotificationCallback = base::Callback<
|
using NotificationCallback = base::Callback<
|
||||||
void(const std::string&, const base::DictionaryValue&)>;
|
void(const std::string&, const base::DictionaryValue&)>;
|
||||||
|
@ -64,6 +75,25 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
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);
|
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())
|
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
|
## Methods
|
||||||
|
|
||||||
### `systemPreferences.isDarkMode()` _macOS_
|
### `systemPreferences.isDarkMode()` _macOS_
|
||||||
|
@ -124,3 +137,16 @@ if (browserOptions.transparent) {
|
||||||
```
|
```
|
||||||
|
|
||||||
[dwm-composition]:https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx
|
[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.cc',
|
||||||
'atom/browser/api/atom_api_system_preferences.h',
|
'atom/browser/api/atom_api_system_preferences.h',
|
||||||
'atom/browser/api/atom_api_system_preferences_mac.mm',
|
'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.cc',
|
||||||
'atom/browser/api/atom_api_tray.h',
|
'atom/browser/api/atom_api_tray.h',
|
||||||
'atom/browser/api/atom_api_web_contents.cc',
|
'atom/browser/api/atom_api_web_contents.cc',
|
||||||
|
|
|
@ -3,11 +3,23 @@ const {remote} = require('electron')
|
||||||
const {systemPreferences} = remote
|
const {systemPreferences} = remote
|
||||||
|
|
||||||
describe('systemPreferences module', function () {
|
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') {
|
if (process.platform !== 'darwin') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('systemPreferences.getUserDefault(key, type)', function () {
|
|
||||||
it('returns values for known user defaults', function () {
|
it('returns values for known user defaults', function () {
|
||||||
let locale = systemPreferences.getUserDefault('AppleLocale', 'string')
|
let locale = systemPreferences.getUserDefault('AppleLocale', 'string')
|
||||||
assert.notEqual(locale, null)
|
assert.notEqual(locale, null)
|
||||||
|
|
Loading…
Reference in a new issue