зеркало из https://github.com/mozilla/gecko-dev.git
Bug 786898 part.1 Set overflowDelta 0 if the delta is unused by overflow-x: hidden; or overflow-y: hidden; but an ancestor is scrollable along the axis r=smaug
This commit is contained in:
Родитель
fba947c973
Коммит
8819e0f580
|
@ -2504,7 +2504,8 @@ nsEventStateManager::DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
|
|||
// Ignore mouse wheel transaction for computing legacy mouse wheel
|
||||
// events' delta value.
|
||||
nsIScrollableFrame* scrollTarget =
|
||||
ComputeScrollTarget(aTargetFrame, aEvent, false);
|
||||
ComputeScrollTarget(aTargetFrame, aEvent,
|
||||
COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET);
|
||||
|
||||
nsIFrame* scrollFrame = do_QueryFrame(scrollTarget);
|
||||
nsPresContext* pc =
|
||||
|
@ -2688,9 +2689,9 @@ nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
|||
nsIScrollableFrame*
|
||||
nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
widget::WheelEvent* aEvent,
|
||||
bool aForDefaultAction)
|
||||
ComputeScrollTargetOptions aOptions)
|
||||
{
|
||||
if (aForDefaultAction) {
|
||||
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
|
||||
// cursor. nsMouseWheelTransaction tracks the frame currently being
|
||||
|
@ -2717,18 +2718,23 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool checkIfScrollableX =
|
||||
aEvent->deltaX && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS);
|
||||
bool checkIfScrollableY =
|
||||
aEvent->deltaY && (aOptions & PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS);
|
||||
|
||||
nsIScrollableFrame* frameToScroll = nullptr;
|
||||
for (nsIFrame* scrollFrame = aTargetFrame; scrollFrame;
|
||||
scrollFrame = GetParentFrameToScroll(scrollFrame)) {
|
||||
nsIFrame* scrollFrame =
|
||||
!(aOptions & START_FROM_PARENT) ? aTargetFrame :
|
||||
GetParentFrameToScroll(aTargetFrame);
|
||||
for (; scrollFrame; scrollFrame = GetParentFrameToScroll(scrollFrame)) {
|
||||
// Check whether the frame wants to provide us with a scrollable view.
|
||||
frameToScroll = scrollFrame->GetScrollTargetFrame();
|
||||
if (!frameToScroll) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// At computing scroll target for legacy mouse events, we should return
|
||||
// first scrollable element even when it's not scrollable to the direction.
|
||||
if (!aForDefaultAction) {
|
||||
if (!checkIfScrollableX && !checkIfScrollableY) {
|
||||
return frameToScroll;
|
||||
}
|
||||
|
||||
|
@ -2736,8 +2742,8 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
|||
bool hiddenForV = (NS_STYLE_OVERFLOW_HIDDEN == ss.mVertical);
|
||||
bool hiddenForH = (NS_STYLE_OVERFLOW_HIDDEN == ss.mHorizontal);
|
||||
if ((hiddenForV && hiddenForH) ||
|
||||
(aEvent->deltaY && !aEvent->deltaX && hiddenForV) ||
|
||||
(aEvent->deltaX && !aEvent->deltaY && hiddenForH)) {
|
||||
(checkIfScrollableY && !checkIfScrollableX && hiddenForV) ||
|
||||
(checkIfScrollableX && !checkIfScrollableY && hiddenForH)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2763,8 +2769,9 @@ nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
|
|||
|
||||
nsIFrame* newFrame = nsLayoutUtils::GetCrossDocParentFrame(
|
||||
aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
|
||||
return newFrame ?
|
||||
ComputeScrollTarget(newFrame, aEvent, aForDefaultAction) : nullptr;
|
||||
aOptions =
|
||||
static_cast<ComputeScrollTargetOptions>(aOptions & ~START_FROM_PARENT);
|
||||
return newFrame ? ComputeScrollTarget(newFrame, aEvent, aOptions) : nullptr;
|
||||
}
|
||||
|
||||
nsSize
|
||||
|
@ -2908,18 +2915,17 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
|||
return;
|
||||
}
|
||||
|
||||
// XXX When the scroll target came from the wheel transaction manager, there
|
||||
// may be another scrollable element in its ancestors. Then, probably we
|
||||
// shouldn't set overflowDelta even if the event doesn't cause scroll
|
||||
// actually because the non-zero overflowDelta could cause another action
|
||||
// such as "back" or "forward" in the history.
|
||||
|
||||
nsIntPoint overflow;
|
||||
aScrollableFrame->ScrollBy(actualDevPixelScrollAmount,
|
||||
nsIScrollableFrame::DEVICE_PIXELS,
|
||||
mode, &overflow, origin);
|
||||
|
||||
if (isDeltaModePixel) {
|
||||
if (!scrollFrameWeak.IsAlive()) {
|
||||
// If the scroll causes changing the layout, we can think that the event
|
||||
// has been completely consumed by the content. Then, users probably don't
|
||||
// want additional action.
|
||||
aEvent->overflowDeltaX = aEvent->overflowDeltaY = 0;
|
||||
} else if (isDeltaModePixel) {
|
||||
aEvent->overflowDeltaX = overflow.x;
|
||||
aEvent->overflowDeltaY = overflow.y;
|
||||
} else {
|
||||
|
@ -2931,19 +2937,30 @@ nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
|||
|
||||
// If CSS overflow properties caused not to scroll, the overflowDelta* values
|
||||
// should be same as delta* values since they may be used as gesture event by
|
||||
// widget.
|
||||
if (overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
aEvent->overflowDeltaX = aEvent->deltaX;
|
||||
}
|
||||
if (overflowStyle.mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
|
||||
aEvent->overflowDeltaY = aEvent->deltaY;
|
||||
// widget. However, if there is another scrollable element in the ancestor
|
||||
// along the axis, probably users don't want the operation to cause
|
||||
// additional action such as moving history. In such case, overflowDelta
|
||||
// values should stay zero.
|
||||
if (scrollFrameWeak.IsAlive()) {
|
||||
if (aEvent->deltaX &&
|
||||
overflowStyle.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN &&
|
||||
!ComputeScrollTarget(scrollFrame, aEvent,
|
||||
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS)) {
|
||||
aEvent->overflowDeltaX = aEvent->deltaX;
|
||||
}
|
||||
if (aEvent->deltaY &&
|
||||
overflowStyle.mVertical == NS_STYLE_OVERFLOW_HIDDEN &&
|
||||
!ComputeScrollTarget(scrollFrame, aEvent,
|
||||
COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS)) {
|
||||
aEvent->overflowDeltaY = aEvent->deltaY;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(aEvent->overflowDeltaX == 0 ||
|
||||
(aEvent->overflowDeltaX > 0) == (actualDevPixelScrollAmount.x > 0),
|
||||
(aEvent->overflowDeltaX > 0) == (aEvent->deltaX > 0),
|
||||
"The sign of overflowDeltaX is different from the scroll direction");
|
||||
NS_ASSERTION(aEvent->overflowDeltaY == 0 ||
|
||||
(aEvent->overflowDeltaY > 0) == (actualDevPixelScrollAmount.y > 0),
|
||||
(aEvent->overflowDeltaY > 0) == (aEvent->deltaY > 0),
|
||||
"The sign of overflowDeltaY is different from the scroll direction");
|
||||
|
||||
WheelPrefs::GetInstance()->CancelApplyingUserPrefsFromOverflowDelta(aEvent);
|
||||
|
@ -3272,7 +3289,8 @@ nsEventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
// For scrolling of default action, we should honor the mouse wheel
|
||||
// transaction.
|
||||
nsIScrollableFrame* scrollTarget =
|
||||
ComputeScrollTarget(aTargetFrame, wheelEvent, true);
|
||||
ComputeScrollTarget(aTargetFrame, wheelEvent,
|
||||
COMPUTE_DEFAULT_ACTION_TARGET);
|
||||
wheelEvent->overflowDeltaX = wheelEvent->deltaX;
|
||||
wheelEvent->overflowDeltaY = wheelEvent->deltaY;
|
||||
WheelPrefs::GetInstance()->
|
||||
|
@ -5171,7 +5189,8 @@ nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
|
|||
// of default action. The transaction should be used only for the default
|
||||
// action.
|
||||
nsIScrollableFrame* scrollTarget =
|
||||
aESM->ComputeScrollTarget(aTargetFrame, aEvent, false);
|
||||
aESM->ComputeScrollTarget(aTargetFrame, aEvent,
|
||||
COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET);
|
||||
nsIFrame* frame = do_QueryFrame(scrollTarget);
|
||||
nsPresContext* pc =
|
||||
frame ? frame->PresContext() : aTargetFrame->PresContext();
|
||||
|
|
|
@ -468,15 +468,41 @@ protected:
|
|||
*
|
||||
* @param aTargetFrame The event target of the wheel event.
|
||||
* @param aEvent The handling mouse wheel event.
|
||||
* @param aForDefaultAction Whether this uses wheel transaction or not.
|
||||
* If true, returns the latest scrolled frame if
|
||||
* there is it. Otherwise, the nearest ancestor
|
||||
* scrollable frame from aTargetFrame.
|
||||
* @param aOptions The options for finding the scroll target.
|
||||
* Callers should use COMPUTE_*.
|
||||
* @return The scrollable frame which should be scrolled.
|
||||
*/
|
||||
// These flags are used in ComputeScrollTarget(). Callers should use
|
||||
// COMPUTE_*.
|
||||
enum
|
||||
{
|
||||
PREFER_MOUSE_WHEEL_TRANSACTION = 1,
|
||||
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS = 2,
|
||||
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS = 4,
|
||||
START_FROM_PARENT = 8
|
||||
};
|
||||
enum ComputeScrollTargetOptions
|
||||
{
|
||||
// At computing scroll target for legacy mouse events, we should return
|
||||
// first scrollable element even when it's not scrollable to the direction.
|
||||
COMPUTE_LEGACY_MOUSE_SCROLL_EVENT_TARGET = 0,
|
||||
// Default action prefers the scrolled element immediately before if it's
|
||||
// still under the mouse cursor. Otherwise, it prefers the nearest
|
||||
// scrollable ancestor which will be scrolled actually.
|
||||
COMPUTE_DEFAULT_ACTION_TARGET =
|
||||
(PREFER_MOUSE_WHEEL_TRANSACTION |
|
||||
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS |
|
||||
PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS),
|
||||
// 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)
|
||||
};
|
||||
nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
|
||||
mozilla::widget::WheelEvent* aEvent,
|
||||
bool aForDefaultAction);
|
||||
ComputeScrollTargetOptions aOptions);
|
||||
|
||||
/**
|
||||
* GetScrollAmount() returns the scroll amount in app uints of one line or
|
||||
|
|
Загрузка…
Ссылка в новой задаче