1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/gfx/sys_color_change_listener.h"
6
7#if defined(OS_WIN)
8#include <windows.h>
9#endif
10
11#include "base/basictypes.h"
12#include "base/memory/singleton.h"
13#include "base/observer_list.h"
14#include "ui/gfx/color_utils.h"
15
16#if defined(OS_WIN)
17#include "ui/gfx/win/singleton_hwnd.h"
18#endif
19
20namespace gfx {
21
22namespace {
23
24bool g_is_inverted_color_scheme = false;
25bool g_is_inverted_color_scheme_initialized = false;
26
27void UpdateInvertedColorScheme() {
28#if defined(OS_WIN)
29  int foreground_luminance = color_utils::GetLuminanceForColor(
30      color_utils::GetSysSkColor(COLOR_WINDOWTEXT));
31  int background_luminance = color_utils::GetLuminanceForColor(
32      color_utils::GetSysSkColor(COLOR_WINDOW));
33  HIGHCONTRAST high_contrast = {0};
34  high_contrast.cbSize = sizeof(HIGHCONTRAST);
35  g_is_inverted_color_scheme =
36      SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &high_contrast, 0) &&
37      ((high_contrast.dwFlags & HCF_HIGHCONTRASTON) != 0) &&
38      foreground_luminance > background_luminance;
39  g_is_inverted_color_scheme_initialized = true;
40#endif
41}
42
43}  // namespace
44
45bool IsInvertedColorScheme() {
46  if (!g_is_inverted_color_scheme_initialized)
47    UpdateInvertedColorScheme();
48  return g_is_inverted_color_scheme;
49}
50
51#if defined(OS_WIN)
52class SysColorChangeObserver : public gfx::SingletonHwnd::Observer {
53 public:
54  static SysColorChangeObserver* GetInstance();
55
56  void AddListener(SysColorChangeListener* listener);
57  void RemoveListener(SysColorChangeListener* listener);
58
59 private:
60  friend struct DefaultSingletonTraits<SysColorChangeObserver>;
61
62  SysColorChangeObserver();
63  virtual ~SysColorChangeObserver();
64
65  virtual void OnWndProc(HWND hwnd,
66                         UINT message,
67                         WPARAM wparam,
68                         LPARAM lparam) OVERRIDE;
69
70  ObserverList<SysColorChangeListener> listeners_;
71};
72
73// static
74SysColorChangeObserver* SysColorChangeObserver::GetInstance() {
75  return Singleton<SysColorChangeObserver>::get();
76}
77
78SysColorChangeObserver::SysColorChangeObserver() {
79  gfx::SingletonHwnd::GetInstance()->AddObserver(this);
80}
81
82SysColorChangeObserver::~SysColorChangeObserver() {
83  gfx::SingletonHwnd::GetInstance()->RemoveObserver(this);
84}
85
86void SysColorChangeObserver::AddListener(SysColorChangeListener* listener) {
87  listeners_.AddObserver(listener);
88}
89
90void SysColorChangeObserver::RemoveListener(SysColorChangeListener* listener) {
91  listeners_.RemoveObserver(listener);
92}
93
94void SysColorChangeObserver::OnWndProc(HWND hwnd,
95                                       UINT message,
96                                       WPARAM wparam,
97                                       LPARAM lparam) {
98  if (message == WM_SYSCOLORCHANGE ||
99      (message == WM_SETTINGCHANGE && wparam == SPI_SETHIGHCONTRAST)) {
100    UpdateInvertedColorScheme();
101    FOR_EACH_OBSERVER(SysColorChangeListener, listeners_, OnSysColorChange());
102  }
103}
104#endif
105
106ScopedSysColorChangeListener::ScopedSysColorChangeListener(
107    SysColorChangeListener* listener)
108    : listener_(listener) {
109#if defined(OS_WIN)
110  SysColorChangeObserver::GetInstance()->AddListener(listener_);
111#endif
112}
113
114ScopedSysColorChangeListener::~ScopedSysColorChangeListener() {
115#if defined(OS_WIN)
116  SysColorChangeObserver::GetInstance()->RemoveListener(listener_);
117#endif
118}
119
120}  // namespace gfx
121