Bug 1338283 - Use the actual menupopup system colors to determine if the popup should be showing custom styles.
MozReview-Commit-ID: 7AAZNCMVZky
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -1076,18 +1076,16 @@
if (!this._selectParentHelper) {
this._selectParentHelper =
Cu.import("resource://gre/modules/SelectParentHelper.jsm", {}).SelectParentHelper;
}
let menulist = document.getElementById(this.getAttribute("selectmenulist"));
menulist.menupopup.style.direction = data.direction;
this._selectParentHelper.populate(menulist, data.options, data.selectedIndex, this._fullZoom,
- data.uaBackgroundColor, data.uaColor,
- data.uaSelectBackgroundColor, data.uaSelectColor,
data.selectBackgroundColor, data.selectColor);
this._selectParentHelper.open(this, menulist, data.rect, data.isOpenedViaTouch);
break;
}
case "Forms:HideDropDown": {
if (this._selectParentHelper) {
let menulist = document.getElementById(this.getAttribute("selectmenulist"));
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -467,19 +467,17 @@
}
let menulist = document.getElementById(this.getAttribute("selectmenulist"));
menulist.menupopup.style.direction = data.direction;
let zoom = Services.prefs.getBoolPref("browser.zoom.full") ||
this.isSyntheticDocument ? this._fullZoom : this._textZoom;
this._selectParentHelper.populate(menulist, data.options, data.selectedIndex,
- zoom, data.uaBackgroundColor, data.uaColor,
- data.uaSelectBackgroundColor, data.uaSelectColor,
- data.selectBackgroundColor, data.selectColor);
+ zoom, data.selectBackgroundColor, data.selectColor);
this._selectParentHelper.open(this, menulist, data.rect, data.isOpenedViaTouch);
break;
}
case "FullZoomChange": {
this._fullZoom = data.value;
let event = document.createEvent("Events");
event.initEvent("FullZoomChange", true, false);
--- a/toolkit/modules/SelectContentHelper.jsm
+++ b/toolkit/modules/SelectContentHelper.jsm
@@ -33,20 +33,16 @@ this.EXPORTED_SYMBOLS = [
this.SelectContentHelper = function(aElement, aOptions, aGlobal) {
this.element = aElement;
this.initialSelection = aElement[aElement.selectedIndex] || null;
this.global = aGlobal;
this.closedWithEnter = false;
this.isOpenedViaTouch = aOptions.isOpenedViaTouch;
this._selectBackgroundColor = null;
this._selectColor = null;
- this._uaBackgroundColor = null;
- this._uaColor = null;
- this._uaSelectBackgroundColor = null;
- this._uaSelectColor = null;
this.init();
this.showDropDown();
this._updateTimer = new DeferredTask(this._update.bind(this), 0);
}
Object.defineProperty(SelectContentHelper, "open", {
get() {
return gOpen;
@@ -100,20 +96,16 @@ this.SelectContentHelper.prototype = {
this.global.sendAsyncMessage("Forms:ShowDropDown", {
direction: computedStyles.direction,
isOpenedViaTouch: this.isOpenedViaTouch,
options: this._buildOptionList(),
rect,
selectedIndex: this.element.selectedIndex,
selectBackgroundColor: this._selectBackgroundColor,
selectColor: this._selectColor,
- uaBackgroundColor: this.uaBackgroundColor,
- uaColor: this.uaColor,
- uaSelectBackgroundColor: this.uaSelectBackgroundColor,
- uaSelectColor: this.uaSelectColor
});
gOpen = true;
},
_getBoundingContentRect() {
return BrowserUtils.getElementBoundingScreenRect(this.element);
},
@@ -124,69 +116,19 @@ this.SelectContentHelper.prototype = {
_update() {
// The <select> was updated while the dropdown was open.
// Let's send up a new list of options.
this.global.sendAsyncMessage("Forms:UpdateDropDown", {
options: this._buildOptionList(),
selectedIndex: this.element.selectedIndex,
selectBackgroundColor: this._selectBackgroundColor,
selectColor: this._selectColor,
- uaBackgroundColor: this.uaBackgroundColor,
- uaColor: this.uaColor,
- uaSelectBackgroundColor: this.uaSelectBackgroundColor,
- uaSelectColor: this.uaSelectColor
});
},
- // Determine user agent background-color and color.
- // This is used to skip applying the custom color if it matches
- // the user agent values.
- _calculateUAColors() {
- let dummyOption = this.element.ownerDocument.createElement("option");
- dummyOption.style.color = "-moz-comboboxtext";
- dummyOption.style.backgroundColor = "-moz-combobox";
- let optionCS = this.element.ownerGlobal.getComputedStyle(dummyOption);
- this._uaBackgroundColor = optionCS.backgroundColor;
- this._uaColor = optionCS.color;
- let dummySelect = this.element.ownerDocument.createElement("select");
- dummySelect.style.color = "-moz-fieldtext";
- dummySelect.style.backgroundColor = "-moz-field";
- let selectCS = this.element.ownerGlobal.getComputedStyle(dummySelect);
- this._uaSelectBackgroundColor = selectCS.backgroundColor;
- this._uaSelectColor = selectCS.color;
- },
-
- get uaBackgroundColor() {
- if (!this._uaBackgroundColor) {
- this._calculateUAColors();
- }
- return this._uaBackgroundColor;
- },
-
- get uaColor() {
- if (!this._uaColor) {
- this._calculateUAColors();
- }
- return this._uaColor;
- },
-
- get uaSelectBackgroundColor() {
- if (!this._selectBackgroundColor) {
- this._calculateUAColors();
- }
- return this._uaSelectBackgroundColor;
- },
-
- get uaSelectColor() {
- if (!this._selectBackgroundColor) {
- this._calculateUAColors();
- }
- return this._uaSelectColor;
- },
-
dispatchMouseEvent(win, target, eventName) {
let mouseEvent = new win.MouseEvent(eventName, {
view: win,
bubbles: true,
cancelable: true,
});
target.dispatchEvent(mouseEvent);
},
--- a/toolkit/modules/SelectParentHelper.jsm
+++ b/toolkit/modules/SelectParentHelper.jsm
@@ -18,20 +18,66 @@ const MAX_ROWS = 20;
// Minimum elements required to show select search
const SEARCH_MINIMUM_ELEMENTS = 40;
var currentBrowser = null;
var currentMenulist = null;
var currentZoom = 1;
var closedWithEnter = false;
var selectRect;
+var uaColors = {
+ "menupopup": {
+ get backgroundColor() {
+ let value = AppConstants.platform == "win" ? "-moz-field" : "menu";
+ return calculateUAColors("menupopup", "backgroundColor", value);
+ },
+ get color() {
+ return calculateUAColors("menupopup", "color", "menutext");
+ }
+ },
+ "menucaption": {
+ get backgroundColor() {
+ let value = AppConstants.platform == "win" ? "buttonface" : "-moz-combobox";
+ return calculateUAColors("menucaption", "backgroundColor", value);
+ },
+ get color() {
+ return calculateUAColors("menucaption", "color", "-moz-fieldtext");
+ }
+ },
+ "menuitem": {
+ get backgroundColor() {
+ return calculateUAColors("menuitem", "backgroundColor", "-moz-combobox");
+ },
+ get color() {
+ return calculateUAColors("menuitem", "color", "-moz-comboboxtext");
+ }
+ }
+};
+
+// Determine user agent background-color and color.
+// This is used to skip applying the custom color if it matches
+// the user agent values.
+function calculateUAColors(tagName, property, value) {
+ if (!currentMenulist) {
+ return null;
+ }
+ let document = currentMenulist.ownerDocument;
+ let window = currentMenulist.ownerGlobal;
+ let element = document.createElement(tagName);
+ element.style[property] = value;
+ let cs = window.getComputedStyle(element);
+ delete uaColors[tagName][property];
+ return uaColors[tagName][property] = cs[property];
+}
this.SelectParentHelper = {
- populate(menulist, items, selectedIndex, zoom, uaBackgroundColor, uaColor,
- uaSelectBackgroundColor, uaSelectColor, selectBackgroundColor, selectColor) {
+ populate(menulist, items, selectedIndex, zoom, selectBackgroundColor, selectColor) {
+ currentZoom = zoom;
+ currentMenulist = menulist;
+
// Clear the current contents of the popup
menulist.menupopup.textContent = "";
let stylesheet = menulist.querySelector("#ContentSelectDropdownScopedStylesheet");
if (stylesheet) {
stylesheet.remove();
}
let doc = menulist.ownerDocument;
@@ -39,42 +85,39 @@ this.SelectParentHelper = {
stylesheet.setAttribute("id", "ContentSelectDropdownScopedStylesheet");
stylesheet.scoped = true;
stylesheet.hidden = true;
stylesheet = menulist.appendChild(stylesheet);
let sheet = stylesheet.sheet;
let ruleBody = "";
- if (selectBackgroundColor != uaSelectBackgroundColor &&
+ if (selectBackgroundColor != uaColors.menupopup.backgroundColor &&
selectBackgroundColor != "transparent" &&
selectBackgroundColor != selectColor) {
ruleBody = `background-color: ${selectBackgroundColor};`;
}
- if (selectColor != uaSelectColor &&
+ if (selectColor != uaColors.menupopup.color &&
selectColor != selectBackgroundColor &&
(selectBackgroundColor != "transparent" ||
- selectColor != uaSelectBackgroundColor)) {
+ selectColor != uaColors.menupopup.backgroundColor)) {
ruleBody += `color: ${selectColor};`;
}
if (ruleBody) {
sheet.insertRule(`menupopup {
${ruleBody}
}`, 0);
menulist.menupopup.setAttribute("customoptionstyling", "true");
} else {
menulist.menupopup.removeAttribute("customoptionstyling");
}
- currentZoom = zoom;
- currentMenulist = menulist;
- populateChildren(menulist, items, selectedIndex, zoom,
- uaBackgroundColor, uaColor, sheet);
+ populateChildren(menulist, items, selectedIndex, zoom, sheet);
},
open(browser, menulist, rect, isOpenedViaTouch) {
menulist.hidden = false;
currentBrowser = browser;
closedWithEnter = false;
selectRect = rect;
this._registerListeners(browser, menulist.menupopup);
@@ -173,23 +216,20 @@ this.SelectParentHelper = {
// Sanity check - we'd better know what the currently
// opened menulist is, and what browser it belongs to...
if (!currentMenulist || !currentBrowser) {
return;
}
let options = msg.data.options;
let selectedIndex = msg.data.selectedIndex;
- let uaBackgroundColor = msg.data.uaBackgroundColor;
- let uaColor = msg.data.uaColor;
let selectBackgroundColor = msg.data.selectBackgroundColor;
let selectColor = msg.data.selectColor;
this.populate(currentMenulist, options, selectedIndex,
- currentZoom, uaBackgroundColor, uaColor,
- selectBackgroundColor, selectColor);
+ currentZoom, selectBackgroundColor, selectColor);
}
},
_registerListeners(browser, popup) {
popup.addEventListener("command", this);
popup.addEventListener("popuphidden", this);
popup.addEventListener("mouseover", this);
popup.addEventListener("mouseout", this);
@@ -207,18 +247,17 @@ this.SelectParentHelper = {
browser.ownerGlobal.removeEventListener("mouseup", this, true);
browser.ownerGlobal.removeEventListener("keydown", this, true);
browser.ownerGlobal.removeEventListener("fullscreen", this, true);
browser.messageManager.removeMessageListener("Forms:UpdateDropDown", this);
},
};
-function populateChildren(menulist, options, selectedIndex, zoom,
- uaBackgroundColor, uaColor, sheet,
+function populateChildren(menulist, options, selectedIndex, zoom, sheet,
parentElement = null, isGroupDisabled = false,
adjustedTextSize = -1, addSearch = true, nthChildIndex = 1) {
let element = menulist.menupopup;
let win = element.ownerGlobal;
// -1 just means we haven't calculated it yet. When we recurse through this function
// we will pass in adjustedTextSize to save on recalculations.
if (adjustedTextSize == -1) {
@@ -240,22 +279,22 @@ function populateChildren(menulist, opti
// Keep track of which options are hidden by page content, so we can avoid showing
// them on search input
item.hiddenByContent = item.hidden;
item.setAttribute("tooltiptext", option.tooltip);
let ruleBody = "";
if (option.backgroundColor &&
option.backgroundColor != "transparent" &&
- option.backgroundColor != uaBackgroundColor) {
+ option.backgroundColor != uaColors.menuitem.backgroundColor) {
ruleBody = `background-color: ${option.backgroundColor};`;
}
if (option.color &&
- option.color != uaColor) {
+ option.color != uaColors.menuitem.color) {
ruleBody += `color: ${option.color};`;
}
if (ruleBody) {
sheet.insertRule(`${item.localName}:nth-child(${nthChildIndex}):not([_moz-menuactive="true"]) {
${ruleBody}
}`, 0);
@@ -271,18 +310,17 @@ function populateChildren(menulist, opti
let isDisabled = isGroupDisabled || option.disabled;
if (isDisabled) {
item.setAttribute("disabled", "true");
}
if (isOptGroup) {
nthChildIndex =
populateChildren(menulist, option.children, selectedIndex, zoom,
- uaBackgroundColor, uaColor, sheet,
- item, isDisabled, adjustedTextSize, false);
+ sheet, item, isDisabled, adjustedTextSize, false);
} else {
if (option.index == selectedIndex) {
// We expect the parent element of the popup to be a <xul:menulist> that
// has the popuponly attribute set to "true". This is necessary in order
// for a <xul:menupopup> to act like a proper <html:select> dropdown, as
// the <xul:menulist> does things like remember state and set the
// _moz-menuactive attribute on the selected <xul:menuitem>.
menulist.selectedItem = item;