Bug 992373 - Items in the panel jump up slightly when the customization transition finishes. r=Gijs, mikedeboer, a=sledru.
authorMike Conley <mconley@mozilla.com>
Wed, 09 Apr 2014 17:37:38 -0400
changeset 183720 7c5fb4327c30413328b2b5b994d7f7a9fcac4a00
parent 183719 5aa6eb09fe62272fdc5293cdcc55476532078354
child 183721 3537a7b4b9924125f3d6f39c4cfb4028b40d590e
push id3458
push usermconley@mozilla.com
push dateSat, 12 Apr 2014 18:03:04 +0000
treeherdermozilla-beta@f1c211a4714d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, mikedeboer, sledru
bugs992373
milestone29.0
Bug 992373 - Items in the panel jump up slightly when the customization transition finishes. r=Gijs, mikedeboer, a=sledru.
browser/components/customizableui/src/CustomizeMode.jsm
browser/components/customizableui/src/DragPositionManager.jsm
browser/themes/shared/customizableui/panelUIOverlay.inc.css
--- a/browser/components/customizableui/src/CustomizeMode.jsm
+++ b/browser/components/customizableui/src/CustomizeMode.jsm
@@ -1598,16 +1598,17 @@ CustomizeMode.prototype = {
     draggedWrapper.hidden = false;
     draggedWrapper.removeAttribute("mousedown");
     if (this._dragOverItem) {
       this._cancelDragActive(this._dragOverItem);
       this._dragOverItem = null;
     }
     this._updateToolbarCustomizationOutline(this.window);
     this._showPanelCustomizationPlaceholders();
+    DragPositionManager.stop();
   },
 
   _isUnwantedDragDrop: function(aEvent) {
     // The simulated events generated by synthesizeDragStart/synthesizeDrop in
     // mochitests are used only for testing whether the right data is being put
     // into the dataTransfer. Neither cause a real drop to occur, so they don't
     // set the source node. There isn't a means of testing real drag and drops,
     // so this pref skips the check but it should only be set by test code.
--- a/browser/components/customizableui/src/DragPositionManager.jsm
+++ b/browser/components/customizableui/src/DragPositionManager.jsm
@@ -327,30 +327,46 @@ AreaPositionManager.prototype = {
    * Get position details from our cache. If the node is not yet cached, get its position
    * information and cache it now.
    * @param aNode  the node whose position info we want
    * @return the position info
    */
   _lazyStoreGet: function(aNode) {
     let rect = this._nodePositionStore.get(aNode);
     if (!rect) {
-      rect = aNode.getBoundingClientRect();
+      // getBoundingClientRect() returns a DOMRect that is live, meaning that
+      // as the element moves around, the rects values change. We don't want
+      // that - we want a snapshot of what the rect values are right at this
+      // moment, and nothing else. So we have to clone the values.
+      let clientRect = aNode.getBoundingClientRect();
+      rect = {
+        left: clientRect.left,
+        right: clientRect.right,
+        width: clientRect.width,
+        height: clientRect.height,
+        top: clientRect.top,
+        bottom: clientRect.bottom,
+      };
       rect.x = rect.left + rect.width / 2;
       rect.y = rect.top + rect.height / 2;
+      Object.freeze(rect);
       this._nodePositionStore.set(aNode, rect);
     }
     return rect;
   },
 
   _firstInRow: function(aNode) {
-    let bound = this._lazyStoreGet(aNode).top;
+    // XXXmconley: I'm not entirely sure why we need to take the floor of these
+    // values - it looks like, periodically, we're getting fractional pixels back
+    //from lazyStoreGet. I've filed bug 994247 to investigate.
+    let bound = Math.floor(this._lazyStoreGet(aNode).top);
     let rv = aNode;
     let prev;
     while (rv && (prev = this._getVisibleSiblingForDirection(rv, "previous"))) {
-      if (this._lazyStoreGet(prev).bottom <= bound) {
+      if (Math.floor(this._lazyStoreGet(prev).bottom) <= bound) {
         return rv;
       }
       rv = prev;
     }
     return rv;
   },
 
   _getVisibleSiblingForDirection: function(aNode, aDirection) {
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -239,17 +239,16 @@ panelview:not([mainview]) .toolbarbutton
 .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton > .toolbarbutton-icon {
   min-width: 0;
   min-height: 0;
   margin: 0;
 }
 
 toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-item),
 .panelUI-grid .toolbarbutton-1,
-toolbarpaletteitem[place="panel"]:not([haswideitem=true]),
 .panel-customization-placeholder-child {
   -moz-appearance: none;
   -moz-box-orient: vertical;
   width: calc(@menuPanelButtonWidth@);
   height: calc(51px + 2.2em);
 }
 
 /* In order to have button labels constrained appropriately, items inside the toolbarpaletteitem
@@ -913,18 +912,22 @@ toolbarpaletteitem[place="palette"] > #s
   border-bottom-color: hsla(210,4%,10%,.1);
   padding: 0;
   transition-property: background-color, border-color;
   transition-duration: 150ms;
 }
 
 /* Make direct siblings overlap borders: */
 .toolbaritem-combined-buttons + .toolbaritem-combined-buttons@inAnyPanel@ {
+  border-top-color: transparent !important;
+}
+
+.toolbaritem-combined-buttons + .toolbaritem-combined-buttons@inAnyPanel@,
+toolbarpaletteitem[haswideitem][place="panel"] + toolbarpaletteitem[haswideitem][place="panel"] {
   margin-top: -1px;
-  border-top-color: transparent !important;
 }
 
 .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton {
   border: 0;
   padding: .5em;
   margin: 0;
   -moz-box-flex: 1;
   min-width: calc(@menuPanelButtonWidth@);