Bug 1358017 - Part 3: Defines a common interface of the auto-dir scrolling delta adjuster. r?masayuki, kats
This commit defines a common interface of the auto-dir scrolling functionality.
In future commits, it will be implemented in both the APZ and non-APZ parts.
MozReview-Commit-ID: 8fApuHwsbrv
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -1,16 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WheelHandlingHelper.h"
+#include <utility> // for std::swap
+
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/WheelEventBinding.h"
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsIContent.h"
@@ -632,9 +634,76 @@ void WheelDeltaHorizontalizer::CancelHor
}
}
WheelDeltaHorizontalizer::~WheelDeltaHorizontalizer()
{
CancelHorizontalization();
}
+/******************************************************************/
+/* mozilla::AutoDirWheelDeltaAdjuster */
+/******************************************************************/
+
+bool
+AutoDirWheelDeltaAdjuster::ShouldBeAdjusted()
+{
+ // Sometimes, this function can be called more than one time. If we have
+ // already checked if the scroll should be adjusted, there's no need to check
+ // it again.
+ if (mCheckedIfShouldBeAdjusted) {
+ return mShouldBeAdjusted;
+ }
+ mCheckedIfShouldBeAdjusted = true;
+
+ // For an auto-dir wheel scroll, if all the following conditions are met, we
+ // should adjust X and Y values:
+ // 1. There is only one non-zero value between DeltaX and DeltaY.
+ // 2. There is only one direction for the target that overflows and is
+ // scrollable with wheel.
+ // 3. The direction described in Condition 1 is orthogonal to the one
+ // described in Condition 2.
+ if ((mDeltaX && mDeltaY) || (!mDeltaX && !mDeltaY)) {
+ return false;
+ }
+ if (mDeltaX) {
+ if (CanScrollAlongXAxis()) {
+ return false;
+ }
+ if (IsHorizontalContentRightToLeft()) {
+ mShouldBeAdjusted = mDeltaX > 0 ? CanScrollUpwards()
+ : CanScrollDownwards();
+ } else {
+ mShouldBeAdjusted = mDeltaX < 0 ? CanScrollUpwards()
+ : CanScrollDownwards();
+ }
+ return mShouldBeAdjusted;
+ }
+ MOZ_ASSERT(0 != mDeltaY);
+ if (CanScrollAlongYAxis()) {
+ return false;
+ }
+ if (IsHorizontalContentRightToLeft()) {
+ mShouldBeAdjusted = mDeltaY > 0 ? CanScrollLeftwards()
+ : CanScrollRightwards();
+ } else {
+ mShouldBeAdjusted = mDeltaY < 0 ? CanScrollLeftwards()
+ : CanScrollRightwards();
+ }
+ return mShouldBeAdjusted;
+}
+
+void
+AutoDirWheelDeltaAdjuster::Adjust()
+{
+ if (!ShouldBeAdjusted()) {
+ return;
+ }
+ std::swap(mDeltaX, mDeltaY);
+ if (IsHorizontalContentRightToLeft()) {
+ mDeltaX *= -1;
+ mDeltaY *= -1;
+ }
+ mShouldBeAdjusted = false;
+ OnAdjusted();
+}
+
} // namespace mozilla
--- a/dom/events/WheelHandlingHelper.h
+++ b/dom/events/WheelHandlingHelper.h
@@ -292,11 +292,93 @@ private:
WidgetWheelEvent& mWheelEvent;
double mOldDeltaX;
double mOldDeltaZ;
double mOldOverflowDeltaX;
int32_t mOldLineOrPageDeltaX;
bool mHorizontalized;
};
+/**
+ * This class is used to adjust the delta values for wheel scrolling with the
+ * auto-dir functionality.
+ * A traditional wheel scroll only allows the user use the wheel in the same
+ * scrollable direction as that of the scrolling target to scroll the target,
+ * whereas an auto-dir scroll lets the user use any wheel(either a vertical
+ * wheel or a horizontal tilt wheel) to scroll a frame which is scrollable in
+ * only one direction. For detailed information on auto-dir scrolling,
+ * @see mozilla::WheelDeltaAdjustmentStrategy.
+ */
+class MOZ_STACK_CLASS AutoDirWheelDeltaAdjuster
+{
+protected:
+ /**
+ * @param aDeltaX DeltaX for a wheel event whose delta values will
+ * be adjusted upon calling Adjust() when
+ * ShouldBeAdjusted() returns true.
+ * @param aDeltaY DeltaY for a wheel event, like DeltaX.
+ */
+ AutoDirWheelDeltaAdjuster(double& aDeltaX,
+ double& aDeltaY)
+ : mDeltaX(aDeltaX)
+ , mDeltaY(aDeltaY)
+ , mCheckedIfShouldBeAdjusted(false)
+ , mShouldBeAdjusted(false)
+ {
+ }
+
+public:
+ /**
+ * Gets whether the values of the delta should be adjusted for auto-dir
+ * scrolling. Note that if Adjust() has been called, this function simply
+ * returns false.
+ *
+ * @return true if the delta should be adjusted; otherwise false.
+ */
+ bool ShouldBeAdjusted();
+ /**
+ * Adjusts the values of the delta values for auto-dir scrolling when
+ * ShouldBeAdjusted() returns true. If you call it when ShouldBeAdjusted()
+ * returns false, this function will simply do nothing.
+ */
+ void Adjust();
+
+private:
+ /**
+ * Called by Adjust() if Adjust() successfully adjusted the delta values.
+ */
+ virtual void OnAdjusted()
+ {
+ }
+
+ virtual bool CanScrollAlongXAxis() const = 0;
+ virtual bool CanScrollAlongYAxis() const = 0;
+ virtual bool CanScrollUpwards() const = 0;
+ virtual bool CanScrollDownwards() const = 0;
+ virtual bool CanScrollLeftwards() const = 0;
+ virtual bool CanScrollRightwards() const = 0;
+
+ /**
+ * Gets whether the horizontal content starts at rightside.
+ *
+ * @return If the content is in vertical-RTL writing mode(E.g. "writing-mode:
+ * vertical-rl" in CSS), or if it's in horizontal-RTL writing-mode
+ * (E.g. "writing-mode: horizontal-tb; direction: rtl;" in CSS), then
+ * this function returns true. From the representation perspective,
+ * frames whose horizontal contents start at rightside also cause
+ * their horizontal scrollbars, if any, initially start at rightside.
+ * So we can also learn about the initial side of the horizontal
+ * scrollbar for the frame by calling this function.
+ */
+ virtual bool IsHorizontalContentRightToLeft() const = 0;
+
+protected:
+ double& mDeltaX;
+ double& mDeltaY;
+
+private:
+ bool mCheckedIfShouldBeAdjusted;
+ bool mShouldBeAdjusted;
+};
+
} // namespace mozilla
#endif // mozilla_WheelHandlingHelper_h_