Bug 1352075 - Implement new animation for opening/closing the arrow panels. draft
authorSam Foster <sfoster@mozilla.com>
Wed, 05 Jul 2017 14:58:01 -0400
changeset 613441 3b4d8015d8899e695331ad81c5faf23feb7ff8ae
parent 613409 a83177668dc2035ff5c6d92a5f93227190583229
child 638679 88deb6c236bca53864a72e1a6089c13c862a8a1f
push id69801
push userbmo:sfoster@mozilla.com
push dateFri, 21 Jul 2017 23:22:58 +0000
bugs1352075
milestone56.0a1
Bug 1352075 - Implement new animation for opening/closing the arrow panels. * Use new panel animation when opening arrow-panels (including bookmarks menu) to fade in and drop into position * Make animation of bookmarks menu conditional on an animate attribute != "false" like arrowpanel binding * Wait for popupshown rather than transitionend in bookmark reparenting test * Linux/GTK is (still) excluded * The same element has its opacity and transform properties animated as before, so it doesnt change fundamentally * Add animating attribute to the panel to disable pointer-events during the transition (via :jaws) * Fix specificity of CSS rules for panels/bookmarks-menu on edges other than the top (via :jaws) * New animation is non-directional (i.e. LTR vs. RTL) MozReview-Commit-ID: JczH72gq2g1
browser/base/content/browser-places.js
browser/base/content/browser.css
browser/components/customizableui/test/browser_984455_bookmarks_items_reparenting.js
browser/components/places/content/menu.xml
toolkit/content/xul.css
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -28,17 +28,19 @@ var StarUI = {
     element.addEventListener("keypress", this);
     element.addEventListener("mousedown", this);
     element.addEventListener("mouseout", this);
     element.addEventListener("mousemove", this);
     element.addEventListener("compositionstart", this);
     element.addEventListener("compositionend", this);
     element.addEventListener("input", this);
     element.addEventListener("popuphidden", this);
+    element.addEventListener("popupshowing", this);
     element.addEventListener("popupshown", this);
+    element.addEventListener("transitionend", this);
     return this.panel = element;
   },
 
   // Array of command elements to disable when the panel is opened.
   get _blockedCommands() {
     delete this._blockedCommands;
     return this._blockedCommands =
       ["cmd_close", "cmd_closeWindow"].map(id => this._element(id));
@@ -191,16 +193,27 @@ var StarUI = {
           this._autoCloseTimer = setTimeout(() => {
             if (!this.panel.mozMatchesSelector(":hover")) {
               this.panel.hidePopup();
             }
           }, delay);
           this._autoCloseTimerEnabled = true;
         }
         break;
+      case "popupshowing":
+        if (Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
+          this.panel.setAttribute("animating", "true");
+        }
+        break;
+      case "transitionend":
+        if (aEvent.propertyName == "transform" &&
+            aEvent.target == this.panel) {
+          this.panel.removeAttribute("animating");
+        }
+        break;
     }
   },
 
   _overlayLoaded: false,
   _overlayLoading: false,
   async showEditBookmarkPopup(aNode, aAnchorElement, aPosition, aIsNewBookmark) {
     // Slow double-clicks (not true double-clicks) shouldn't
     // cause the panel to flicker.
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1119,26 +1119,82 @@ toolbarpaletteitem[place="palette"] > #d
   -moz-appearance: none;
   -moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
   background: transparent;
   border: none;
   /* The popup inherits -moz-image-region from the button, must reset it */
   -moz-image-region: auto;
 }
 
+%ifdef MOZ_PHOTON_ANIMATIONS
 %ifdef MOZ_WIDGET_COCOA
 
 /* On Mac, use the properties "-moz-window-transform" and "-moz-window-opacity"
    instead of "transform" and "opacity" for these animations.
    The -moz-window* properties apply to the whole window including the window's
    shadow, and they don't affect the window's "shape", so the system doesn't
    have to recompute the shadow shape during the animation. This makes them a
    lot faster. In fact, Gecko no longer triggers shadow shape recomputations
    for repaints.
    These properties are not implemented on other platforms. */
