Bug 1018255 - Make the translation (in the direction of overscroll) more pronounced than the zoom. r=kats
authorBotond Ballo <botond@mozilla.com>
Tue, 03 Jun 2014 18:03:55 -0400
changeset 207624 05ce4d3cf94e8f03e81569340337122802d096c0
parent 207623 1495e351283ef0d3474f7bfc2835fcfa61ae6890
child 207625 77d99630aa73cd53c7b40ab1b9eae6db7f9a1487
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1018255
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1018255 - Make the translation (in the direction of overscroll) more pronounced than the zoom. r=kats
b2g/app/b2g.js
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/thebes/gfxPrefs.h
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -953,16 +953,18 @@ pref("apz.enlarge_displayport_when_clipp
 // Use "sticky" axis locking
 pref("apz.axis_lock_mode", 2);
 pref("apz.subframe.enabled", true);
 
 // Overscroll-related settings
 pref("apz.overscroll.enabled", false);
 pref("apz.overscroll.fling_friction", "0.02");
 pref("apz.overscroll.fling_stopped_threshold", "0.4");
+pref("apz.overscroll.clamping", "0.5");
+pref("apz.overscroll.z_effect", "0.2");
 pref("apz.overscroll.snap_back_accel", "0.003");
 pref("apz.overscroll.snap_back_init_vel", "1");
 
 // This preference allows FirefoxOS apps (and content, I think) to force
 // the use of software (instead of hardware accelerated) 2D canvases by
 // creating a context like this:
 //
 //   canvas.getContext('2d', { willReadFrequently: true })
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -219,16 +219,27 @@ typedef GeckoContentController::APZState
  * "apz.overscroll.fling_friction"
  * Amount of friction applied during flings when in overscroll.
  *
  * "apz.overscroll.fling_stopped_threshold"
  * When flinging in an overscrolled state, if the velocity goes below this
  * number, we stop the fling.
  * Units: screen pixels per millisecond
  *
+ * "apz.overscroll.clamping"
+ * The maximum proportion of the composition bounds which can become blank
+ * as a result of overscroll, along the axis of overscroll.
+ *
+ * "apz.overscroll.z_effect"
+ * The fraction of "apz.overscroll.clamping" which can become blank as a result
+ * of overscroll, along the axis opposite to the axis of overscroll. Called
+ * "z_effect" because the shrinking that brings about the blank space on the
+ * opposite axis creates the effect of the page moving away from you along a
+ * "z" axis.
+ *
  * "apz.overscroll.snap_back_accel"
  * Amount of acceleration applied during the snap-back animation.
  *
  * "apz.overscroll.snap_back_init_vel"
  * Initial velocity of a snap-back animation along one axis.
  * Units: screen pixels per millisecond
  * requests.
  *
@@ -1832,96 +1843,102 @@ bool AsyncPanZoomController::UpdateAnima
     mLastSampleTime = aSampleTime;
     return true;
   }
   return false;
 }
 
 void AsyncPanZoomController::ApplyOverscrollEffect(ViewTransform* aTransform) const {
   // The overscroll effect applied here is a combination of a translation in
-  // the direction of overscroll, and shrinking in both directions. For
-  // example, when overscrolling past the top of the page, the rectangle of
-  // content that filled the composition bounds will now fill a smaller
-  // rectangle at the bottom of the composition bounds, centred horizontally.
-  // The magnitude of the translation and the shrinking depends on the amount
-  // of the overscroll.
+  // the direction of overscroll, and shrinking in both directions.
   // With the effect applied, we can think of the composited region as being
   // made up of the following subregions.
-  //  (1) The shrunk content that used to fill the composited region.
+  //  (1) The shrunk content (or a portion of it) that used to fill the
+  //      composited region.
   //  (2) The space created along the axis that has overscroll. This space is
   //      blank, filled by the background color of the overscrolled content.
   //      TODO(botond): Implement handling of background color.
   //  (3) The space created along the other axis. There may or may not be
   //      content available to fill this space, depending on our scroll
   //      position along this axis. If there is content, it's shown from the
   //      displayport. (TODO: Currently we don't take any measures to ensure
   //      that the displayport is large enough to have this content. Perhaps
   //      we should.) Otherwise, these spaces are also blank like (2).
   // To illustrate, for the case where we are overscrolling past the top of
   // the page, these regions are (1) the bottom-centre region, (2) the top
   // regions, and (3) the bottom-left and bottom-right regions of the
   // composited area, respectively.
 
   // The maximum proportion of the composition length which can become blank
   // space along an axis as we overscroll along that axis.
-  const float CLAMPING = 0.5;
+  const float kClamping = gfxPrefs::APZOverscrollClamping();
 
   // The proportion of the composition length which will become blank space
   // along each axis as a result of overscroll along that axis. Since
   // Axis::ApplyResistance() keeps the magnitude of the overscroll in the range
   // [0, GetCompositionLength()], these scale factors should be in the range
-  // [0, CLAMPING].
-  float spacePropX = CLAMPING * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
-  float spacePropY = CLAMPING * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
+  // [0, kClamping].
+  float spacePropX = kClamping * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
+  float spacePropY = kClamping * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
+
+  // The fraction of the proportions above which will become blank space along
+  // the _opposite_ axis as we zoom out as a result of overscroll along an axis.
+  // This creates a 3D effect, as in the layer were moving backward along a "z"
+  // axis.
+  const float kZEffect = gfxPrefs::APZOverscrollZEffect();
 
   // The translation to apply for overscroll along the x axis.
   CSSPoint translationX;
-  if (mX.GetOverscroll() < 0) {
-    // Overscroll on left.
-    // Keep content at the midpoint of the screen's right edge fixed.
-    translationX.x = spacePropX * mX.GetCompositionLength();
-    translationX.y = (spacePropX * mY.GetCompositionLength()) / 2;
-  } else if (mX.GetOverscroll() > 0) {
-    // Overscroll on right.
-    // Keep content at the midpoint of the screen's left edge fixed.
-    translationX.y = (spacePropX * mY.GetCompositionLength()) / 2;
+  if (mX.IsOverscrolled()) {
+    // Keep the content centred vertically as we zoom out.
+    translationX.y = (spacePropX * kZEffect * mY.GetCompositionLength()) / 2;
+
+    if (mX.GetOverscroll() < 0) {
+      // Overscroll on left.
+      translationX.x = spacePropX * mX.GetCompositionLength();
+    } else {
+      // Overscroll on right.
+      // Note that zooming out already moves the content at the right edge
+      // of the composition bounds to the left, but since the zooming is
+      // dampened by kZEffect, it doesn't take us as far as we want to go.
+      translationX.x = - (spacePropX * (1 - kZEffect) * mX.GetCompositionLength());
+    }
   }
 
   // The translation to apply for overscroll along the y axis.
   CSSPoint translationY;
-  if (mY.GetOverscroll() < 0) {
-    // Overscroll at top.
-    // Keep content at the midpoint of the screen's bottom edge fixed.
-    translationY.x = (spacePropY * mX.GetCompositionLength()) / 2;
-    translationY.y = spacePropY * mY.GetCompositionLength();
-  } else if (mY.GetOverscroll() > 0) {
-    // Overscroll at bottom.
-    // Keep content at the midpoint of the screen's top edge fixed.
-    translationY.x = (spacePropY * mX.GetCompositionLength()) / 2;
+  if (mY.IsOverscrolled()) {
+    // Keep the content centred horizontally as we zoom out.
+    translationY.x = (spacePropY * kZEffect * mX.GetCompositionLength()) / 2;
+
+    if (mY.GetOverscroll() < 0) {
+      // Overscroll at top.
+      translationY.y = spacePropY * mY.GetCompositionLength();
+    } else {
+      // Overscroll at bottom.
+      // Note that zooming out already moves the content at the bottom edge
+      // of the composition bounds up, but since the zooming is
+      // dampened by kZEffect, it doesn't take us as far as we want to go.
+      translationY.y = - (spacePropY * (1 - kZEffect) * mY.GetCompositionLength());
+    }
   }
 
   // Combine the transformations along the two axes.
-  // TODO(botond): This method of combination is imperfect, and results in a
-  // funny-looking snap-back animation when we have overscroll along both axes.
-  // We should fine-tune this.
-  float spaceProp = std::max(spacePropX, spacePropY);
-  CSSPoint translation(std::max(translationX.x, translationY.x),
-                       std::max(translationX.y, translationY.y));
+  float spaceProp = sqrtf(spacePropX * spacePropX + spacePropY * spacePropY);
+  CSSPoint translation = translationX + translationY;
 
-  // The prpoportion of the composition length which will be taken up by the
-  // original content; this is the scale we will apply to the content.
-  float contentProp = 1 - spaceProp;
+  float scale = 1 - (kZEffect * spaceProp);
 
   // In a ViewTransform, the translation is applied before the scale. We want
   // to apply our translation after our scale, so we compensate for that here.
-  translation.x /= contentProp;
-  translation.y /= contentProp;
+  translation.x /= scale;
+  translation.y /= scale;
 
   // Finally, apply the transformations.
-  aTransform->mScale.scale *= contentProp;
+  aTransform->mScale.scale *= scale;
   aTransform->mTranslation += translation * mFrameMetrics.LayersPixelsPerCSSPixel();
 }
 
 bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
                                                             ViewTransform* aNewTransform,
                                                             ScreenPoint& aScrollOffset) {
   // The eventual return value of this function. The compositor needs to know
   // whether or not to advance by a frame as soon as it can. For example, if a
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -119,16 +119,18 @@ private:
   DECL_GFX_PREF(Once, "apz.fling_stopped_threshold",           APZFlingStoppedThreshold, float, 0.01f);
   DECL_GFX_PREF(Once, "apz.max_velocity_inches_per_ms",        APZMaxVelocity, float, -1.0f);
   DECL_GFX_PREF(Once, "apz.max_velocity_queue_size",           APZMaxVelocityQueueSize, uint32_t, 5);
   DECL_GFX_PREF(Live, "apz.min_skate_speed",                   APZMinSkateSpeed, float, 1.0f);
   DECL_GFX_PREF(Live, "apz.num_paint_duration_samples",        APZNumPaintDurationSamples, int32_t, 3);
   DECL_GFX_PREF(Live, "apz.overscroll.enabled",                APZOverscrollEnabled, bool, false);
   DECL_GFX_PREF(Live, "apz.overscroll.fling_friction",         APZOverscrollFlingFriction, float, 0.02f);
   DECL_GFX_PREF(Live, "apz.overscroll.fling_stopped_threshold", APZOverscrollFlingStoppedThreshold, float, 0.4f);
+  DECL_GFX_PREF(Live, "apz.overscroll.clamping",               APZOverscrollClamping, float, 0.5f);
+  DECL_GFX_PREF(Live, "apz.overscroll.z_effect",               APZOverscrollZEffect, float, 0.2f);
   DECL_GFX_PREF(Once, "apz.overscroll.snap_back_accel",        APZSnapBackAcceleration, float, 0.002f);
   DECL_GFX_PREF(Live, "apz.overscroll.snap_back_init_vel",     APZSnapBackInitialVelocity, float, 1.0f);
   DECL_GFX_PREF(Live, "apz.pan_repaint_interval",              APZPanRepaintInterval, int32_t, 250);
   DECL_GFX_PREF(Live, "apz.subframe.enabled",                  APZSubframeEnabled, bool, false);
   DECL_GFX_PREF(Once, "apz.test.logging_enabled",              APZTestLoggingEnabled, bool, false);
   DECL_GFX_PREF(Live, "apz.touch_start_tolerance",             APZTouchStartTolerance, float, 1.0f/4.5f);
   DECL_GFX_PREF(Live, "apz.use_paint_duration",                APZUsePaintDuration, bool, true);
   DECL_GFX_PREF(Live, "apz.velocity_bias",                     APZVelocityBias, float, 1.0f);