| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | // Copyright (c) 2014 GitHub, Inc.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-06 23:39:56 +02:00
										 |  |  | #include <dwmapi.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  | #include <windows.devices.enumeration.h>
 | 
					
						
							|  |  |  | #include <wrl/client.h>
 | 
					
						
							| 
									
										
										
										
											2018-01-09 11:07:29 -08:00
										 |  |  | #include <iomanip>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/browser/api/electron_api_system_preferences.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  | #include "base/win/core_winrt_util.h"
 | 
					
						
							| 
									
										
										
										
											2020-07-13 18:13:34 -07:00
										 |  |  | #include "base/win/windows_types.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | #include "base/win/wrapped_window_proc.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:46:59 -07:00
										 |  |  | #include "shell/common/color_util.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | #include "ui/base/win/shell.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-10 14:31:06 -07:00
										 |  |  | #include "ui/gfx/color_utils.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | #include "ui/gfx/win/hwnd_util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace electron { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 02:42:41 +10:00
										 |  |  | const wchar_t kSystemPreferencesWindowClass[] = | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |     L"Electron_SystemPreferencesHostWindow"; | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  | using ABI::Windows::Devices::Enumeration::DeviceAccessStatus; | 
					
						
							|  |  |  | using ABI::Windows::Devices::Enumeration::DeviceClass; | 
					
						
							|  |  |  | using ABI::Windows::Devices::Enumeration::IDeviceAccessInformation; | 
					
						
							|  |  |  | using ABI::Windows::Devices::Enumeration::IDeviceAccessInformationStatics; | 
					
						
							|  |  |  | using Microsoft::WRL::ComPtr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DeviceAccessStatus GetDeviceAccessStatus(DeviceClass device_class) { | 
					
						
							|  |  |  |   ComPtr<IDeviceAccessInformationStatics> dev_access_info_statics; | 
					
						
							|  |  |  |   HRESULT hr = base::win::GetActivationFactory< | 
					
						
							|  |  |  |       IDeviceAccessInformationStatics, | 
					
						
							|  |  |  |       RuntimeClass_Windows_Devices_Enumeration_DeviceAccessInformation>( | 
					
						
							|  |  |  |       &dev_access_info_statics); | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							|  |  |  |     VLOG(1) << "IDeviceAccessInformationStatics failed: " << hr; | 
					
						
							|  |  |  |     return DeviceAccessStatus::DeviceAccessStatus_Allowed; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ComPtr<IDeviceAccessInformation> dev_access_info; | 
					
						
							|  |  |  |   hr = dev_access_info_statics->CreateFromDeviceClass(device_class, | 
					
						
							|  |  |  |                                                       &dev_access_info); | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							|  |  |  |     VLOG(1) << "IDeviceAccessInformation failed: " << hr; | 
					
						
							|  |  |  |     return DeviceAccessStatus::DeviceAccessStatus_Allowed; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto status = DeviceAccessStatus::DeviceAccessStatus_Unspecified; | 
					
						
							|  |  |  |   dev_access_info->get_CurrentStatus(&status); | 
					
						
							|  |  |  |   return status; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string ConvertDeviceAccessStatus(DeviceAccessStatus value) { | 
					
						
							|  |  |  |   switch (value) { | 
					
						
							|  |  |  |     case DeviceAccessStatus::DeviceAccessStatus_Unspecified: | 
					
						
							|  |  |  |       return "not-determined"; | 
					
						
							|  |  |  |     case DeviceAccessStatus::DeviceAccessStatus_Allowed: | 
					
						
							|  |  |  |       return "granted"; | 
					
						
							|  |  |  |     case DeviceAccessStatus::DeviceAccessStatus_DeniedBySystem: | 
					
						
							|  |  |  |       return "restricted"; | 
					
						
							|  |  |  |     case DeviceAccessStatus::DeviceAccessStatus_DeniedByUser: | 
					
						
							|  |  |  |       return "denied"; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return "unknown"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | }  // namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace api { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool SystemPreferences::IsAeroGlassEnabled() { | 
					
						
							|  |  |  |   return ui::win::IsAeroGlassEnabled(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string hexColorDWORDToRGBA(DWORD color) { | 
					
						
							| 
									
										
										
										
											2018-01-09 11:07:29 -08:00
										 |  |  |   DWORD rgba = color << 8 | color >> 24; | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |   std::ostringstream stream; | 
					
						
							| 
									
										
										
										
											2018-01-09 11:07:29 -08:00
										 |  |  |   stream << std::hex << std::setw(8) << std::setfill('0') << rgba; | 
					
						
							|  |  |  |   return stream.str(); | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string SystemPreferences::GetAccentColor() { | 
					
						
							|  |  |  |   DWORD color = 0; | 
					
						
							|  |  |  |   BOOL opaque = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-06 23:39:56 +02:00
										 |  |  |   if (FAILED(DwmGetColorizationColor(&color, &opaque))) { | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |     return ""; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return hexColorDWORDToRGBA(color); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-21 14:31:03 -07:00
										 |  |  | std::string SystemPreferences::GetColor(gin_helper::ErrorThrower thrower, | 
					
						
							|  |  |  |                                         const std::string& color) { | 
					
						
							| 
									
										
										
										
											2016-10-10 14:31:06 -07:00
										 |  |  |   int id; | 
					
						
							|  |  |  |   if (color == "3d-dark-shadow") { | 
					
						
							|  |  |  |     id = COLOR_3DDKSHADOW; | 
					
						
							|  |  |  |   } else if (color == "3d-face") { | 
					
						
							|  |  |  |     id = COLOR_3DFACE; | 
					
						
							|  |  |  |   } else if (color == "3d-highlight") { | 
					
						
							|  |  |  |     id = COLOR_3DHIGHLIGHT; | 
					
						
							|  |  |  |   } else if (color == "3d-light") { | 
					
						
							|  |  |  |     id = COLOR_3DLIGHT; | 
					
						
							|  |  |  |   } else if (color == "3d-shadow") { | 
					
						
							|  |  |  |     id = COLOR_3DSHADOW; | 
					
						
							|  |  |  |   } else if (color == "active-border") { | 
					
						
							|  |  |  |     id = COLOR_ACTIVEBORDER; | 
					
						
							|  |  |  |   } else if (color == "active-caption") { | 
					
						
							|  |  |  |     id = COLOR_ACTIVECAPTION; | 
					
						
							|  |  |  |   } else if (color == "active-caption-gradient") { | 
					
						
							|  |  |  |     id = COLOR_GRADIENTACTIVECAPTION; | 
					
						
							|  |  |  |   } else if (color == "app-workspace") { | 
					
						
							|  |  |  |     id = COLOR_APPWORKSPACE; | 
					
						
							|  |  |  |   } else if (color == "button-text") { | 
					
						
							|  |  |  |     id = COLOR_BTNTEXT; | 
					
						
							|  |  |  |   } else if (color == "caption-text") { | 
					
						
							|  |  |  |     id = COLOR_CAPTIONTEXT; | 
					
						
							|  |  |  |   } else if (color == "desktop") { | 
					
						
							|  |  |  |     id = COLOR_DESKTOP; | 
					
						
							|  |  |  |   } else if (color == "disabled-text") { | 
					
						
							|  |  |  |     id = COLOR_GRAYTEXT; | 
					
						
							|  |  |  |   } else if (color == "highlight") { | 
					
						
							|  |  |  |     id = COLOR_HIGHLIGHT; | 
					
						
							|  |  |  |   } else if (color == "highlight-text") { | 
					
						
							|  |  |  |     id = COLOR_HIGHLIGHTTEXT; | 
					
						
							|  |  |  |   } else if (color == "hotlight") { | 
					
						
							|  |  |  |     id = COLOR_HOTLIGHT; | 
					
						
							|  |  |  |   } else if (color == "inactive-border") { | 
					
						
							|  |  |  |     id = COLOR_INACTIVEBORDER; | 
					
						
							|  |  |  |   } else if (color == "inactive-caption") { | 
					
						
							|  |  |  |     id = COLOR_INACTIVECAPTION; | 
					
						
							|  |  |  |   } else if (color == "inactive-caption-gradient") { | 
					
						
							|  |  |  |     id = COLOR_GRADIENTINACTIVECAPTION; | 
					
						
							|  |  |  |   } else if (color == "inactive-caption-text") { | 
					
						
							|  |  |  |     id = COLOR_INACTIVECAPTIONTEXT; | 
					
						
							|  |  |  |   } else if (color == "info-background") { | 
					
						
							|  |  |  |     id = COLOR_INFOBK; | 
					
						
							|  |  |  |   } else if (color == "info-text") { | 
					
						
							|  |  |  |     id = COLOR_INFOTEXT; | 
					
						
							|  |  |  |   } else if (color == "menu") { | 
					
						
							|  |  |  |     id = COLOR_MENU; | 
					
						
							|  |  |  |   } else if (color == "menu-highlight") { | 
					
						
							|  |  |  |     id = COLOR_MENUHILIGHT; | 
					
						
							|  |  |  |   } else if (color == "menubar") { | 
					
						
							|  |  |  |     id = COLOR_MENUBAR; | 
					
						
							|  |  |  |   } else if (color == "menu-text") { | 
					
						
							|  |  |  |     id = COLOR_MENUTEXT; | 
					
						
							|  |  |  |   } else if (color == "scrollbar") { | 
					
						
							|  |  |  |     id = COLOR_SCROLLBAR; | 
					
						
							|  |  |  |   } else if (color == "window") { | 
					
						
							|  |  |  |     id = COLOR_WINDOW; | 
					
						
							|  |  |  |   } else if (color == "window-frame") { | 
					
						
							|  |  |  |     id = COLOR_WINDOWFRAME; | 
					
						
							|  |  |  |   } else if (color == "window-text") { | 
					
						
							|  |  |  |     id = COLOR_WINDOWTEXT; | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2019-10-21 14:31:03 -07:00
										 |  |  |     thrower.ThrowError("Unknown color: " + color); | 
					
						
							| 
									
										
										
										
											2016-10-10 14:31:06 -07:00
										 |  |  |     return ""; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ToRGBHex(color_utils::GetSysSkColor(id)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  | std::string SystemPreferences::GetMediaAccessStatus( | 
					
						
							| 
									
										
										
										
											2020-07-28 11:03:30 -07:00
										 |  |  |     gin_helper::ErrorThrower thrower, | 
					
						
							|  |  |  |     const std::string& media_type) { | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  |   if (media_type == "camera") { | 
					
						
							|  |  |  |     return ConvertDeviceAccessStatus( | 
					
						
							|  |  |  |         GetDeviceAccessStatus(DeviceClass::DeviceClass_VideoCapture)); | 
					
						
							|  |  |  |   } else if (media_type == "microphone") { | 
					
						
							|  |  |  |     return ConvertDeviceAccessStatus( | 
					
						
							|  |  |  |         GetDeviceAccessStatus(DeviceClass::DeviceClass_AudioCapture)); | 
					
						
							|  |  |  |   } else if (media_type == "screen") { | 
					
						
							|  |  |  |     return ConvertDeviceAccessStatus( | 
					
						
							|  |  |  |         DeviceAccessStatus::DeviceAccessStatus_Allowed); | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2020-07-28 11:03:30 -07:00
										 |  |  |     thrower.ThrowError("Invalid media type"); | 
					
						
							| 
									
										
										
										
											2020-06-25 18:47:50 +02:00
										 |  |  |     return std::string(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | void SystemPreferences::InitializeWindow() { | 
					
						
							| 
									
										
										
										
											2022-06-16 03:46:11 -04:00
										 |  |  |   inverted_color_scheme_ = IsInvertedColorScheme(); | 
					
						
							| 
									
										
										
										
											2018-10-31 15:22:18 +01:00
										 |  |  |   high_contrast_color_scheme_ = IsHighContrastColorScheme(); | 
					
						
							| 
									
										
										
										
											2016-10-10 10:20:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-02 09:34:20 -08:00
										 |  |  |   // Wait until app is ready before creating sys color listener
 | 
					
						
							|  |  |  |   // Creating this listener before the app is ready causes global shortcuts
 | 
					
						
							|  |  |  |   // to not fire
 | 
					
						
							|  |  |  |   if (Browser::Get()->is_ready()) | 
					
						
							| 
									
										
										
										
											2021-06-07 19:00:05 -07:00
										 |  |  |     color_change_listener_ = | 
					
						
							|  |  |  |         std::make_unique<gfx::ScopedSysColorChangeListener>(this); | 
					
						
							| 
									
										
										
										
											2017-02-02 09:34:20 -08:00
										 |  |  |   else | 
					
						
							|  |  |  |     Browser::Get()->AddObserver(this); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |   WNDCLASSEX window_class; | 
					
						
							|  |  |  |   base::win::InitializeWindowClass( | 
					
						
							| 
									
										
										
										
											2016-09-20 02:42:41 +10:00
										 |  |  |       kSystemPreferencesWindowClass, | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |       &base::win::WrappedWindowProc<SystemPreferences::WndProcStatic>, 0, 0, 0, | 
					
						
							|  |  |  |       NULL, NULL, NULL, NULL, NULL, &window_class); | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |   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".
 | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |   window_ = CreateWindow(MAKEINTATOM(atom_), 0, WS_POPUP, 0, 0, 0, 0, 0, 0, | 
					
						
							|  |  |  |                          instance_, 0); | 
					
						
							| 
									
										
										
										
											2020-07-13 18:13:34 -07:00
										 |  |  |   gfx::CheckWindowCreated(window_, ::GetLastError()); | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |   gfx::SetWindowUserData(window_, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LRESULT CALLBACK SystemPreferences::WndProcStatic(HWND hwnd, | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |                                                   UINT message, | 
					
						
							|  |  |  |                                                   WPARAM wparam, | 
					
						
							|  |  |  |                                                   LPARAM lparam) { | 
					
						
							| 
									
										
										
										
											2020-10-26 11:56:31 -07:00
										 |  |  |   auto* msg_wnd = reinterpret_cast<SystemPreferences*>( | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |       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, | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |                                             UINT message, | 
					
						
							|  |  |  |                                             WPARAM wparam, | 
					
						
							|  |  |  |                                             LPARAM lparam) { | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |   if (message == WM_DWMCOLORIZATIONCOLORCHANGED) { | 
					
						
							| 
									
										
										
										
											2018-04-17 21:55:30 -04:00
										 |  |  |     DWORD new_color = (DWORD)wparam; | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  |     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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 10:20:51 -07:00
										 |  |  | void SystemPreferences::OnSysColorChange() { | 
					
						
							| 
									
										
										
										
											2022-06-16 03:46:11 -04:00
										 |  |  |   bool new_inverted_color_scheme = IsInvertedColorScheme(); | 
					
						
							|  |  |  |   if (new_inverted_color_scheme != inverted_color_scheme_) { | 
					
						
							|  |  |  |     inverted_color_scheme_ = new_inverted_color_scheme; | 
					
						
							|  |  |  |     Emit("inverted-color-scheme-changed", new_inverted_color_scheme); | 
					
						
							| 
									
										
										
										
											2016-10-07 09:38:19 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-10-31 15:22:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   bool new_high_contrast_color_scheme = IsHighContrastColorScheme(); | 
					
						
							|  |  |  |   if (new_high_contrast_color_scheme != high_contrast_color_scheme_) { | 
					
						
							|  |  |  |     high_contrast_color_scheme_ = new_high_contrast_color_scheme; | 
					
						
							|  |  |  |     Emit("high-contrast-color-scheme-changed", new_high_contrast_color_scheme); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-11 09:35:14 -07:00
										 |  |  |   Emit("color-changed"); | 
					
						
							| 
									
										
										
										
											2016-10-07 09:38:19 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 23:28:41 -07:00
										 |  |  | void SystemPreferences::OnFinishLaunching(base::Value::Dict launch_info) { | 
					
						
							| 
									
										
										
										
											2021-06-07 19:00:05 -07:00
										 |  |  |   color_change_listener_ = | 
					
						
							|  |  |  |       std::make_unique<gfx::ScopedSysColorChangeListener>(this); | 
					
						
							| 
									
										
										
										
											2017-02-02 09:34:20 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 02:00:22 +10:00
										 |  |  | }  // namespace api
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace electron
 |