Add a systemPreferences API method to fetch the system ColorizationColor
authorSamuel Attard <samuel.r.attard@gmail.com>
Fri, 16 Sep 2016 16:00:22 +0000 (02:00 +1000)
committerSamuel Attard <samuel.r.attard@gmail.com>
Mon, 19 Sep 2016 16:41:26 +0000 (02:41 +1000)
This is useful for automatical app theming

* Fetches the color from the registry
* Returns an empty string if the fetch fails (a falsey value)

atom/browser/api/atom_api_system_preferences.cc
atom/browser/api/atom_api_system_preferences.h
atom/browser/api/atom_api_system_preferences_win.cc [new file with mode: 0644]
filenames.gypi

index ba6c972..f0b966e 100644 (file)
@@ -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;
@@ -49,6 +42,7 @@ void SystemPreferences::BuildPrototype(
   mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
 #if defined(OS_WIN)
       .SetMethod("isAeroGlassEnabled", &SystemPreferences::IsAeroGlassEnabled)
+      .SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
 #elif defined(OS_MACOSX)
       .SetMethod("postNotification",
                  &SystemPreferences::PostNotification)
index f855ab0..e257dc5 100644 (file)
@@ -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);
 };
 
diff --git a/atom/browser/api/atom_api_system_preferences_win.cc b/atom/browser/api/atom_api_system_preferences_win.cc
new file mode 100644 (file)
index 0000000..0c8e96a
--- /dev/null
@@ -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 kSystemPreferencestWindowClass[] =
+  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(
+      kSystemPreferencestWindowClass,
+      &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
index 1f4c9e4..88a8dc0 100644 (file)
       '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',