Index: ui/webui/resources/js/cr/ui/menu.js |
diff --git a/ui/webui/resources/js/cr/ui/menu.js b/ui/webui/resources/js/cr/ui/menu.js |
index d54f5430f855a9239caaa9ba9af714054acae0db..abcb79c71906f6a6fb1f83f7617f183d54699281 100644 |
--- a/ui/webui/resources/js/cr/ui/menu.js |
+++ b/ui/webui/resources/js/cr/ui/menu.js |
@@ -32,6 +32,7 @@ cr.define('cr.ui', function() { |
decorate: function() { |
this.addEventListener('mouseover', this.handleMouseOver_); |
this.addEventListener('mouseout', this.handleMouseOut_); |
+ this.addEventListener('mouseup', this.handleMouseUp_, true); |
this.classList.add('decorated'); |
this.setAttribute('role', 'menu'); |
@@ -113,6 +114,37 @@ cr.define('cr.ui', function() { |
this.selectedItem = null; |
}, |
+ /** |
+ * If there's a mouseup that happens quickly in about the same position, |
+ * stop it from propagating to items. This is to prevent accidentally |
+ * selecting a menu item that's created under the mouse cursor. |
+ * @param {Event} e A mouseup event on the menu (in capturing phase). |
+ * @private |
+ */ |
+ handleMouseUp_: function(e) { |
+ assert(this.contains(/** @type {Element} */(e.target))); |
+ |
+ if (!this.trustEvent_(e) || Date.now() - this.shown_.time > 200) |
+ return; |
+ |
+ var pos = this.shown_.mouseDownPos; |
+ if (!pos || Math.abs(pos.x - e.screenX) + Math.abs(pos.y - e.screenY) > 4) |
+ return; |
+ |
+ e.preventDefault(); |
+ e.stopPropagation(); |
+ }, |
+ |
+ /** |
+ * @param {!Event} e |
+ * @return {boolean} Whether |e| can be trusted. |
+ * @private |
+ * @suppress {checkTypes} |
+ */ |
+ trustEvent_: function(e) { |
+ return e.isTrusted || e.isTrustedForTesting; |
+ }, |
+ |
get menuItems() { |
return this.querySelectorAll(this.menuItemSelector || '*'); |
}, |
@@ -238,6 +270,17 @@ cr.define('cr.ui', function() { |
return false; |
}, |
+ hide: function() { |
+ this.hidden = true; |
+ delete this.shown_; |
+ }, |
+ |
+ /** @param {{x: number, y: number}=} opt_mouseDownPos */ |
+ show: function(opt_mouseDownPos) { |
+ this.shown_ = {mouseDownPos: opt_mouseDownPos, time: Date.now()}; |
+ this.hidden = false; |
+ }, |
+ |
/** |
* Updates menu items command according to context. |
* @param {Node=} node Node for which to actuate commands state. |