summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/accessibility/invert_bubble_views.cc135
-rw-r--r--chrome/browser/accessibility/invert_bubble_views.h27
-rw-r--r--chrome/browser/prefs/browser_prefs.cc2
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc12
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h11
-rw-r--r--chrome/browser/ui/webui/ntp/ntp_resource_cache.cc39
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/pref_names.cc4
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--content/browser/accessibility/browser_accessibility_state_impl.cc4
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc8
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc9
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.h9
-rw-r--r--ui/gfx/color_utils.cc8
-rw-r--r--ui/gfx/color_utils.h6
-rw-r--r--ui/gfx/sys_color_change_listener.cc118
-rw-r--r--ui/gfx/sys_color_change_listener.h45
-rw-r--r--ui/ui.gyp2
19 files changed, 426 insertions, 23 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 85c726a..c643945 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -15419,6 +15419,12 @@ Battery full
</message>
</if>
+ <!-- Inverting for high-constrast mode. -->
+ <message name="IDS_INVERT_NOTIFICATION"
+ desc="Text that explains that Chrome has inverted (i.e. reversed black and white) all web pages because the user is using Windows High-Constrast mode with an inverted color scheme.">
+ Web pages are displayed inverted because you have High Constrast mode enabled and you're using a light-on-dark color scheme.
+ </message>
+
</messages>
<structures fallback_to_english="true">
<!-- Make sure these stay in sync with the structures in generated_resources.grd. -->
diff --git a/chrome/browser/accessibility/invert_bubble_views.cc b/chrome/browser/accessibility/invert_bubble_views.cc
new file mode 100644
index 0000000..d6971b1
--- /dev/null
+++ b/chrome/browser/accessibility/invert_bubble_views.cc
@@ -0,0 +1,135 @@
+// 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 "base/utf_string_conversions.h"
+#include "chrome/browser/accessibility/invert_bubble_views.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/views/event_utils.h"
+#include "chrome/browser/ui/views/window.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/page_navigator.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/sys_color_change_listener.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/controls/link_listener.h"
+#include "ui/views/layout/grid_layout.h"
+#include "ui/views/layout/layout_constants.h"
+
+namespace {
+const char kLearnMoreUrl[] = "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
+const int kBubbleWidth = 500;
+} // namespace
+
+class InvertBubbleView : public views::BubbleDelegateView,
+ public views::LinkListener {
+ public:
+ InvertBubbleView(Profile* profile, views::View* anchor_view);
+ virtual ~InvertBubbleView();
+
+ // views::BubbleDelegateView overrides:
+ virtual gfx::Rect GetAnchorRect() OVERRIDE;
+
+ protected:
+ // views::BubbleDelegateView overrides:
+ virtual void Init() OVERRIDE;
+
+ // views::LinkListener overrides:
+ virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
+
+ Profile* profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvertBubbleView);
+};
+
+void InvertBubbleView::Init() {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ const gfx::Font& original_font = rb.GetFont(ResourceBundle::MediumFont);
+
+ views::Label* title = new views::Label(
+ l10n_util::GetStringUTF16(IDS_INVERT_NOTIFICATION));
+ title->SetFont(original_font.DeriveFont(2, gfx::Font::BOLD));
+ title->SetMultiLine(true);
+ title->SizeToFit(kBubbleWidth);
+
+ views::Link* learn_more =
+ new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
+ learn_more->SetFont(original_font);
+ learn_more->set_listener(this);
+
+ views::GridLayout* layout = views::GridLayout::CreatePanel(this);
+ SetLayoutManager(layout);
+
+ views::ColumnSet* columns = layout->AddColumnSet(0);
+ columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0,
+ views::GridLayout::USE_PREF, 0, 0);
+
+ layout->StartRow(0, 0);
+ layout->AddView(title);
+ layout->StartRowWithPadding(0, 0, 0,
+ views::kRelatedControlSmallVerticalSpacing);
+ layout->AddView(learn_more);
+
+ // Switching to high-contrast mode has a nasty habit of causing Chrome
+ // top-level windows to lose focus, so closing the bubble on deactivate
+ // makes it disappear before the user has even seen it. This forces the
+ // user to close it explicitly, which should be okay because it affects
+ // a small minority of users, and only once.
+ set_close_on_deactivate(false);
+}
+
+gfx::Rect InvertBubbleView::GetAnchorRect() {
+ // Set the height to 0 so we display the bubble at the top of the
+ // anchor rect.
+ gfx::Rect rect(BubbleDelegateView::GetAnchorRect());
+ rect.set_height(0);
+ return rect;
+}
+
+InvertBubbleView::InvertBubbleView(Profile* profile, views::View* anchor_view)
+ : views::BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
+ profile_(profile) {
+}
+
+InvertBubbleView::~InvertBubbleView() {
+}
+
+void InvertBubbleView::LinkClicked(views::Link* source, int event_flags) {
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_);
+ if (browser) {
+ WindowOpenDisposition disposition =
+ event_utils::DispositionFromEventFlags(event_flags);
+ content::OpenURLParams params(
+ GURL(kLearnMoreUrl), content::Referrer(),
+ disposition == CURRENT_TAB ? NEW_FOREGROUND_TAB : disposition,
+ content::PAGE_TRANSITION_LINK, false);
+ browser->OpenURL(params);
+ }
+ GetWidget()->Close();
+}
+
+// static
+void InvertBubble::RegisterUserPrefs(PrefService* prefs) {
+ prefs->RegisterBooleanPref(prefs::kInvertNotificationShown,
+ false,
+ PrefService::UNSYNCABLE_PREF);
+}
+
+void InvertBubble::MaybeShowInvertBubble(Profile* profile,
+ views::View* anchor_view) {
+ PrefService* pref_service = profile->GetPrefs();
+ if (gfx::IsInvertedColorScheme() &&
+ !pref_service->GetBoolean(prefs::kInvertNotificationShown)) {
+ pref_service->SetBoolean(prefs::kInvertNotificationShown, true);
+ InvertBubbleView* delegate = new InvertBubbleView(profile, anchor_view);
+ browser::CreateViewsBubble(delegate);
+ delegate->StartFade(true);
+ }
+}
diff --git a/chrome/browser/accessibility/invert_bubble_views.h b/chrome/browser/accessibility/invert_bubble_views.h
new file mode 100644
index 0000000..d38740c
--- /dev/null
+++ b/chrome/browser/accessibility/invert_bubble_views.h
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef CHROME_BROWSER_ACCESSIBILITY_INVERT_BUBBLE_VIEWS_H_
+#define CHROME_BROWSER_ACCESSIBILITY_INVERT_BUBBLE_VIEWS_H_
+#pragma once
+
+class PrefService;
+class Profile;
+namespace views {
+class View;
+}
+
+class InvertBubble {
+ public:
+ static void RegisterUserPrefs(PrefService* prefs);
+
+ // Show a bubble telling the user that web contents are inverted because
+ // they're using Windows high-constrast mode and their color scheme is
+ // light-on-dark. Only shows the first time we encounter this condition
+ // for a particular profile.
+ static void MaybeShowInvertBubble(Profile* profile,
+ views::View* anchor_view);
+};
+
+#endif // CHROME_BROWSER_ACCESSIBILITY_INVERT_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c696741..aed1810 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -74,6 +74,7 @@
#endif
#if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port
+#include "chrome/browser/accessibility/invert_bubble_views.h"
#include "chrome/browser/ui/views/browser_actions_container.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#endif
@@ -212,6 +213,7 @@ void RegisterUserPrefs(PrefService* user_prefs) {
#if defined(TOOLKIT_VIEWS)
BrowserActionsContainer::RegisterUserPrefs(user_prefs);
+ InvertBubble::RegisterUserPrefs(user_prefs);
#elif defined(TOOLKIT_GTK)
BrowserWindowGtk::RegisterUserPrefs(user_prefs);
#endif
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index aae215b..b31942f 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -18,6 +18,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/accessibility/invert_bubble_views.h"
#include "chrome/browser/autocomplete/autocomplete_popup_model.h"
#include "chrome/browser/autocomplete/autocomplete_popup_view.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
@@ -92,6 +93,8 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/sys_color_change_listener.h"
#include "ui/ui_controls/ui_controls.h"
#include "ui/views/controls/single_split_view.h"
#include "ui/views/events/event.h"
@@ -325,7 +328,8 @@ BrowserView::BrowserView(Browser* browser)
ticker_(0),
#endif
force_location_bar_focus_(false),
- move_observer_(NULL) {
+ move_observer_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(color_change_listener_(this)) {
browser_->tabstrip_model()->AddObserver(this);
}
@@ -615,6 +619,8 @@ void BrowserView::Show() {
force_location_bar_focus_ = false;
browser()->OnWindowDidShow();
+
+ InvertBubble::MaybeShowInvertBubble(browser_->profile(), contents_);
}
void BrowserView::ShowInactive() {
@@ -1852,6 +1858,10 @@ bool BrowserView::SplitHandleMoved(views::SingleSplitView* sender) {
return false;
}
+void BrowserView::OnSysColorChange() {
+ InvertBubble::MaybeShowInvertBubble(browser_->profile(), contents_);
+}
+
views::LayoutManager* BrowserView::CreateLayoutManager() const {
return new BrowserViewLayout;
}
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index e0ddddd..5c592a4 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -22,6 +22,7 @@
#include "chrome/browser/ui/views/tabs/abstract_tab_strip_view.h"
#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h"
#include "ui/base/models/simple_menu_model.h"
+#include "ui/gfx/sys_color_change_listener.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/controls/single_split_view_listener.h"
#include "ui/views/widget/widget_delegate.h"
@@ -87,7 +88,8 @@ class BrowserView : public BrowserWindow,
public views::Widget::Observer,
public views::ClientView,
public InfoBarContainer::Delegate,
- public views::SingleSplitViewListener {
+ public views::SingleSplitViewListener,
+ public gfx::SysColorChangeListener {
public:
// The browser view's class name.
static const char kViewClassName[];
@@ -202,7 +204,7 @@ class BrowserView : public BrowserWindow,
return browser_->is_type_tabbed();
}
- // Register preferences specific to this view.
+ // Register local state preferences specific to this view.
static void RegisterBrowserViewPrefs(PrefService* prefs);
// Returns true if the specified point(BrowserView coordinates) is in
@@ -404,6 +406,9 @@ class BrowserView : public BrowserWindow,
// views::SingleSplitViewListener overrides:
virtual bool SplitHandleMoved(views::SingleSplitView* sender) OVERRIDE;
+ // gfx::ScopedSysColorChangeListener overrides:
+ virtual void OnSysColorChange() OVERRIDE;
+
protected:
// Appends to |toolbars| a pointer to each AccessiblePaneView that
// can be traversed using F6, in the order they should be traversed.
@@ -718,6 +723,8 @@ class BrowserView : public BrowserWindow,
BrowserWindowMoveObserver* move_observer_;
+ gfx::ScopedSysColorChangeListener color_change_listener_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index a037cb0..b18bf16 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -49,6 +49,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/theme_provider.h"
#include "ui/gfx/color_utils.h"
+#include "ui/gfx/sys_color_change_listener.h"
#if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
@@ -108,6 +109,14 @@ std::string SkColorToRGBComponents(SkColor color) {
SkColorGetB(color));
}
+SkColor GetThemeColor(ui::ThemeProvider* tp, int id) {
+ SkColor color = tp->GetColor(id);
+ // If web contents are being inverted because the system is in high-contrast
+ // mode, any system theme colors we use must be inverted too to cancel out.
+ return gfx::IsInvertedColorScheme() ?
+ color_utils::InvertColor(color) : color;
+}
+
// Get the CSS string for the background position on the new tab page for the
// states when the bar is attached or detached.
std::string GetNewTabBackgroundCSS(const ui::ThemeProvider* theme_provider,
@@ -420,7 +429,7 @@ void NTPResourceCache::CreateNewTabIncognitoCSS() {
// Get our theme colors
SkColor color_background =
- tp->GetColor(ThemeService::COLOR_NTP_BACKGROUND);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_BACKGROUND);
// Generate the replacements.
std::vector<std::string> subst;
@@ -453,33 +462,33 @@ void NTPResourceCache::CreateNewTabCSS() {
// Get our theme colors
SkColor color_background =
- tp->GetColor(ThemeService::COLOR_NTP_BACKGROUND);
- SkColor color_text = tp->GetColor(ThemeService::COLOR_NTP_TEXT);
- SkColor color_link = tp->GetColor(ThemeService::COLOR_NTP_LINK);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_BACKGROUND);
+ SkColor color_text = GetThemeColor(tp, ThemeService::COLOR_NTP_TEXT);
+ SkColor color_link = GetThemeColor(tp, ThemeService::COLOR_NTP_LINK);
SkColor color_link_underline =
- tp->GetColor(ThemeService::COLOR_NTP_LINK_UNDERLINE);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_LINK_UNDERLINE);
SkColor color_section =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION);
SkColor color_section_text =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_TEXT);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_TEXT);
SkColor color_section_link =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_LINK);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_LINK);
SkColor color_section_link_underline =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE);
SkColor color_section_header_text =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_TEXT);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_HEADER_TEXT);
SkColor color_section_header_text_hover =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_TEXT_HOVER);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_HEADER_TEXT_HOVER);
SkColor color_section_header_rule =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_RULE);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_HEADER_RULE);
SkColor color_section_header_rule_light =
- tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_RULE_LIGHT);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_SECTION_HEADER_RULE_LIGHT);
SkColor color_text_light =
- tp->GetColor(ThemeService::COLOR_NTP_TEXT_LIGHT);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_TEXT_LIGHT);
SkColor color_header =
- tp->GetColor(ThemeService::COLOR_NTP_HEADER);
+ GetThemeColor(tp, ThemeService::COLOR_NTP_HEADER);
// Generate a lighter color for the header gradients.
color_utils::HSL header_lighter;
color_utils::SkColorToHSL(color_header, &header_lighter);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index dcd2da9..5b84718 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -90,6 +90,8 @@
'browser/accessibility/accessibility_extension_api_constants.h',
'browser/accessibility/accessibility_events.cc',
'browser/accessibility/accessibility_events.h',
+ 'browser/accessibility/invert_bubble_views.cc',
+ 'browser/accessibility/invert_bubble_views.h',
'browser/aeropeek_manager.cc',
'browser/aeropeek_manager.h',
'browser/alternate_nav_url_fetcher.cc',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 211ddcd..6b72aed8 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -942,6 +942,10 @@ const char kPasswordsUseLocalProfileId[] =
const char kProfileAvatarIndex[] = "profile.avatar_index";
const char kProfileName[] = "profile.name";
+// Indicates if we've already shown a notification that web contents are
+// inverted because high-contrast mode is on.
+const char kInvertNotificationShown[] = "invert_notification_shown";
+
// *************** LOCAL STATE ***************
// These are attached to the machine/installation
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index afb38d3..dc9fca8 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -341,6 +341,8 @@ extern const char kPasswordsUseLocalProfileId[];
extern const char kProfileAvatarIndex[];
extern const char kProfileName[];
+extern const char kInvertNotificationShown[];
+
// Local state prefs. Please add Profile prefs above instead.
extern const char kCertRevocationCheckingEnabled[];
extern const char kSSL3Enabled[];
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index 08c0775..7edc3e0 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -7,6 +7,7 @@
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/timer.h"
+#include "ui/gfx/sys_color_change_listener.h"
// Update the accessibility histogram 45 seconds after initialization.
static const int kAccessibilityHistogramDelaySecs = 45;
@@ -51,4 +52,7 @@ void BrowserAccessibilityStateImpl::UpdateHistogram() {
UMA_HISTOGRAM_ENUMERATION("Accessibility.State",
accessibility_enabled_ ? 1 : 0,
2);
+ UMA_HISTOGRAM_ENUMERATION("Accessibility.InvertedColors",
+ gfx::IsInvertedColorScheme() ? 1 : 0,
+ 2);
}
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index b2e76fc..3edbcc9 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -58,6 +58,7 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
#endif
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/sys_color_change_listener.h"
#include "webkit/fileapi/isolated_context.h"
#include "webkit/glue/webaccessibility.h"
#include "webkit/glue/webdropdata.h"
@@ -250,8 +251,11 @@ bool RenderViewHostImpl::CreateRenderView(const string16& frame_name,
// Let our delegate know that we created a RenderView.
delegate_->RenderViewCreated(this);
- // Invert the color scheme if a flag was set.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInvertWebContent))
+ // Invert the color scheme if the operating system's color scheme is
+ // inverted or if a flag is set.
+ if (gfx::IsInvertedColorScheme() ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kInvertWebContent))
Send(new ViewMsg_InvertWebContent(GetRoutingID(), true));
FOR_EACH_OBSERVER(
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 7b45563..6cb801a 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -331,7 +331,8 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
pointer_down_context_(false),
focus_on_editable_field_(false),
received_focus_change_after_pointer_down_(false),
- touch_events_enabled_(false) {
+ touch_events_enabled_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(sys_color_change_listener_(this)) {
render_widget_host_->SetView(this);
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
@@ -1331,6 +1332,12 @@ void RenderWidgetHostViewWin::OnThemeChanged() {
render_widget_host_->GetRoutingID()));
}
+void RenderWidgetHostViewWin::OnSysColorChange() {
+ render_widget_host_->Send(new ViewMsg_InvertWebContent(
+ render_widget_host_->GetRoutingID(),
+ gfx::IsInvertedColorScheme()));
+}
+
LRESULT RenderWidgetHostViewWin::OnNotify(int w_param, NMHDR* header) {
if (tooltip_hwnd_ == NULL)
return 0;
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index 4dc81b4..2269430 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -28,6 +28,7 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/surface/accelerated_surface_win.h"
+#include "ui/gfx/sys_color_change_listener.h"
#include "webkit/glue/webcursor.h"
class BackingStore;
@@ -91,7 +92,8 @@ class RenderWidgetHostViewWin
RenderWidgetHostHWNDTraits>,
public content::RenderWidgetHostViewBase,
public content::NotificationObserver,
- public BrowserAccessibilityDelegate {
+ public BrowserAccessibilityDelegate,
+ public gfx::SysColorChangeListener {
public:
virtual ~RenderWidgetHostViewWin();
@@ -239,6 +241,9 @@ class RenderWidgetHostViewWin
virtual void AccessibilitySetTextSelection(
int acc_obj_id, int start_offset, int end_offset) OVERRIDE;
+ // Implementation of SysColorChangeListener:
+ virtual void OnSysColorChange() OVERRIDE;
+
protected:
friend class content::RenderWidgetHostView;
@@ -566,6 +571,8 @@ class RenderWidgetHostViewWin
// Are touch events currently enabled?
bool touch_events_enabled_;
+ gfx::ScopedSysColorChangeListener sys_color_change_listener_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewWin);
};
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc
index a79947c..0012b24 100644
--- a/ui/gfx/color_utils.cc
+++ b/ui/gfx/color_utils.cc
@@ -296,6 +296,14 @@ SkColor GetReadableColor(SkColor foreground, SkColor background) {
foreground : foreground2;
}
+SkColor InvertColor(SkColor color) {
+ return SkColorSetARGB(
+ SkColorGetA(color),
+ 255 - SkColorGetR(color),
+ 255 - SkColorGetG(color),
+ 255 - SkColorGetB(color));
+}
+
SkColor GetSysSkColor(int which) {
#if defined(OS_WIN)
return skia::COLORREFToSkColor(GetSysColor(which));
diff --git a/ui/gfx/color_utils.h b/ui/gfx/color_utils.h
index 8f2697b..0627d34 100644
--- a/ui/gfx/color_utils.h
+++ b/ui/gfx/color_utils.h
@@ -6,6 +6,7 @@
#define UI_GFX_COLOR_UTILS_H_
#pragma once
+#include "base/basictypes.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_export.h"
@@ -20,7 +21,7 @@ struct HSL {
double l;
};
-unsigned char GetLuminanceForColor(SkColor color);
+UI_EXPORT unsigned char GetLuminanceForColor(SkColor color);
// Calculated according to http://www.w3.org/TR/WCAG20/#relativeluminancedef
UI_EXPORT double RelativeLuminance(SkColor color);
@@ -76,6 +77,9 @@ UI_EXPORT SkColor AlphaBlend(SkColor foreground, SkColor background,
// has a luma value close to the midpoint (0.5 in the HSL representation).
UI_EXPORT SkColor GetReadableColor(SkColor foreground, SkColor background);
+// Invert a color.
+UI_EXPORT SkColor InvertColor(SkColor color);
+
// Gets a Windows system color as a SkColor
UI_EXPORT SkColor GetSysSkColor(int which);
diff --git a/ui/gfx/sys_color_change_listener.cc b/ui/gfx/sys_color_change_listener.cc
new file mode 100644
index 0000000..b6e321c
--- /dev/null
+++ b/ui/gfx/sys_color_change_listener.cc
@@ -0,0 +1,118 @@
+// 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/color_utils.h"
+#include "ui/gfx/sys_color_change_listener.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "base/observer_list.h"
+#if defined(OS_WIN)
+#include "ui/base/win/singleton_hwnd.h"
+#endif
+
+namespace gfx {
+
+namespace {
+
+bool g_is_inverted_color_scheme = false;
+bool g_is_inverted_color_scheme_initialized = false;
+
+void UpdateInvertedColorScheme() {
+#if defined(OS_WIN)
+ int foreground = color_utils::GetLuminanceForColor(
+ color_utils::GetSysSkColor(COLOR_WINDOWTEXT));
+ int background = color_utils::GetLuminanceForColor(
+ 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);
+ g_is_inverted_color_scheme_initialized = true;
+#endif
+}
+
+} // namespace
+
+bool IsInvertedColorScheme() {
+ if (!g_is_inverted_color_scheme_initialized)
+ UpdateInvertedColorScheme();
+ return g_is_inverted_color_scheme;
+}
+
+#if defined(OS_WIN)
+class SysColorChangeObserver : public ui::SingletonHwnd::Observer {
+ public:
+ static SysColorChangeObserver* GetInstance();
+
+ void AddListener(SysColorChangeListener* listener);
+ void RemoveListener(SysColorChangeListener* listener);
+
+ private:
+ friend struct DefaultSingletonTraits<SysColorChangeObserver>;
+
+ SysColorChangeObserver();
+ virtual ~SysColorChangeObserver();
+
+ virtual void OnWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) OVERRIDE;
+
+ ObserverList<SysColorChangeListener> listeners_;
+};
+
+// static
+SysColorChangeObserver* SysColorChangeObserver::GetInstance() {
+ return Singleton<SysColorChangeObserver>::get();
+}
+
+SysColorChangeObserver::SysColorChangeObserver() {
+ ui::SingletonHwnd::GetInstance()->AddObserver(this);
+}
+
+SysColorChangeObserver::~SysColorChangeObserver() {
+ ui::SingletonHwnd::GetInstance()->RemoveObserver(this);
+}
+
+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_EACH_OBSERVER(SysColorChangeListener, listeners_, OnSysColorChange());
+ }
+}
+#endif
+
+ScopedSysColorChangeListener::ScopedSysColorChangeListener(
+ SysColorChangeListener* listener)
+ : listener_(listener) {
+#if defined(OS_WIN)
+ SysColorChangeObserver::GetInstance()->AddListener(listener_);
+#endif
+}
+
+ScopedSysColorChangeListener::~ScopedSysColorChangeListener() {
+#if defined(OS_WIN)
+ SysColorChangeObserver::GetInstance()->RemoveListener(listener_);
+#endif
+}
+
+} // namespace gfx
diff --git a/ui/gfx/sys_color_change_listener.h b/ui/gfx/sys_color_change_listener.h
new file mode 100644
index 0000000..6cb126c
--- /dev/null
+++ b/ui/gfx/sys_color_change_listener.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef UI_GFX_SYS_COLOR_CHANGE_LISTENER_H_
+#define UI_GFX_SYS_COLOR_SCHEME_LISTENER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/ui_export.h"
+
+namespace gfx {
+
+// Returns true only if Chrome should use an inverted color scheme - which is
+// only true if the system has high-contrast mode enabled and and is using a
+// light-on-dark color scheme. To be notified when this status changes, use
+// ScopedSysColorChangeListener, below.
+UI_EXPORT bool IsInvertedColorScheme();
+
+// Interface for classes that want to listen to system color changes.
+class SysColorChangeListener {
+ public:
+ virtual void OnSysColorChange() = 0;
+
+ protected:
+ virtual ~SysColorChangeListener() {}
+};
+
+// Create an instance of this class in any object that wants to listen
+// for system color changes.
+class UI_EXPORT ScopedSysColorChangeListener {
+ public:
+ explicit ScopedSysColorChangeListener(SysColorChangeListener* listener);
+ ~ScopedSysColorChangeListener();
+
+ private:
+ SysColorChangeListener* listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSysColorChangeListener);
+};
+
+} // namespace gfx;
+
+#endif // UI_GFX_SYS_COLOR_CHANGE_LISTENER_
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 85c34dc..f54abc2 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -358,6 +358,8 @@
'gfx/skia_util.h',
'gfx/skia_utils_gtk.cc',
'gfx/skia_utils_gtk.h',
+ 'gfx/sys_color_change_listener.cc',
+ 'gfx/sys_color_change_listener.h',
'gfx/transform.cc',
'gfx/transform.h',
'gfx/transform_util.cc',