Bug 1266575 - Dispatch click event on <select> after item is selected when in e10s mode. r?felipe
MozReview-Commit-ID: 1AwWW9XwWXu
--- a/toolkit/content/select-child.js
+++ b/toolkit/content/select-child.js
@@ -6,10 +6,12 @@ Components.utils.import("resource://gre/
XPCOMUtils.defineLazyModuleGetter(this, "SelectContentHelper",
"resource://gre/modules/SelectContentHelper.jsm");
addEventListener("mozshowdropdown", event => {
if (!event.isTrusted)
return;
- new SelectContentHelper(event.target, this);
+ if (!SelectContentHelper.open) {
+ new SelectContentHelper(event.target, this);
+ }
});
--- a/toolkit/modules/SelectContentHelper.jsm
+++ b/toolkit/modules/SelectContentHelper.jsm
@@ -14,29 +14,41 @@ XPCOMUtils.defineLazyModuleGetter(this,
"resource://gre/modules/BrowserUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils",
"@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
"resource://gre/modules/DeferredTask.jsm");
const kStateHover = 0x00000004; // NS_EVENT_STATE_HOVER
+// A process global state for whether or not content thinks
+// that a <select> dropdown is open or not. This is managed
+// entirely within this module, and is read-only accessible
+// via SelectContentHelper.open.
+var gOpen = false;
+
this.EXPORTED_SYMBOLS = [
"SelectContentHelper"
];
this.SelectContentHelper = function (aElement, aGlobal) {
this.element = aElement;
this.initialSelection = aElement[aElement.selectedIndex] || null;
this.global = aGlobal;
this.init();
this.showDropDown();
this._updateTimer = new DeferredTask(this._update.bind(this), 0);
}
+Object.defineProperty(SelectContentHelper, "open", {
+ get: function() {
+ return gOpen;
+ },
+});
+
this.SelectContentHelper.prototype = {
init: function() {
this.global.addMessageListener("Forms:SelectDropDownItem", this);
this.global.addMessageListener("Forms:DismissedDropDown", this);
this.global.addMessageListener("Forms:MouseOver", this);
this.global.addMessageListener("Forms:MouseOut", this);
this.global.addEventListener("pagehide", this);
this.global.addEventListener("mozhidedropdown", this);
@@ -57,27 +69,28 @@ this.SelectContentHelper.prototype = {
this.global.removeMessageListener("Forms:MouseOut", this);
this.global.removeEventListener("pagehide", this);
this.global.removeEventListener("mozhidedropdown", this);
this.element = null;
this.global = null;
this.mut.disconnect();
this._updateTimer.disarm();
this._updateTimer = null;
+ gOpen = false;
},
showDropDown: function() {
let rect = this._getBoundingContentRect();
-
this.global.sendAsyncMessage("Forms:ShowDropDown", {
rect: rect,
options: this._buildOptionList(),
selectedIndex: this.element.selectedIndex,
direction: getComputedDirection(this.element)
});
+ gOpen = true;
},
_getBoundingContentRect: function() {
return BrowserUtils.getElementBoundingScreenRect(this.element);
},
_buildOptionList: function() {
return buildOptionListForChildren(this.element);
@@ -95,19 +108,32 @@ this.SelectContentHelper.prototype = {
receiveMessage: function(message) {
switch (message.name) {
case "Forms:SelectDropDownItem":
this.element.selectedIndex = message.data.value;
break;
case "Forms:DismissedDropDown":
if (this.initialSelection != this.element.item(this.element.selectedIndex)) {
- let event = this.element.ownerDocument.createEvent("Events");
- event.initEvent("change", true, true);
- this.element.dispatchEvent(event);
+ let win = this.element.ownerDocument.defaultView;
+ let inputEvent = new win.UIEvent("input", {
+ bubbles: true,
+ });
+ this.element.dispatchEvent(inputEvent);
+
+ let changeEvent = new win.Event("change", {
+ bubbles: true,
+ });
+ this.element.dispatchEvent(changeEvent);
+
+ let dwu = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ let rect = this.element.getBoundingClientRect();
+ dwu.sendMouseEvent("mousedown", rect.left, rect.top, 0, 1, 0, true);
+ dwu.sendMouseEvent("mouseup", rect.left, rect.top, 0, 1, 0, true);
}
this.uninit();
break;
case "Forms:MouseOver":
DOMUtils.setContentState(this.element, kStateHover);
break;