From 86208b298ba3fbf177d9cc07bb864f51e636394b Mon Sep 17 00:00:00 2001 From: Jared Wein Date: Thu, 20 Mar 2014 20:23:36 -0400 Subject: [PATCH] Bug 940393 - Win8: Text color on inactive tabs makes text very hard to read. r=gijs --- browser/base/content/browser.js | 27 ++++++++ .../migration/src/IEProfileMigrator.js | 64 ++++--------------- browser/modules/Windows8WindowFrameColor.jsm | 33 ++++++++++ browser/modules/WindowsRegistry.jsm | 50 +++++++++++++++ browser/modules/moz.build | 2 + browser/themes/windows/browser-aero.css | 21 ++++++ browser/themes/windows/browser.css | 4 +- 7 files changed, 148 insertions(+), 53 deletions(-) create mode 100644 browser/modules/Windows8WindowFrameColor.jsm create mode 100644 browser/modules/WindowsRegistry.jsm diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 4be040b95b4c..abbe16895463 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1186,6 +1186,33 @@ var gBrowserInit = { WindowsPrefSync.init(); } +#ifdef XP_WIN + if (window.matchMedia("-moz-os-version: windows-win8") && + window.matchMedia("-moz-windows-default-theme")) { + let windows8WindowFrameColor = Cu.import("resource:///modules/Windows8WindowFrameColor.jsm", {}).Windows8WindowFrameColor; + let windowFrameColor = windows8WindowFrameColor.get(); + + // Formula from W3C Techniques For Accessibility Evaluation And + // Repair Tools, Section 2.2 http://www.w3.org/TR/AERT#color + let brightnessThreshold = 125; + let colorThreshold = 500; + let bY = windowFrameColor[0] * .299 + + windowFrameColor[1] * .587 + + windowFrameColor[2] * .114; + let fY = 0; // Default to black for foreground text. + let brightnessDifference = Math.abs(bY - fY); + // Color difference calculation is simplified because black is 0 for R,G,B. + let colorDifference = windowFrameColor[0] + windowFrameColor[1] + windowFrameColor[2]; + + // Brightness is defined within {0, 255}. Set an attribute + // if the window frame color doesn't reach these thresholds + // so the theme can be adjusted for readability. + if (brightnessDifference < brightnessThreshold && colorDifference < colorThreshold) { + document.documentElement.setAttribute("darkwindowframe", "true"); + } + } +#endif + SessionStore.promiseInitialized.then(() => { // Bail out if the window has been closed in the meantime. if (window.closed) { diff --git a/browser/components/migration/src/IEProfileMigrator.js b/browser/components/migration/src/IEProfileMigrator.js index 2a226e32ae47..32247938d1f8 100644 --- a/browser/components/migration/src/IEProfileMigrator.js +++ b/browser/components/migration/src/IEProfileMigrator.js @@ -10,7 +10,6 @@ const Cu = Components.utils; const Cr = Components.results; const kMainKey = "Software\\Microsoft\\Internet Explorer\\Main"; -const kRegMultiSz = 7; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -21,6 +20,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ctypes", "resource://gre/modules/ctypes.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry", + "resource:///modules/WindowsRegistry.jsm"); //////////////////////////////////////////////////////////////////////////////// //// Helpers. @@ -126,45 +127,6 @@ function hostIsIPAddress(aHost) { return false; } -/** - * Safely reads a value from the registry. - * - * @param aRoot - * The root registry to use. - * @param aPath - * The registry path to the key. - * @param aKey - * The key name. - * @return The key value or undefined if it doesn't exist. If the key is - * a REG_MULTI_SZ, an array is returned. - */ -function readRegKey(aRoot, aPath, aKey) { - let registry = Cc["@mozilla.org/windows-registry-key;1"]. - createInstance(Ci.nsIWindowsRegKey); - try { - registry.open(aRoot, aPath, Ci.nsIWindowsRegKey.ACCESS_READ); - if (registry.hasValue(aKey)) { - let type = registry.getValueType(aKey); - switch (type) { - case kRegMultiSz: - // nsIWindowsRegKey doesn't support REG_MULTI_SZ type out of the box. - let str = registry.readStringValue(aKey); - return [v for each (v in str.split("\0")) if (v)]; - case Ci.nsIWindowsRegKey.TYPE_STRING: - return registry.readStringValue(aKey); - case Ci.nsIWindowsRegKey.TYPE_INT: - return registry.readIntValue(aKey); - default: - throw new Error("Unsupported registry value."); - } - } - } catch (ex) { - } finally { - registry.close(); - } - return undefined; -}; - //////////////////////////////////////////////////////////////////////////////// //// Resources @@ -192,9 +154,9 @@ Bookmarks.prototype = { // Retrieve the name of IE's favorites subfolder that holds the bookmarks // in the toolbar. This was previously stored in the registry and changed // in IE7 to always be called "Links". - let folderName = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - "Software\\Microsoft\\Internet Explorer\\Toolbar", - "LinksFolderName"); + let folderName = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "Software\\Microsoft\\Internet Explorer\\Toolbar", + "LinksFolderName"); this.__toolbarFolderName = folderName || "Links"; } return this.__toolbarFolderName; @@ -605,8 +567,8 @@ Settings.prototype = { * Conversion function from the Registry format to the pref format. */ _set: function S__set(aPath, aKey, aPref, aTransformFn) { - let value = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - aPath, aKey); + let value = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + aPath, aKey); // Don't import settings that have never been flipped. if (value === undefined) return; @@ -651,10 +613,10 @@ IEProfileMigrator.prototype.getResources = function IE_getResources() { Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", { get: function IE_get_sourceHomePageURL() { - let defaultStartPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, - kMainKey, "Default_Page_URL"); - let startPage = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - kMainKey, "Start Page"); + let defaultStartPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, + kMainKey, "Default_Page_URL"); + let startPage = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + kMainKey, "Start Page"); // If the user didn't customize the Start Page, he is still on the default // page, that may be considered the equivalent of our about:home. There's // no reason to retain it, since it is heavily targeted to IE. @@ -664,8 +626,8 @@ Object.defineProperty(IEProfileMigrator.prototype, "sourceHomePageURL", { // are in addition to the Start Page, and no empty entries are possible, // thus a Start Page is always defined if any of these exists, though it // may be the default one. - let secondaryPages = readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, - kMainKey, "Secondary Start Pages"); + let secondaryPages = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + kMainKey, "Secondary Start Pages"); if (secondaryPages) { if (homepage) secondaryPages.unshift(homepage); diff --git a/browser/modules/Windows8WindowFrameColor.jsm b/browser/modules/Windows8WindowFrameColor.jsm new file mode 100644 index 000000000000..a80881c45727 --- /dev/null +++ b/browser/modules/Windows8WindowFrameColor.jsm @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +this.EXPORTED_SYMBOLS = ["Windows8WindowFrameColor"]; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource:///modules/WindowsRegistry.jsm"); + +const Windows8WindowFrameColor = { + _windowFrameColor: null, + + get: function() { + if (this._windowFrameColor) + return this._windowFrameColor; + + let windowFrameColor = WindowsRegistry.readRegKey(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\DWM", + "ColorizationColor"); + // The color returned from the Registry is in decimal form. + let windowFrameColorHex = windowFrameColor.toString(16); + // Zero-pad the number just to make sure that it is 8 digits. + windowFrameColorHex = ("00000000" + windowFrameColorHex).substr(-8); + let windowFrameColorArray = windowFrameColorHex.match(/../g); + let [pixelA, pixelR, pixelG, pixelB] = windowFrameColorArray.map(function(val) parseInt(val, 16)); + + return this._windowFrameColor = [pixelR, pixelG, pixelB]; + }, +}; diff --git a/browser/modules/WindowsRegistry.jsm b/browser/modules/WindowsRegistry.jsm new file mode 100644 index 000000000000..074cd37a207f --- /dev/null +++ b/browser/modules/WindowsRegistry.jsm @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; + +this.EXPORTED_SYMBOLS = ["WindowsRegistry"]; + +const WindowsRegistry = { + /** + * Safely reads a value from the registry. + * + * @param aRoot + * The root registry to use. + * @param aPath + * The registry path to the key. + * @param aKey + * The key name. + * @return The key value or undefined if it doesn't exist. If the key is + * a REG_MULTI_SZ, an array is returned. + */ + readRegKey: function(aRoot, aPath, aKey) { + const kRegMultiSz = 7; + let registry = Cc["@mozilla.org/windows-registry-key;1"]. + createInstance(Ci.nsIWindowsRegKey); + try { + registry.open(aRoot, aPath, Ci.nsIWindowsRegKey.ACCESS_READ); + if (registry.hasValue(aKey)) { + let type = registry.getValueType(aKey); + switch (type) { + case kRegMultiSz: + // nsIWindowsRegKey doesn't support REG_MULTI_SZ type out of the box. + let str = registry.readStringValue(aKey); + return [v for each (v in str.split("\0")) if (v)]; + case Ci.nsIWindowsRegKey.TYPE_STRING: + return registry.readStringValue(aKey); + case Ci.nsIWindowsRegKey.TYPE_INT: + return registry.readIntValue(aKey); + default: + throw new Error("Unsupported registry value."); + } + } + } catch (ex) { + } finally { + registry.close(); + } + return undefined; + }, +}; diff --git a/browser/modules/moz.build b/browser/modules/moz.build index 98b7a45afa58..0af650acd8f5 100644 --- a/browser/modules/moz.build +++ b/browser/modules/moz.build @@ -26,8 +26,10 @@ EXTRA_JS_MODULES += [ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': EXTRA_JS_MODULES += [ + 'Windows8WindowFrameColor.jsm', 'WindowsJumpLists.jsm', 'WindowsPreviewPerTab.jsm', + 'WindowsRegistry.jsm', ] EXTRA_PP_JS_MODULES += [ diff --git a/browser/themes/windows/browser-aero.css b/browser/themes/windows/browser-aero.css index 64fd91c598b0..4a907f0f175d 100644 --- a/browser/themes/windows/browser-aero.css +++ b/browser/themes/windows/browser-aero.css @@ -136,6 +136,26 @@ border-right-style: none !important; } + #main-window[darkwindowframe="true"] #toolbar-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive), + #main-window[darkwindowframe="true"] #TabsToolbar:not(:-moz-lwtheme):not(:-moz-window-inactive) { + color: white; + } + + #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) :-moz-any(@primaryToolbarButtons@):not(:-moz-lwtheme):not(:-moz-window-inactive), + #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) #bookmarks-menu-button:not(:-moz-lwtheme) > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:not(:-moz-window-inactive) { + list-style-image: url(chrome://browser/skin/Toolbar-inverted.png); + } + + #main-window[darkwindowframe="true"] .tabs-newtab-button:not(:-moz-lwtheme):not(:-moz-window-inactive), + #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > #new-tab-button:not(:-moz-lwtheme):not(:-moz-window-inactive), + #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > toolbarpaletteitem > #new-tab-button:not(:-moz-lwtheme):not(:-moz-window-inactive) { + list-style-image: url(chrome://browser/skin/tabbrowser/newtab-inverted.png); + } + + #main-window[darkwindowframe="true"] .tab-close-button:not(:-moz-any(:hover, [selected="true"], :-moz-lwtheme, :-moz-window-inactive)) { + -moz-image-region: rect(0, 64px, 16px, 48px); + } + #toolbar-menubar:not(:-moz-lwtheme) { text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4); } @@ -195,6 +215,7 @@ #main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) { background-color: rgba(255,255,255,.5); + color: black; } @media (-moz-os-version: windows-vista), diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css index 194ef8f9cfb6..9fa953095d21 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css @@ -109,8 +109,8 @@ %endif /* Make the menu inherit the toolbar's color. On non-compositor (Aero Basic, XP modern, classic) - * this is defined above. Otherwise (Aero Glass, Windows 8), this is hardcoded to black in - * browser-aero.css. */ + * this is defined above. Otherwise (Aero Glass, Windows 8 inactive windows), this is hardcoded + * to black in browser-aero.css. */ #main-menubar > menu:not(:-moz-lwtheme) { color: inherit; }