+#BMB_bookmarksPopup:not([animate="false"]) {
+  -moz-window-opacity: 0;
+  -moz-window-transform: translateY(-70px);
+  transition-property: -moz-window-transform, -moz-window-opacity;
+  transition-duration: 0.18s, 0.18s;
+  transition-timing-function:
+    var(--animation-easing-function), ease-out;
+}
+
+#BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
+  -moz-window-transform: translateY(70px);
+}
+
+#BMB_bookmarksPopup[side][animate="open"] {
+  -moz-window-opacity: 1.0;
+  transition-duration: 0.20s, 0.10s;
+  -moz-window-transform: none;
+  transition-timing-function:
+    var(--animation-easing-function), ease-in-out;
+}
+
+#BMB_bookmarksPopup[animate="cancel"] {
+  -moz-window-transform: none;
+}
+
+%elifndef MOZ_WIDGET_GTK
+
+#BMB_bookmarksPopup:not([animate="false"]) {
+  opacity: 0;
+  transform: translateY(-70px);
+  transition-property: transform, opacity;
+  transition-duration: 0.18s, 0.18s;
+  transition-timing-function:
+    var(--animation-easing-function), ease-out;
+}
+
+#BMB_bookmarksPopup[side="bottom"]:not([animate="false"]) {
+  transform: translateY(70px);
+}
+
+#BMB_bookmarksPopup[side][animate="open"] {
+  opacity: 1.0;
+  transition-duration: 0.20s, 0.10s;
+  transform: none;
+  transition-timing-function:
+    var(--animation-easing-function), ease-in-out;
+}
+
+#BMB_bookmarksPopup[animate="cancel"] {
+  transform: none;
+}
+%endif
+
+%else
+%ifdef MOZ_WIDGET_COCOA
 #BMB_bookmarksPopup {
   -moz-window-transform: scale(.4);
   -moz-window-opacity: 0;
   transition-property: -moz-window-transform, -moz-window-opacity;
   transition-duration: 0.15s;
   transition-timing-function: ease-out;
 }
 
@@ -1205,16 +1261,17 @@ toolbarpaletteitem[place="palette"] > #d
   transform-origin: 20px bottom;
 }
 
 #BMB_bookmarksPopup[arrowposition="before_end"]:-moz-locale-dir(ltr),
 #BMB_bookmarksPopup[arrowposition="before_start"]:-moz-locale-dir(rtl) {
   transform-origin: calc(100% - 20px) bottom;
 }
 %endif
+%endif
 
 /* Customize mode */
 %ifndef MOZ_PHOTON_THEME
 #navigator-toolbox,
 #browser-bottombox,
 #content-deck {
   transition-property: margin-left, margin-right;
   transition-duration: 200ms;
