mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 05:30:29 +00:00
Fix scrollbars on subframes not directing APZ events to the correct scrollframe. (bug 1213324, r=tn)
This commit is contained in:
parent
3306b77a11
commit
fb84bcaa55
@ -29,3 +29,5 @@ skip-if = toolkit != 'gonk'
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_scroll_inactive_bug1190112.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_scroll_subframe_scrollbar.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
|
@ -0,0 +1,119 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test scrolling subframe scrollbars</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
p {
|
||||
width:200px;
|
||||
height:200px;
|
||||
border:solid 1px black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p id="subframe">
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
</p>
|
||||
<script clss="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
var DefaultEvent = {
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 0, deltaY: 1,
|
||||
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
|
||||
};
|
||||
|
||||
var ScrollbarWidth = 0;
|
||||
|
||||
function test() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
var oldClientWidth = subframe.clientWidth;
|
||||
|
||||
subframe.style.overflow = 'auto';
|
||||
subframe.getBoundingClientRect();
|
||||
|
||||
waitForAllPaintsFlushed(function () {
|
||||
ScrollbarWidth = oldClientWidth - subframe.clientWidth;
|
||||
if (!ScrollbarWidth) {
|
||||
// Probably we have overlay scrollbars - abort the test.
|
||||
ok(true, "overlay scrollbars - skipping test");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ok(subframe.scrollHeight > subframe.clientHeight, "subframe should have scrollable content");
|
||||
testScrolling(subframe);
|
||||
});
|
||||
}
|
||||
|
||||
function testScrolling(subframe) {
|
||||
// Send a wheel event roughly to where we think the trackbar is. We pick a
|
||||
// point at the bottom, in the middle of the trackbar, where the slider is
|
||||
// unlikely to be (since it starts at the top).
|
||||
var posX = subframe.clientWidth + (ScrollbarWidth / 2);
|
||||
var posY = subframe.clientHeight - 20;
|
||||
|
||||
var oldScrollTop = subframe.scrollTop;
|
||||
|
||||
sendWheelAndPaint(subframe, posX, posY, DefaultEvent, function () {
|
||||
ok(subframe.scrollTop > oldScrollTop, "subframe should have scrolled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 0],
|
||||
['mousewheel.transaction.ignoremovedelay', 0]]
|
||||
}, function () {
|
||||
SimpleTest.waitForFocus(test);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -624,6 +624,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
|
||||
mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID),
|
||||
mCurrentScrollbarFlags(0),
|
||||
mCurrentScrollbarWillHaveLayer(false),
|
||||
mBuildCaret(aBuildCaret),
|
||||
mIgnoreSuppression(false),
|
||||
mHadToIgnoreSuppression(false),
|
||||
@ -3214,7 +3215,15 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
|
||||
} else {
|
||||
mHitRegion.Or(mHitRegion, borderBox);
|
||||
}
|
||||
if (aBuilder->GetAncestorHasApzAwareEventHandler()) {
|
||||
|
||||
if (aBuilder->IsBuildingNonLayerizedScrollbar() ||
|
||||
aBuilder->GetAncestorHasApzAwareEventHandler())
|
||||
{
|
||||
// Scrollbars may be painted into a layer below the actual layer they will
|
||||
// scroll, and therefore wheel events may be dispatched to the outer frame
|
||||
// instead of the intended scrollframe. To address this, we force a d-t-c
|
||||
// region on scrollbar frames that won't be placed in their own layer. See
|
||||
// bug 1213324 for details.
|
||||
mDispatchToContentHitRegion.Or(mDispatchToContentHitRegion, borderBox);
|
||||
} else if (aFrame->GetType() == nsGkAtoms::objectFrame) {
|
||||
// If the frame is a plugin frame and wants to handle wheel events as
|
||||
|
@ -312,6 +312,14 @@ public:
|
||||
*aOutScrollbarTarget = mCurrentScrollbarTarget;
|
||||
*aOutScrollbarFlags = mCurrentScrollbarFlags;
|
||||
}
|
||||
/**
|
||||
* Returns true if building a scrollbar, and the scrollbar will not be
|
||||
* layerized.
|
||||
*/
|
||||
bool IsBuildingNonLayerizedScrollbar() const {
|
||||
return mCurrentScrollbarTarget != FrameMetrics::NULL_SCROLL_ID &&
|
||||
!mCurrentScrollbarWillHaveLayer;
|
||||
}
|
||||
/**
|
||||
* Calling this setter makes us include all out-of-flow descendant
|
||||
* frames in the display list, wherever they may be positioned (even
|
||||
@ -753,15 +761,17 @@ public:
|
||||
class AutoCurrentScrollbarInfoSetter {
|
||||
public:
|
||||
AutoCurrentScrollbarInfoSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollTargetID,
|
||||
uint32_t aScrollbarFlags)
|
||||
uint32_t aScrollbarFlags, bool aWillHaveLayer)
|
||||
: mBuilder(aBuilder) {
|
||||
aBuilder->mCurrentScrollbarTarget = aScrollTargetID;
|
||||
aBuilder->mCurrentScrollbarFlags = aScrollbarFlags;
|
||||
aBuilder->mCurrentScrollbarWillHaveLayer = aWillHaveLayer;
|
||||
}
|
||||
~AutoCurrentScrollbarInfoSetter() {
|
||||
// No need to restore old values because scrollbars cannot be nested.
|
||||
mBuilder->mCurrentScrollbarTarget = FrameMetrics::NULL_SCROLL_ID;
|
||||
mBuilder->mCurrentScrollbarFlags = 0;
|
||||
mBuilder->mCurrentScrollbarWillHaveLayer = false;
|
||||
}
|
||||
private:
|
||||
nsDisplayListBuilder* mBuilder;
|
||||
@ -1156,6 +1166,7 @@ private:
|
||||
uint32_t mCurrentScrollbarFlags;
|
||||
BlendModeSet mContainedBlendModes;
|
||||
Preserves3DContext mPreserves3DCtx;
|
||||
bool mCurrentScrollbarWillHaveLayer;
|
||||
bool mBuildCaret;
|
||||
bool mIgnoreSuppression;
|
||||
bool mHadToIgnoreSuppression;
|
||||
|
@ -2699,17 +2699,20 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList
|
||||
buildingForChild(aBuilder, scrollParts[i],
|
||||
dirty + mOuter->GetOffsetTo(scrollParts[i]), true);
|
||||
|
||||
// Always create layers for overlay scrollbars so that we don't create a
|
||||
// giant layer covering the whole scrollport if both scrollbars are visible.
|
||||
bool isOverlayScrollbar = (flags != 0) && overlayScrollbars;
|
||||
bool createLayer = aCreateLayer || isOverlayScrollbar;
|
||||
|
||||
nsDisplayListBuilder::AutoCurrentScrollbarInfoSetter
|
||||
infoSetter(aBuilder, scrollTargetId, flags);
|
||||
infoSetter(aBuilder, scrollTargetId, flags, createLayer);
|
||||
nsDisplayListCollection partList;
|
||||
mOuter->BuildDisplayListForChild(
|
||||
aBuilder, scrollParts[i], dirty, partList,
|
||||
nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
|
||||
|
||||
// Always create layers for overlay scrollbars so that we don't create a
|
||||
// giant layer covering the whole scrollport if both scrollbars are visible.
|
||||
bool isOverlayScrollbar = (flags != 0) && overlayScrollbars;
|
||||
if (aCreateLayer || isOverlayScrollbar) {
|
||||
if (createLayer) {
|
||||
appendToTopFlags |= APPEND_OWN_LAYER;
|
||||
}
|
||||
if (aPositioned) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user