Bug 1358017 - Part 6: Implements the auto-dir scrolling feature(without the "honour root" functionality) in non-APZ r=masayuki

This commit implements the auto-dir scrolling functionality in non-APZ, based on
part 1 to part 3. However, the functionality of mousewheel.autodir.honourroot is
unimplemented in this commit.

MozReview-Commit-ID: 2vYABOx4RkK

--HG--
extra : rebase_source : 7dc45e6747a101c1a2c3a22bc695b2a0b2494b50
This commit is contained in:
Zhang Junzhi 2018-03-19 17:05:45 +08:00
Родитель 2bdc6774da
Коммит 891d6c4b37
4 изменённых файлов: 428 добавлений и 45 удалений

Просмотреть файл

@ -2332,8 +2332,8 @@ EventStateManager::DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
// Ignore mouse wheel transaction for computing legacy mouse wheel
// events' delta value.
nsIFrame* scrollFrame =
ComputeScrollTarget(aTargetFrame, aEvent,
COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET);
ComputeScrollTargetAndMayAdjustWheelEvent(
aTargetFrame, aEvent, COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET);
nsIScrollableFrame* scrollTarget = do_QueryFrame(scrollFrame);
nsPresContext* pc =
@ -2523,29 +2523,60 @@ EventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
}
nsIFrame*
EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions)
EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
nsIFrame* aTargetFrame,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions)
{
return ComputeScrollTarget(aTargetFrame, aEvent->mDeltaX, aEvent->mDeltaY,
aEvent, aOptions);
return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame,
aEvent->mDeltaX,
aEvent->mDeltaY,
aEvent, aOptions);
}
// Overload ComputeScrollTarget method to allow passing "test" dx and dy when looking
// for which scrollbarmediators to activate when two finger down on trackpad
// and before any actual motion
// Overload ComputeScrollTargetAndMayAdjustWheelEvent method to allow passing
// "test" dx and dy when looking for which scrollbarmediators to activate when
// two finger down on trackpad and before any actual motion
nsIFrame*
EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
double aDirectionX,
double aDirectionY,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions)
EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent(
nsIFrame* aTargetFrame,
double aDirectionX,
double aDirectionY,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions)
{
if ((aOptions & INCLUDE_PLUGIN_AS_TARGET) &&
!WheelPrefs::WheelEventsEnabledOnPlugins()) {
aOptions = RemovePluginFromTarget(aOptions);
}
bool isAutoDir = false;
bool honoursRoot = false;
if (MAY_BE_ADJUSTED_BY_AUTO_DIR & aOptions) {
// If the scroll is respected as auto-dir, aDirection* should always be
// equivalent to the event's delta vlaues(Currently, there are only one case
// where aDirection*s have different values from the widget wheel event's
// original delta values and the only case isn't auto-dir, see
// ScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets).
MOZ_ASSERT(aDirectionX == aEvent->mDeltaX &&
aDirectionY == aEvent->mDeltaY);
WheelDeltaAdjustmentStrategy strategy =
GetWheelDeltaAdjustmentStrategy(*aEvent);
switch (strategy) {
case WheelDeltaAdjustmentStrategy::eAutoDir:
isAutoDir = true;
honoursRoot = false;
break;
case WheelDeltaAdjustmentStrategy::eAutoDirWithRootHonour:
isAutoDir = true;
honoursRoot = true;
break;
default:
break;
}
}
if (aOptions & PREFER_MOUSE_WHEEL_TRANSACTION) {
// If the user recently scrolled with the mousewheel, then they probably
// want to scroll the same view as before instead of the view under the
@ -2570,6 +2601,16 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
if (scrollableFrame) {
nsIFrame* frameToScroll = do_QueryFrame(scrollableFrame);
MOZ_ASSERT(frameToScroll);
if (isAutoDir) {
ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent,
*lastScrollFrame,
honoursRoot);
// Note that calling this function will not always cause the delta to
// be adjusted, it only adjusts the delta when it should, because
// Adjust() internally calls ShouldBeAdjusted() before making
// adjustment.
adjuster.Adjust();
}
return frameToScroll;
}
}
@ -2582,10 +2623,21 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
return nullptr;
}
bool checkIfScrollableX =
aDirectionX && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
bool checkIfScrollableY =
aDirectionY && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
bool checkIfScrollableX;
bool checkIfScrollableY;
if (isAutoDir) {
// Always check the frame's scrollability in both the two directions for an
// auto-dir scroll. That is, for an auto-dir scroll,
// PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS and
// PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS should be ignored.
checkIfScrollableX = true;
checkIfScrollableY = true;
} else {
checkIfScrollableX =
aDirectionX && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
checkIfScrollableY =
aDirectionY && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
}
nsIFrame* scrollFrame =
!(aOptions & START_FROM_PARENT) ? aTargetFrame :
@ -2648,10 +2700,23 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
continue;
}
// For default action, we should climb up the tree if cannot scroll it
// by the event actually.
bool canScroll = WheelHandlingUtils::CanScrollOn(scrollableFrame,
aDirectionX, aDirectionY);
// Computes whether the currently checked frame is scrollable by this wheel
// event.
bool canScroll = false;
if (isAutoDir) {
ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *scrollFrame, honoursRoot);
if (adjuster.ShouldBeAdjusted()) {
adjuster.Adjust();
canScroll = true;
} else if (WheelHandlingUtils::CanScrollOn(scrollableFrame,
aDirectionX, aDirectionY)) {
canScroll = true;
}
} else if (WheelHandlingUtils::CanScrollOn(scrollableFrame,
aDirectionX, aDirectionY)) {
canScroll = true;
}
// Comboboxes need special care.
nsIComboboxControlFrame* comboBox = do_QueryFrame(scrollFrame);
if (comboBox) {
@ -2666,13 +2731,20 @@ EventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
if (canScroll) {
return frameToScroll;
}
// Where we are at is the block ending in a for loop.
// The current frame has been checked to be unscrollable by this wheel
// event, continue the loop to check its parent, if any.
}
nsIFrame* newFrame = nsLayoutUtils::GetCrossDocParentFrame(
aTargetFrame->PresShell()->GetRootFrame());
aOptions =
static_cast<ComputeScrollTargetOptions>(aOptions & ~START_FROM_PARENT);
return newFrame ? ComputeScrollTarget(newFrame, aEvent, aOptions) : nullptr;
if (!newFrame) {
return nullptr;
}
return ComputeScrollTargetAndMayAdjustWheelEvent(newFrame, aEvent, aOptions);
}
nsSize
@ -2837,14 +2909,16 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
if (scrollFrameWeak.IsAlive()) {
if (aEvent->mDeltaX &&
overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN &&
!ComputeScrollTarget(scrollFrame, aEvent,
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS)) {
!ComputeScrollTargetAndMayAdjustWheelEvent(
scrollFrame, aEvent,
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR)) {
aEvent->mOverflowDeltaX = aEvent->mDeltaX;
}
if (aEvent->mDeltaY &&
overflowStyle.mVertical == NS_STYLE_OVERFLOW_HIDDEN &&
!ComputeScrollTarget(scrollFrame, aEvent,
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS)) {
!ComputeScrollTargetAndMayAdjustWheelEvent(
scrollFrame, aEvent,
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR)) {
aEvent->mOverflowDeltaY = aEvent->mDeltaY;
}
}
@ -3368,8 +3442,10 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
ScrollbarsForWheel::MayInactivate();
WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
nsIScrollableFrame* scrollTarget =
do_QueryFrame(ComputeScrollTarget(mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET));
do_QueryFrame(
ComputeScrollTargetAndMayAdjustWheelEvent(
mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR));
if (scrollTarget) {
scrollTarget->ScrollSnap();
}
@ -3408,12 +3484,21 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
horizontalizer.Horizontalize();
}
// Since ComputeScrollTargetAndMayAdjustWheelEvent() may adjust the delta
// if the event is auto-dir. So we use |ESMAutoDirWheelDeltaRestorer|
// here.
// An instance of |ESMAutoDirWheelDeltaRestorer| is used to monitor
// auto-dir adjustment which may happen during its lifetime. If the delta
// values is adjusted during its lifetime, the instance will restore the
// adjusted delta when it's being destrcuted.
ESMAutoDirWheelDeltaRestorer restorer(*wheelEvent);
// Check if the frame to scroll before checking the default action
// because if the scroll target is a plugin, the default action should be
// chosen by the plugin rather than by our prefs.
nsIFrame* frameToScroll =
ComputeScrollTarget(mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET);
ComputeScrollTargetAndMayAdjustWheelEvent(
mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR);
nsPluginFrame* pluginFrame = do_QueryFrame(frameToScroll);
if (pluginFrame) {
MOZ_ASSERT(pluginFrame->WantsToHandleWheelEventAsDefaultAction());
@ -3505,8 +3590,8 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// scrolling is possible in the requested direction. It does this
// by looking at the scroll overflow values on mCanTriggerSwipe
// events after they have been processed.
allDeltaOverflown =
!ComputeScrollTarget(mCurrentTarget, wheelEvent,
allDeltaOverflown = !ComputeScrollTarget(
mCurrentTarget, wheelEvent,
COMPUTE_DEFAULT_ACTION_TARGET);
}
} else {
@ -6160,7 +6245,6 @@ EventStateManager::GetWheelDeltaAdjustmentStrategy(
case WheelPrefs::ACTION_HORIZONTALIZED_SCROLL:
return WheelDeltaAdjustmentStrategy::eHorizontalize;
default:
// Prevent compilation errors generated by -Werror=switch
break;
}
return WheelDeltaAdjustmentStrategy::eNone;

Просмотреть файл

@ -768,8 +768,8 @@ protected:
DeltaDirection aDeltaDirection);
/**
* ComputeScrollTarget() returns the scrollable frame which should be
* scrolled.
* ComputeScrollTargetAndMayAdjustWheelEvent() returns the scrollable frame
* which should be scrolled.
*
* @param aTargetFrame The event target of the wheel event.
* @param aEvent The handling mouse wheel event.
@ -777,15 +777,18 @@ protected:
* Callers should use COMPUTE_*.
* @return The scrollable frame which should be scrolled.
*/
// These flags are used in ComputeScrollTarget(). Callers should use
// COMPUTE_*.
// These flags are used in ComputeScrollTargetAndMayAdjustWheelEvent().
// Callers should use COMPUTE_*.
enum
{
PREFER_MOUSE_WHEEL_TRANSACTION = 0x00000001,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 0x00000002,
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 0x00000004,
START_FROM_PARENT = 0x00000008,
INCLUDE_PLUGIN_AS_TARGET = 0x00000010
INCLUDE_PLUGIN_AS_TARGET = 0x00000010,
// Indicates the wheel scroll event being computed is an auto-dir scroll, so
// its delta may be adjusted after being computed.
MAY_BE_ADJUSTED_BY_AUTO_DIR = 0x00000020,
};
enum ComputeScrollTargetOptions
{
@ -804,12 +807,22 @@ protected:
COMPUTE_DEFAULT_ACTION_TARGET =
(COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN |
INCLUDE_PLUGIN_AS_TARGET),
COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR_EXCEPT_PLUGIN =
(COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN |
MAY_BE_ADJUSTED_BY_AUTO_DIR),
COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR =
(COMPUTE_DEFAULT_ACTION_TARGET |
MAY_BE_ADJUSTED_BY_AUTO_DIR),
// Look for the nearest scrollable ancestor which can be scrollable with
// aEvent.
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS =
(PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS =
(PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT)
(PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT),
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS_WITH_AUTO_DIR =
(COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS | MAY_BE_ADJUSTED_BY_AUTO_DIR),
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS_WITH_AUTO_DIR =
(COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS | MAY_BE_ADJUSTED_BY_AUTO_DIR),
};
static ComputeScrollTargetOptions RemovePluginFromTarget(
ComputeScrollTargetOptions aOptions)
@ -817,20 +830,52 @@ protected:
switch (aOptions) {
case COMPUTE_DEFAULT_ACTION_TARGET:
return COMPUTE_DEFAULT_ACTION_TARGET_EXCEPT_PLUGIN;
case COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR:
return COMPUTE_DEFAULT_ACTION_TARGET_WITH_AUTO_DIR_EXCEPT_PLUGIN;
default:
MOZ_ASSERT(!(aOptions & INCLUDE_PLUGIN_AS_TARGET));
return aOptions;
}
}
// Compute the scroll target.
// The delta values in the wheel event may be changed if the event is for
// auto-dir scrolling. For information on auto-dir,
// @see mozilla::WheelDeltaAdjustmentStrategy
nsIFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
nsIFrame* aTargetFrame,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions);
nsIFrame* ComputeScrollTargetAndMayAdjustWheelEvent(
nsIFrame* aTargetFrame,
double aDirectionX,
double aDirectionY,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions);
nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions);
ComputeScrollTargetOptions aOptions)
{
MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
"aEvent may be modified by auto-dir");
return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame, aEvent,
aOptions);
}
nsIFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
double aDirectionX,
double aDirectionY,
WidgetWheelEvent* aEvent,
ComputeScrollTargetOptions aOptions);
ComputeScrollTargetOptions aOptions)
{
MOZ_ASSERT(!(aOptions & MAY_BE_ADJUSTED_BY_AUTO_DIR),
"aEvent may be modified by auto-dir");
return ComputeScrollTargetAndMayAdjustWheelEvent(aTargetFrame,
aDirectionX, aDirectionY,
aEvent, aOptions);
}
/**
* GetScrollAmount() returns the scroll amount in app uints of one line or
@ -838,7 +883,8 @@ protected:
* height. Otherwise, returns line height for both its width and height.
*
* @param aScrollableFrame A frame which will be scrolled by the event.
* The result of ComputeScrollTarget() is
* The result of
* ComputeScrollTargetAndMayAdjustWheelEvent() is
* expected for this value.
* This can be nullptr if there is no scrollable
* frame. Then, this method uses root frame's

Просмотреть файл

@ -531,7 +531,8 @@ ScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets(
AutoWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
MOZ_ASSERT(!*scrollTarget, "scroll target still temporarily activated!");
nsIScrollableFrame* target = do_QueryFrame(
aESM->ComputeScrollTarget(aTargetFrame, dir->deltaX, dir->deltaY, aEvent,
aESM->ComputeScrollTarget(
aTargetFrame, dir->deltaX, dir->deltaY, aEvent,
EventStateManager::COMPUTE_DEFAULT_ACTION_TARGET));
nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(target);
if (scrollbarMediator) {
@ -706,4 +707,188 @@ AutoDirWheelDeltaAdjuster::Adjust()
OnAdjusted();
}
/******************************************************************/
/* mozilla::ESMAutoDirWheelDeltaAdjuster */
/******************************************************************/
ESMAutoDirWheelDeltaAdjuster::ESMAutoDirWheelDeltaAdjuster(
WidgetWheelEvent& aEvent,
nsIFrame& aScrollFrame,
bool aHonoursRoot)
: AutoDirWheelDeltaAdjuster(aEvent.mDeltaX, aEvent.mDeltaY)
, mLineOrPageDeltaX(aEvent.mLineOrPageDeltaX)
, mLineOrPageDeltaY(aEvent.mLineOrPageDeltaY)
, mOverflowDeltaX(aEvent.mOverflowDeltaX)
, mOverflowDeltaY(aEvent.mOverflowDeltaY)
{
mScrollTargetFrame = aScrollFrame.GetScrollTargetFrame();
MOZ_ASSERT(mScrollTargetFrame);
// TODO Currently, the honoured target is always the current scrolling frame.
nsIFrame* honouredFrame = &aScrollFrame;
WritingMode writingMode = honouredFrame->GetWritingMode();
WritingMode::BlockDir blockDir = writingMode.GetBlockDir();
WritingMode::InlineDir inlineDir = writingMode.GetInlineDir();
// Get whether the honoured frame's content in the horizontal direction starts
// from right to left(E.g. it's true either if "writing-mode: vertical-rl", or
// if "writing-mode: horizontal-tb; direction: rtl;" in CSS).
mIsHorizontalContentRightToLeft =
(blockDir == WritingMode::BlockDir::eBlockRL ||
(blockDir == WritingMode::BlockDir::eBlockTB &&
inlineDir == WritingMode::InlineDir::eInlineRTL));
}
void
ESMAutoDirWheelDeltaAdjuster::OnAdjusted()
{
// Adjust() only adjusted basic deltaX and deltaY, which are not enough for
// ESM, we should continue to adjust line-or-page and overflow values.
if (mDeltaX) {
// A vertical scroll was adjusted to be horizontal.
MOZ_ASSERT(0 == mDeltaY);
mLineOrPageDeltaX = mLineOrPageDeltaY;
mLineOrPageDeltaY = 0;
mOverflowDeltaX = mOverflowDeltaY;
mOverflowDeltaY = 0;
} else {
// A horizontal scroll was adjusted to be vertical.
MOZ_ASSERT(0 != mDeltaY);
mLineOrPageDeltaY = mLineOrPageDeltaX;
mLineOrPageDeltaX = 0;
mOverflowDeltaY = mOverflowDeltaX;
mOverflowDeltaX = 0;
}
if (mIsHorizontalContentRightToLeft) {
// If in RTL writing mode, reverse the side the scroll will go towards.
mLineOrPageDeltaX *= -1;
mLineOrPageDeltaY *= -1;
mOverflowDeltaX *= -1;
mOverflowDeltaY *= -1;
}
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollAlongXAxis() const
{
return mScrollTargetFrame->GetPerceivedScrollingDirections() &
nsIScrollableFrame::HORIZONTAL;
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollAlongYAxis() const
{
return mScrollTargetFrame->GetPerceivedScrollingDirections() &
nsIScrollableFrame::VERTICAL;
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollUpwards() const
{
nsPoint scrollPt = mScrollTargetFrame->GetScrollPosition();
nsRect scrollRange = mScrollTargetFrame->GetScrollRange();
return static_cast<double>(scrollRange.y) < scrollPt.y;
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollDownwards() const
{
nsPoint scrollPt = mScrollTargetFrame->GetScrollPosition();
nsRect scrollRange = mScrollTargetFrame->GetScrollRange();
return static_cast<double>(scrollRange.YMost()) > scrollPt.y;
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollLeftwards() const
{
nsPoint scrollPt = mScrollTargetFrame->GetScrollPosition();
nsRect scrollRange = mScrollTargetFrame->GetScrollRange();
return static_cast<double>(scrollRange.x) < scrollPt.x;
}
bool
ESMAutoDirWheelDeltaAdjuster::CanScrollRightwards() const
{
nsPoint scrollPt = mScrollTargetFrame->GetScrollPosition();
nsRect scrollRange = mScrollTargetFrame->GetScrollRange();
return static_cast<double>(scrollRange.XMost()) > scrollPt.x;
}
bool
ESMAutoDirWheelDeltaAdjuster::IsHorizontalContentRightToLeft() const
{
return mIsHorizontalContentRightToLeft;
}
/******************************************************************/
/* mozilla::ESMAutoDirWheelDeltaRestorer */
/******************************************************************/
/*explicit*/
ESMAutoDirWheelDeltaRestorer::ESMAutoDirWheelDeltaRestorer(
WidgetWheelEvent& aEvent)
: mEvent(aEvent)
, mOldDeltaX(aEvent.mDeltaX)
, mOldDeltaY(aEvent.mDeltaY)
, mOldLineOrPageDeltaX(aEvent.mLineOrPageDeltaX)
, mOldLineOrPageDeltaY(aEvent.mLineOrPageDeltaY)
, mOldOverflowDeltaX(aEvent.mOverflowDeltaX)
, mOldOverflowDeltaY(aEvent.mOverflowDeltaY)
{
}
ESMAutoDirWheelDeltaRestorer::~ESMAutoDirWheelDeltaRestorer()
{
if (mOldDeltaX == mEvent.mDeltaX || mOldDeltaY == mEvent.mDeltaY) {
// The delta of the event wasn't adjusted during the lifetime of this
// |ESMAutoDirWheelDeltaRestorer| instance. No need to restore it.
return;
}
bool forRTL = false;
// First, restore the basic deltaX and deltaY.
std::swap(mEvent.mDeltaX, mEvent.mDeltaY);
if (mOldDeltaX != mEvent.mDeltaX || mOldDeltaY != mEvent.mDeltaY) {
// If X and Y still don't equal to their original values after being
// swapped, then it must be because they were adjusted for RTL.
forRTL = true;
mEvent.mDeltaX *= -1;
mEvent.mDeltaY *= -1;
MOZ_ASSERT(mOldDeltaX == mEvent.mDeltaX && mOldDeltaY == mEvent.mDeltaY);
}
if (mEvent.mDeltaX) {
// A horizontal scroll was adjusted to be vertical during the lifetime of
// this instance.
MOZ_ASSERT(0 == mEvent.mDeltaY);
// Restore the line-or-page and overflow values to be horizontal.
mEvent.mOverflowDeltaX = mEvent.mOverflowDeltaY;
mEvent.mLineOrPageDeltaX = mEvent.mLineOrPageDeltaY;
if (forRTL) {
mEvent.mOverflowDeltaX *= -1;
mEvent.mLineOrPageDeltaX *= -1;
}
mEvent.mOverflowDeltaY = mOldOverflowDeltaY;
mEvent.mLineOrPageDeltaY = mOldLineOrPageDeltaY;
} else {
// A vertical scroll was adjusted to be horizontal during the lifetime of
// this instance.
MOZ_ASSERT(0 != mEvent.mDeltaY);
// Restore the line-or-page and overflow values to be vertical.
mEvent.mOverflowDeltaY = mEvent.mOverflowDeltaX;
mEvent.mLineOrPageDeltaY = mEvent.mLineOrPageDeltaX;
if (forRTL) {
mEvent.mOverflowDeltaY *= -1;
mEvent.mLineOrPageDeltaY *= -1;
}
mEvent.mOverflowDeltaX = mOldOverflowDeltaX;
mEvent.mLineOrPageDeltaX = mOldLineOrPageDeltaX;
}
}
} // namespace mozilla

Просмотреть файл

@ -382,6 +382,74 @@ private:
bool mShouldBeAdjusted;
};
/**
* This is the implementation of AutoDirWheelDeltaAdjuster for EventStateManager
*
* Detailed comments about some member functions are given in the base class
* AutoDirWheelDeltaAdjuster.
*/
class MOZ_STACK_CLASS ESMAutoDirWheelDeltaAdjuster final
: public AutoDirWheelDeltaAdjuster
{
public:
/**
* @param aEvent The auto-dir wheel scroll event.
* @param aScrollFrame The scroll target for the event.
* @param aHonoursRoot If set to true, the honoured frame is the root
* frame in the same document where the target is;
* If false, the honoured frame is the scroll
* target. For the concept of an honoured target,
* @see mozilla::WheelDeltaAdjustmentStrategy
*/
ESMAutoDirWheelDeltaAdjuster(WidgetWheelEvent& aEvent,
nsIFrame& aScrollFrame,
bool aHonoursRoot);
private:
virtual void OnAdjusted() override;
virtual bool CanScrollAlongXAxis() const override;
virtual bool CanScrollAlongYAxis() const override;
virtual bool CanScrollUpwards() const override;
virtual bool CanScrollDownwards() const override;
virtual bool CanScrollLeftwards() const override;
virtual bool CanScrollRightwards() const override;
virtual bool IsHorizontalContentRightToLeft() const override;
nsIScrollableFrame* mScrollTargetFrame;
bool mIsHorizontalContentRightToLeft;
int32_t& mLineOrPageDeltaX;
int32_t& mLineOrPageDeltaY;
double& mOverflowDeltaX;
double& mOverflowDeltaY;
};
/**
* This class is used for restoring the delta in an auto-dir wheel.
*
* An instance of this calss monitors auto-dir adjustment which may happen
* during its lifetime. If the delta values is adjusted during its lifetime, the
* instance will restore the adjusted delta when it's being destrcuted.
*/
class MOZ_STACK_CLASS ESMAutoDirWheelDeltaRestorer final
{
public:
/**
* @param aEvent The wheel scroll event to be monitored.
*/
explicit ESMAutoDirWheelDeltaRestorer(WidgetWheelEvent& aEvent);
~ESMAutoDirWheelDeltaRestorer();
private:
WidgetWheelEvent& mEvent;
double mOldDeltaX;
double mOldDeltaY;
int32_t mOldLineOrPageDeltaX;
int32_t mOldLineOrPageDeltaY;
double mOldOverflowDeltaX;
double mOldOverflowDeltaY;
};
} // namespace mozilla
#endif // mozilla_WheelHandlingHelper_h_