Bug 945584: Part 8 - Implement Scroll Snapping for Middle Mouse Button Scrolls (v2 Patch), r=roc, r=bz
authorKearwood (Kip) Gilbert <kgilbert@mozilla.com>
Thu, 19 Feb 2015 16:03:07 -0800
changeset 232154 18c59100d528cfbeb5a415d941fdbc66f74f3a56
parent 232153 79989474e408ef46f51ed515a2202310b54b8b4c
child 232155 1e3ba87c78002755caafa273a0cd19dd24652d44
push id28372
push usercbook@mozilla.com
push dateFri, 06 Mar 2015 12:07:51 +0000
treeherdermozilla-central@7d85ac833cff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, bz
bugs945584, 1137937
milestone39.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 945584: Part 8 - Implement Scroll Snapping for Middle Mouse Button Scrolls (v2 Patch), r=roc, r=bz - Implemented scroll snapping at the end of a middle-mouse-button scroll. - As this scrolling occurs within chrome Javascript, chrome-only DOM methods had to be added: window.MozScrollSnap and element.MozScrollSnap - Bug 1137937 tracks implementation of a replacement for these chome-only DOM methods, to be replaced with a web accessible API.
dom/base/Element.cpp
dom/base/Element.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/webidl/Element.webidl
dom/webidl/Window.webidl
toolkit/content/browser-content.js
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -792,16 +792,25 @@ Element::ScrollByNoFlush(int32_t aDx, in
   if (!weakRef.IsAlive()) {
     return false;
   }
 
   CSSIntPoint after = sf->GetScrollPositionCSSPixels();
   return (before != after);
 }
 
+void
+Element::MozScrollSnap()
+{
+  nsIScrollableFrame* sf = GetScrollFrame(nullptr, false);
+  if (sf) {
+    sf->ScrollSnap();
+  }
+}
+
 static nsSize GetScrollRectSizeForOverflowVisibleFrame(nsIFrame* aFrame)
 {
   if (!aFrame) {
     return nsSize(0,0);
   }
 
   nsRect paddingRect = aFrame->GetPaddingRectRelativeToSelf();
   nsOverflowAreas overflowAreas(paddingRect, paddingRect);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -757,16 +757,17 @@ public:
    */
   bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
   int32_t ScrollTop();
   void SetScrollTop(int32_t aScrollTop);
   int32_t ScrollLeft();
   void SetScrollLeft(int32_t aScrollLeft);
   int32_t ScrollWidth();
   int32_t ScrollHeight();
+  void MozScrollSnap();
   int32_t ClientTop()
   {
     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
   }
   int32_t ClientLeft()
   {
     return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
   }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7351,16 +7351,26 @@ nsGlobalWindow::ScrollByPages(int32_t nu
     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
                  smoothScroll
                    ? nsIScrollableFrame::SMOOTH_MSD
                    : nsIScrollableFrame::INSTANT);
   }
 }
 
 void
+nsGlobalWindow::MozScrollSnap()
+{
+  FlushPendingNotifications(Flush_Layout);
+  nsIScrollableFrame *sf = GetScrollFrame();
+  if (sf) {
+    sf->ScrollSnap();
+  }
+}
+
+void
 nsGlobalWindow::MozRequestOverfill(OverfillCallback& aCallback,
                                    mozilla::ErrorResult& aError)
 {
   nsIWidget* widget = nsContentUtils::WidgetForDocument(mDoc);
   if (widget) {
     mozilla::layers::LayerManager* manager = widget->GetLayerManager();
     if (manager) {
       manager->RequestOverfill(&aCallback);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -941,16 +941,17 @@ public:
   void ScrollTo(double aXScroll, double aYScroll);
   void ScrollTo(const mozilla::dom::ScrollToOptions& aOptions);
   void ScrollBy(double aXScrollDif, double aYScrollDif);
   void ScrollBy(const mozilla::dom::ScrollToOptions& aOptions);
   void ScrollByLines(int32_t numLines,
                      const mozilla::dom::ScrollOptions& aOptions);
   void ScrollByPages(int32_t numPages,
                      const mozilla::dom::ScrollOptions& aOptions);
+  void MozScrollSnap();
   int32_t GetInnerWidth(mozilla::ErrorResult& aError);
   void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError);
   int32_t GetInnerHeight(mozilla::ErrorResult& aError);
   void SetInnerHeight(int32_t aInnerHeight, mozilla::ErrorResult& aError);
   int32_t GetScrollX(mozilla::ErrorResult& aError);
   int32_t GetPageXOffset(mozilla::ErrorResult& aError)
   {
     return GetScrollX(aError);
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -180,16 +180,21 @@ partial interface Element {
   readonly attribute long scrollHeight;
   
   void scroll(unrestricted double x, unrestricted double y);
   void scroll(optional ScrollToOptions options);
   void scrollTo(unrestricted double x, unrestricted double y);
   void scrollTo(optional ScrollToOptions options);
   void scrollBy(unrestricted double x, unrestricted double y);
   void scrollBy(optional ScrollToOptions options);
+  // mozScrollSnap is used by chrome to perform scroll snapping after the
+  // user performs actions that may affect scroll position
+  // mozScrollSnap is deprecated, to be replaced by a web accessible API, such
+  // as an extension to the ScrollOptions dictionary.  See bug 1137937.
+  [ChromeOnly] void mozScrollSnap();
 
   readonly attribute long clientTop;
   readonly attribute long clientLeft;
   readonly attribute long clientWidth;
   readonly attribute long clientHeight;
 
   // Mozilla specific stuff
   /* The maximum offset that the element can be scrolled to
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -185,16 +185,21 @@ partial interface Window {
   //[Throws] readonly attribute double scrollY;
   //[Throws] readonly attribute double pageYOffset;
   void scroll(unrestricted double x, unrestricted double y);
   void scroll(optional ScrollToOptions options);
   void scrollTo(unrestricted double x, unrestricted double y);
   void scrollTo(optional ScrollToOptions options);
   void scrollBy(unrestricted double x, unrestricted double y);
   void scrollBy(optional ScrollToOptions options);
+  // mozScrollSnap is used by chrome to perform scroll snapping after the
+  // user performs actions that may affect scroll position
+  // mozScrollSnap is deprecated, to be replaced by a web accessible API, such
+  // as an extension to the ScrollOptions dictionary.  See bug 1137937.
+  [ChromeOnly] void mozScrollSnap();
   [Replaceable, Throws] readonly attribute long scrollX;
   [Throws] readonly attribute long pageXOffset;
   [Replaceable, Throws] readonly attribute long scrollY;
   [Throws] readonly attribute long pageYOffset;
 
   // client
   //[Throws] readonly attribute double screenX;
   //[Throws] readonly attribute double screenY;
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -141,16 +141,17 @@ let ClickEventHandler = {
     this._scrollErrorY = 0;
     this._lastFrame = content.mozAnimationStartTime;
 
     content.mozRequestAnimationFrame(this);
   },
 
   stopScroll: function() {
     if (this._scrollable) {
+      this._scrollable.mozScrollSnap();
       this._scrollable = null;
 
       Cc["@mozilla.org/eventlistenerservice;1"]
         .getService(Ci.nsIEventListenerService)
         .removeSystemEventListener(global, "mousemove", this, true);
       removeEventListener("pagehide", this, true);
     }
   },