Bug 1352075 - Implement new animation for opening/closing the arrow panels. draft
authorJared Wein <jwein@mozilla.com>
Wed, 05 Jul 2017 14:58:01 -0400
changeset 613430 eb7df6646bb4dca2236e2e8b2bf2f5a8fd00eaf6
parent 613409 a83177668dc2035ff5c6d92a5f93227190583229
child 638675 38c687cb63bc7d2f4b9164bf50b2f7d798ee5148
push id69797
push userbmo:sfoster@mozilla.com
push dateFri, 21 Jul 2017 22:54:05 +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 * 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/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/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;