diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-17 04:52:11 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-17 04:52:11 +0000 |
commit | 123f0d0432c0aead5d9a2bd1c1df3fc87fe19289 (patch) | |
tree | abad086fa3afe42542a6fe47de7c77c10c81eb83 | |
parent | 5831265ef0c06bbbbe2ee7b807b554c765e407aa (diff) | |
download | chromium_src-123f0d0432c0aead5d9a2bd1c1df3fc87fe19289.zip chromium_src-123f0d0432c0aead5d9a2bd1c1df3fc87fe19289.tar.gz chromium_src-123f0d0432c0aead5d9a2bd1c1df3fc87fe19289.tar.bz2 |
Invert web content when Windows color scheme is white-on-black.
Adds a new interface to listen for changes to system color changes,
which can be used in future changelists to fix other widgets that need
to recompute their color schemes when the user toggles high-contrast mode
on and off.
NTP is currently the only place in Chrome code that uses Windows theme
colors inside the web content area; update this to invert these colors
if we're also inverting the whole web content area.
BUG=112944
TEST=Press Alt+Shift+PrtScr on Windows to toggle high-contrast mode on/off.
Review URL: https://chromiumcodereview.appspot.com/9452033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127344 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/accessibility/invert_bubble_views.cc | 135 | ||||
-rw-r--r-- | chrome/browser/accessibility/invert_bubble_views.h | 27 | ||||
-rw-r--r-- | chrome/browser/prefs/browser_prefs.cc | 2 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/browser_view.cc | 12 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/browser_view.h | 11 | ||||
-rw-r--r-- | chrome/browser/ui/webui/ntp/ntp_resource_cache.cc | 39 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 4 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 2 | ||||
-rw-r--r-- | content/browser/accessibility/browser_accessibility_state_impl.cc | 4 | ||||
-rw-r--r-- | content/browser/renderer_host/render_view_host_impl.cc | 8 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_win.cc | 9 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_win.h | 9 | ||||
-rw-r--r-- | ui/gfx/color_utils.cc | 8 | ||||
-rw-r--r-- | ui/gfx/color_utils.h | 6 | ||||
-rw-r--r-- | ui/gfx/sys_color_change_listener.cc | 118 | ||||
-rw-r--r-- | ui/gfx/sys_color_change_listener.h | 45 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
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_ @@ -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', |