Bug 1316459 - play range outline animations after its properties have been set as the result of a scheduled repaint of the modal highlighter. r?Gijs draft
authorMike de Boer <mdeboer@mozilla.com>
Mon, 23 Jan 2017 20:13:07 +0100
changeset 465075 97d8c0b61235ba0fa0476b288e6c16ce951098f2
parent 464954 36486fdc3813ef7943ae5b07b4128866d1938a6c
child 543094 f272abbf62b67e7c4921bf192ea48ca1089bc115
push id42539
push usermdeboer@mozilla.com
push dateMon, 23 Jan 2017 19:14:17 +0000
reviewersGijs
bugs1316459
milestone53.0a1
Bug 1316459 - play range outline animations after its properties have been set as the result of a scheduled repaint of the modal highlighter. r?Gijs MozReview-Commit-ID: 4xLHwB0l4ja
toolkit/modules/FinderHighlighter.jsm
toolkit/modules/tests/browser/browser_FinderHighlighter.js
--- a/toolkit/modules/FinderHighlighter.jsm
+++ b/toolkit/modules/FinderHighlighter.jsm
@@ -426,42 +426,30 @@ FinderHighlighter.prototype = {
         if (!dict.visible && !params)
           params = {word: data.searchString, linksOnly: data.linksOnly};
         if (params)
           this.highlight(true, params.word, params.linksOnly);
       }
       return;
     }
 
+    dict.animateOutline = true;
+    // Immediately finish running animations, if any.
+    this._finishOutlineAnimations(dict);
+
     if (foundRange !== dict.currentFoundRange || data.findAgain) {
       dict.previousFoundRange = dict.currentFoundRange;
       dict.currentFoundRange = foundRange;
 
       if (!dict.visible)
         this.show(window);
       else
         this._maybeCreateModalHighlightNodes(window);
     }
 
-    let outlineNode = dict.modalHighlightOutline;
-    if (outlineNode && !this._isPageTooBig(dict)) {
-      let animation;
-      if (dict.animations) {
-        for (animation of dict.animations)
-          animation.finish();
-      }
-      dict.animations = [];
-      for (let i = dict.previousRangeRectsAndTexts.rectList.length - 1; i >= 0; --i) {
-        animation = outlineNode.setAnimationForElement(kModalOutlineId + i,
-          Cu.cloneInto(kModalOutlineAnim.keyframes, window), kModalOutlineAnim.duration);
-        animation.onfinish = function(idx) { dict.animations.splice(idx, 1); }.bind(null, i);
-        dict.animations.push(animation);
-      }
-    }
-
     if (this._highlightAll)
       this.highlight(true, data.searchString, data.linksOnly);
   },
 
   /**
    * Invalidates the list by clearing the map of highlighted ranges that we
    * keep to build the mask for.
    */
@@ -471,20 +459,17 @@ FinderHighlighter.prototype = {
       for (let win of gWindows.keys())
         this.hide(win);
       // Reset the Map, because no range references a node anymore.
       gWindows.clear();
       return;
     }
 
     let dict = this.getForWindow(window.top);
-    if (dict.animations) {
-      for (let animation of dict.animations)
-        animation.finish();
-    }
+    this._finishOutlineAnimations(dict);
     dict.dynamicRangesSet.clear();
     dict.frames.clear();
     dict.modalHighlightRectsMap.clear();
     dict.brightText = null;
   },
 
   /**
    * When the current page is refreshed or navigated away from, the CanvasFrame
@@ -1001,20 +986,45 @@ FinderHighlighter.prototype = {
 
     if (rebuildOutline) {
       dict.modalHighlightOutline = kDebug ?
         mockAnonymousContentNode((document.body ||
           document.documentElement).appendChild(outlineBox)) :
         document.insertAnonymousContent(outlineBox);
     }
 
+    if (dict.animateOutline && !this._isPageTooBig(dict)) {
+      let animation;
+      dict.animations = new Set();
+      for (let i = rectsAndTexts.rectList.length - 1; i >= 0; --i) {
+        animation = dict.modalHighlightOutline.setAnimationForElement(kModalOutlineId + i,
+          Cu.cloneInto(kModalOutlineAnim.keyframes, window), kModalOutlineAnim.duration);
+        animation.onfinish = function() { dict.animations.delete(this); };
+        dict.animations.add(animation);
+      }
+    }
+    dict.animateOutline = false;
+
     dict.previousUpdatedRange = range;
   },
 
   /**
+   * Finish any currently playing animations on the found range outline node.
+   *
+   * @param {Object} dict Dictionary of properties belonging to the currently
+   *                      active window
+   */
+  _finishOutlineAnimations(dict) {
+    if (!dict.animations)
+      return;
+    for (let animation of dict.animations)
+      animation.finish();
+  },
+
+  /**
    * Safely remove the outline AnoymousContent node from the CanvasFrame.
    *
    * @param {nsIDOMWindow} window
    */
   _removeRangeOutline(window) {
     let dict = this.getForWindow(window);
     if (!dict.modalHighlightOutline)
       return;
--- a/toolkit/modules/tests/browser/browser_FinderHighlighter.js
+++ b/toolkit/modules/tests/browser/browser_FinderHighlighter.js
@@ -194,17 +194,17 @@ add_task(function* setup() {
 
 // Test the results of modal highlighting, which is on by default.
 add_task(function* testModalResults() {
   let tests = new Map([
     ["Roland", {
       rectCount: 2,
       insertCalls: [2, 4],
       removeCalls: [0, 1],
-      animationCalls: [5, 6]
+      animationCalls: [1, 2]
     }],
     ["their law might propagate their kind", {
       rectCount: 2,
       insertCalls: [5, 6],
       removeCalls: [4, 5],
       extraTest(maskNode, outlineNode, rects) {
         Assert.equal(outlineNode.getElementsByTagName("div").length, 2,
           "There should be multiple rects drawn");