Bug 940393 - Win8: Text color on inactive tabs makes text very hard to read. r=gijs
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1181,16 +1181,43 @@ var gBrowserInit = {
Cu.reportError("Could not end startup crash tracking: " + ex);
}
if (typeof WindowsPrefSync !== 'undefined') {
// Pulls in Metro controlled prefs and pushes out Desktop controlled prefs
WindowsPrefSync.init();
}
+#ifdef XP_WIN
+ if (window.matchMedia("(-moz-os-version: windows-win8)").matches &&
+ window.matchMedia("(-moz-windows-default-theme)").matches) {
+ 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) {
return;
}
// Enable the Restore Last Session command if needed
RestoreLastSessionObserver.init();
--- a/browser/components/migration/src/IEProfileMigrator.js
+++ b/browser/components/migration/src/IEProfileMigrator.js
@@ -5,27 +5,28 @@
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
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");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource:///modules/MigrationUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
"resource://gre/modules/ctypes.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry",
+ "resource://gre/modules/WindowsRegistry.jsm");
////////////////////////////////////////////////////////////////////////////////
//// Helpers.
let CtypesHelpers = {
_structs: {},
_functions: {},
_libs: {},
@@ -121,55 +122,16 @@ function hostIsIPAddress(aHost) {
try {
Services.eTLD.getBaseDomainFromHost(aHost);
} catch (e if e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
return true;
} catch (e) {}
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
function Bookmarks() {
}
Bookmarks.prototype = {
type: MigrationUtils.resourceTypes.BOOKMARKS,
@@ -187,19 +149,19 @@ Bookmarks.prototype = {
},
__toolbarFolderName: null,
get _toolbarFolderName() {
if (!this.__toolbarFolderName) {
// 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;
},
migrate: function B_migrate(aCallback) {
PlacesUtils.bookmarks.runInBatchMode({
runBatched: (function migrateBatched() {
@@ -600,18 +562,18 @@ Settings.prototype = {
* @param aKey
* Name of the key.
* @param aPref
* Firefox preference.
* @param [optional] aTransformFn
* 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;
if (aTransformFn)
value = aTransformFn(value);
switch (typeof(value)) {
@@ -646,31 +608,31 @@ IEProfileMigrator.prototype.getResources
, new Cookies()
, new Settings()
];
return [r for each (r in resources) if (r.exists)];
};
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.
let homepage = startPage != defaultStartPage ? startPage : "";
// IE7+ supports secondary home pages located in a REG_MULTI_SZ key. These
// 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);
homepage = secondaryPages.join("|");
}
return homepage;
}
new file mode 100644
--- /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://gre/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];
+ },
+};
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -21,16 +21,17 @@ EXTRA_JS_MODULES += [
'Social.jsm',
'TabCrashReporter.jsm',
'WebappManager.jsm',
'webrtcUI.jsm',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXTRA_JS_MODULES += [
+ 'Windows8WindowFrameColor.jsm',
'WindowsJumpLists.jsm',
'WindowsPreviewPerTab.jsm',
]
EXTRA_PP_JS_MODULES += [
'AboutHome.jsm',
'RecentWindow.jsm',
'UITour.jsm',
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -131,16 +131,42 @@
#toolbar-menubar:not(:-moz-lwtheme),
#TabsToolbar:not(:-moz-lwtheme) {
background-color: transparent !important;
color: black;
border-left-style: none !important;
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);
+ }
+
+ #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > #sync-button[status="active"]:not(:-moz-lwtheme),
+ #main-window[darkwindowframe="true"] :-moz-any(#toolbar-menubar, #TabsToolbar) > toolbarpaletteitem > #sync-button[status="active"]:not(:-moz-lwtheme) {
+ list-style-image: url("chrome://browser/skin/syncProgress-toolbar-inverted.png");
+ }
+
+
#toolbar-menubar:not(:-moz-lwtheme) {
text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
}
/* Vertical toolbar border */
#main-window[sizemode=normal] #navigator-toolbox::after,
#main-window[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar) {
border-left: 1px solid @toolbarShadowColor@;
@@ -190,16 +216,17 @@
}
#appcontent:not(:-moz-lwtheme) {
background-color: -moz-dialog;
}
#main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) {
background-color: rgba(255,255,255,.5);
+ color: black;
}
@media (-moz-os-version: windows-vista),
(-moz-os-version: windows-win7) {
#main-window[sizemode=normal] #nav-bar {
border-top-left-radius: 2.5px;
border-top-right-radius: 2.5px;
}
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -104,18 +104,18 @@
-moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
visibility: visible;
}
%ifdef WINDOWS_AERO
}
%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;
}
/**
* In the classic themes, the titlebar has a horizontal gradient, which is
* problematic for reading the text of background tabs when they're in the
* titlebar. We side-step this issue by layering our own background underneath
new file mode 100644
--- /dev/null
+++ b/toolkit/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;
+ },
+};
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -65,13 +65,19 @@ EXTRA_PP_JS_MODULES += [
'WindowsPrefSync.jsm',
]
if 'Android' != CONFIG['OS_TARGET']:
EXTRA_PP_JS_MODULES += [
'LightweightThemeConsumer.jsm',
]
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
+ EXTRA_JS_MODULES += [
+ 'WindowsRegistry.jsm',
+ ]
+
DEFINES['MOZ_APP_NAME'] = CONFIG['MOZ_APP_NAME']
DEFINES['MOZ_BUILD_APP'] = CONFIG['MOZ_BUILD_APP']
if CONFIG['MOZ_TOOLKIT_SEARCH']:
DEFINES['MOZ_TOOLKIT_SEARCH'] = True