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