| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/gfx/sys_color_change_listener.h" |
| |
| #include <windows.h> |
| |
| #include <memory> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/memory/singleton.h" |
| #include "base/observer_list.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/gfx/win/singleton_hwnd_observer.h" |
| |
| namespace { |
| |
| bool g_is_inverted_color_scheme = false; |
| bool g_is_inverted_color_scheme_initialized = false; |
| |
| void UpdateInvertedColorScheme() { |
| const uint8_t foreground_luma = |
| color_utils::GetLuma(color_utils::GetSysSkColor(COLOR_WINDOWTEXT)); |
| const uint8_t background_luma = |
| color_utils::GetLuma(color_utils::GetSysSkColor(COLOR_WINDOW)); |
| HIGHCONTRAST high_contrast = {0}; |
| high_contrast.cbSize = sizeof(HIGHCONTRAST); |
| g_is_inverted_color_scheme = |
| SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &high_contrast, 0) && |
| ((high_contrast.dwFlags & HCF_HIGHCONTRASTON) != 0) && |
| foreground_luma > background_luma; |
| g_is_inverted_color_scheme_initialized = true; |
| } |
| |
| } // namespace |
| |
| namespace color_utils { |
| |
| bool IsInvertedColorScheme() { |
| if (!g_is_inverted_color_scheme_initialized) |
| UpdateInvertedColorScheme(); |
| return g_is_inverted_color_scheme; |
| } |
| |
| } // namespace color_utils |
| |
| namespace gfx { |
| |
| class SysColorChangeObserver { |
| public: |
| static SysColorChangeObserver* GetInstance(); |
| |
| void AddListener(SysColorChangeListener* listener); |
| void RemoveListener(SysColorChangeListener* listener); |
| |
| private: |
| friend struct base::DefaultSingletonTraits<SysColorChangeObserver>; |
| |
| SysColorChangeObserver(); |
| virtual ~SysColorChangeObserver(); |
| |
| void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); |
| |
| base::ObserverList<SysColorChangeListener> listeners_; |
| std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_; |
| }; |
| |
| // static |
| SysColorChangeObserver* SysColorChangeObserver::GetInstance() { |
| return base::Singleton<SysColorChangeObserver>::get(); |
| } |
| |
| SysColorChangeObserver::SysColorChangeObserver() |
| : singleton_hwnd_observer_(new SingletonHwndObserver( |
| base::Bind(&SysColorChangeObserver::OnWndProc, |
| base::Unretained(this)))) {} |
| |
| SysColorChangeObserver::~SysColorChangeObserver() {} |
| |
| void SysColorChangeObserver::AddListener(SysColorChangeListener* listener) { |
| listeners_.AddObserver(listener); |
| } |
| |
| void SysColorChangeObserver::RemoveListener(SysColorChangeListener* listener) { |
| listeners_.RemoveObserver(listener); |
| } |
| |
| void SysColorChangeObserver::OnWndProc(HWND hwnd, |
| UINT message, |
| WPARAM wparam, |
| LPARAM lparam) { |
| if (message == WM_SYSCOLORCHANGE || |
| (message == WM_SETTINGCHANGE && wparam == SPI_SETHIGHCONTRAST)) { |
| UpdateInvertedColorScheme(); |
| for (SysColorChangeListener& observer : listeners_) |
| observer.OnSysColorChange(); |
| } |
| } |
| |
| ScopedSysColorChangeListener::ScopedSysColorChangeListener( |
| SysColorChangeListener* listener) |
| : listener_(listener) { |
| SysColorChangeObserver::GetInstance()->AddListener(listener_); |
| } |
| |
| ScopedSysColorChangeListener::~ScopedSysColorChangeListener() { |
| SysColorChangeObserver::GetInstance()->RemoveListener(listener_); |
| } |
| |
| } // namespace gfx |