--- a/browser/components/customizableui/test/browser_984455_bookmarks_items_reparenting.js
+++ b/browser/components/customizableui/test/browser_984455_bookmarks_items_reparenting.js
@@ -14,23 +14,23 @@ const kSmallWidth = 400;
 
 /**
  * Helper function that opens the bookmarks menu, and returns a Promise that
  * resolves as soon as the menu is ready for interaction.
  */
 function bookmarksMenuPanelShown() {
   return new Promise(resolve => {
     let bookmarksMenuPopup = document.getElementById("BMB_bookmarksPopup");
-    let onTransitionEnd = (e) => {
+    let onPopupShown = (e) => {
       if (e.target == bookmarksMenuPopup) {
-        bookmarksMenuPopup.removeEventListener("transitionend", onTransitionEnd);
+        bookmarksMenuPopup.removeEventListener("popupshown", onPopupShown);
         resolve();
       }
     }
-    bookmarksMenuPopup.addEventListener("transitionend", onTransitionEnd);
+    bookmarksMenuPopup.addEventListener("popupshown", onPopupShown);
   });
 }
 
 /**
  * Checks that the placesContext menu is correctly attached to the
  * controller of some view. Returns a Promise that resolves as soon
  * as the context menu is closed.
  *
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -573,16 +573,26 @@
 
           arrow.hidden = false;
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="popupshowing" phase="target"><![CDATA[
+        let prefsService = Components.classes["@mozilla.org/preferences-service;1"]
+                              .getService(Components.interfaces.nsIPrefBranch);
+        let animationsEnabled = prefsService.getBoolPref("toolkit.cosmeticAnimations.enabled");
+        if (!animationsEnabled) {
+          this._previousAnimateAttrValue = this.getAttribute("animate");
+          this.setAttribute("animate", "false");
+        } else {
+          this._previousAnimateAttrValue = null;
+        }
+
         this.adjustArrowPosition();
         this.setAttribute("animate", "open");
       ]]></handler>
       <handler event="popupshown" phase="target"><![CDATA[
         this.setAttribute("panelopen", "true");
         let disablePointerEvents;
         if (!this.hasAttribute("disablepointereventsfortransition")) {
           let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
@@ -609,13 +619,17 @@
       <handler event="popuphiding" phase="target"><![CDATA[
         this.setAttribute("animate", "cancel");
       ]]></handler>
       <handler event="popuphidden" phase="target"><![CDATA[
         this.removeAttribute("panelopen");
         if (this.getAttribute("disablepointereventsfortransition") == "true") {
           this.style.pointerEvents = "none";
         }
-        this.removeAttribute("animate");
+        if (this._previousAnimateAttrValue == "false") {
+          this.setAttribute("animate", this._previousAnimateAttrValue);
+        } else {
+          this.removeAttribute("animate");
+        }
       ]]></handler>
     </handlers>
   </binding>
 </bindings>
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -436,27 +436,88 @@ tooltip {
   white-space: pre-wrap;
   margin-top: 21px;
 }
 
 panel[type="arrow"] {
   -moz-binding: url("chrome://global/content/bindings/popup.xml#arrowpanel");
 }
 
+%ifdef MOZ_PHOTON_ANIMATIONS
 %ifdef MOZ_WIDGET_COCOA
 
 /* On Mac, use the properties "-moz-window-transform" and "-moz-window-opacity"
    instead of "transform" and "opacity" for these animations.
    The -moz-window* properties apply to the whole window including the window's
    shadow, and they don't affect the window's "shape", so the system doesn't
    have to recompute the shadow shape during the animation. This makes them a
    lot faster. In fact, Gecko no longer triggers shadow shape recomputations
    for repaints.
    These properties are not implemented on other platforms. */
 panel[type="arrow"]:not([animate="false"]) {
+  -moz-window-opacity: 0;
+  -moz-window-transform: translateY(-70px);
+  transition-property: -moz-window-transform, -moz-window-opacity;
+  transition-duration: 0.18s, 0.18s;
+  transition-timing-function:
+    var(--animation-easing-function), ease-out;
+}
+
+panel[type="arrow"][side="bottom"]:not([animate="false"]) {
+  -moz-window-transform: translateY(70px);
+}
+
+panel[type="arrow"][side][animate="open"] {
+  -moz-window-opacity: 1.0;
+  transition-duration: 0.20s, 0.10s;
+  -moz-window-transform: none;
+  transition-timing-function:
+    var(--animation-easing-function), ease-in-out;
+}
+
+panel[type="arrow"][animate="cancel"] {
+  -moz-window-transform: none;
+}
+
+%elifndef MOZ_WIDGET_GTK
+
+panel[type="arrow"]:not([animate="false"]) {
+  opacity: 0;
+  transform: translateY(-70px);
+  transition-property: transform, opacity;
+  transition-duration: 0.18s, 0.18s;
+  transition-timing-function:
+    var(--animation-easing-function), ease-out;
+}
+
+panel[type="arrow"][side="bottom"]:not([animate="false"]) {
+  transform: translateY(70px);
+}
+
+panel[type="arrow"][side][animate="open"] {
+  opacity: 1.0;
+  transition-duration: 0.20s, 0.10s;
+  transform: none;
+  transition-timing-function:
+    var(--animation-easing-function), ease-in-out;
+}
+
+panel[type="arrow"][animate="cancel"] {
+  transform: none;
+}
+
+%endif
+panel[type="arrow"][animating] {
+  pointer-events: none;
+}
+
+%else
+
+%ifdef MOZ_WIDGET_COCOA
+panel[type="arrow"]:not([animate="false"]) {
   -moz-window-transform: scale(.4);
   -moz-window-opacity: 0;
   transition-property: -moz-window-transform, -moz-window-opacity;
   transition-duration: 0.15s;
   transition-timing-function: ease-out;
 }
 
 panel[type="arrow"][animate="open"] {
@@ -563,16 +624,17 @@ panel[arrowposition="start_before"]:-moz
 }
 
 panel[arrowposition="end_after"]:-moz-locale-dir(ltr),
 panel[arrowposition="start_after"]:-moz-locale-dir(rtl) {
   transform-origin: left calc(100% - 20px);
 }
 
 %endif
+%endif
 
 %ifdef XP_MACOSX
 .statusbar-resizerpanel {
   display: none;
 }
 %else
 window[sizemode="maximized"] statusbarpanel.statusbar-resizerpanel {
   visibility: collapse;