Bug 1301290 - Position resizer above own content but beneath overlapping content. r=mats
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -60,9 +60,11 @@ skip-if = (buildapp == 'b2g' && (toolkit
[test_textarea_resize.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(resizing textarea not available in b2g) b2g-debug(resizing textarea not available in b2g) b2g-desktop(resizing textarea not available in b2g)
[test_bug961363.html]
skip-if = toolkit == 'android' # Bug 1021644 - Fails when pushed into a different chunk on Android
[test_bug1111995.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[test_select_vertical.html]
skip-if = e10s || buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # Bug 1170129 - vertical <select> popup not implemented for e10s # <select> elements don't use an in-page popup on B2G/Android
+[test_bug1301290.html]
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(resizing textarea not available in b2g) b2g-debug(resizing textarea not available in b2g) b2g-desktop(resizing textarea not available in b2g)
[test_bug1305282.html]
new file mode 100644
--- /dev/null
+++ b/layout/forms/test/test_bug1301290.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test for Bug 1301290</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style type="text/css">
+ .blue, .green {
+ border: none;
+ box-sizing: border-box;
+ display: block;
+ width: 200px;
+ height: 100px;
+ overflow: scroll;
+ resize: both;
+ }
+
+ .blue {
+ background: blue;
+ }
+
+ .green {
+ background: green;
+ margin-top: -100px;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="blue"></div>
+ <textarea class="green" id="textarea"></textarea>
+ <script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(() => SimpleTest.executeSoon(function() {
+ var textarea = $("textarea");
+ var rect = textarea.getBoundingClientRect();
+
+ synthesizeMouse(textarea, rect.width - 10, rect.height - 10, { type: "mousedown" });
+ synthesizeMouse(textarea, rect.width + 40, rect.height + 40, { type: "mousemove" });
+ synthesizeMouse(textarea, rect.width + 40, rect.height + 40, { type: "mouseup" });
+
+ var newrect = textarea.getBoundingClientRect();
+ ok(newrect.width > rect.width, "width did not increase");
+ ok(newrect.height > rect.height, "height did not increase");
+ SimpleTest.finish();
+ }));
+ </script>
+ </body>
+</html>
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2932,17 +2932,17 @@ ScrollFrameHelper::ScrollToImpl(nsPoint
if (docShell) {
docShell->NotifyScrollObservers();
}
}
static int32_t
MaxZIndexInList(nsDisplayList* aList, nsDisplayListBuilder* aBuilder)
{
- int32_t maxZIndex = 0;
+ int32_t maxZIndex = -1;
for (nsDisplayItem* item = aList->GetBottom(); item; item = item->GetAbove()) {
maxZIndex = std::max(maxZIndex, item->ZIndex());
}
return maxZIndex;
}
// Finds the max z-index of the items in aList that meet the following conditions
// 1) have z-index auto or z-index >= 0.
@@ -2961,16 +2961,30 @@ MaxZIndexInListOfItemsContainedInFrame(n
}
if (nsLayoutUtils::IsProperAncestorFrame(aFrame, itemFrame)) {
maxZIndex = std::max(maxZIndex, item->ZIndex());
}
}
return maxZIndex;
}
+template<class T>
+static void
+AppendInternalItemToTop(const nsDisplayListSet& aLists,
+ T* aItem,
+ int32_t aZIndex)
+{
+ if (aZIndex >= 0) {
+ aItem->SetOverrideZIndex(aZIndex);
+ aLists.PositionedDescendants()->AppendNewToTop(aItem);
+ } else {
+ aLists.Content()->AppendNewToTop(aItem);
+ }
+}
+
static const uint32_t APPEND_OWN_LAYER = 0x1;
static const uint32_t APPEND_POSITIONED = 0x2;
static const uint32_t APPEND_SCROLLBAR_CONTAINER = 0x4;
static void
AppendToTop(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists,
nsDisplayList* aSource, nsIFrame* aSourceFrame, uint32_t aFlags)
{
@@ -2986,23 +3000,18 @@ AppendToTop(nsDisplayListBuilder* aBuild
} else {
newItem = new (aBuilder) nsDisplayWrapList(aBuilder, aSourceFrame, aSource);
}
if (aFlags & APPEND_POSITIONED) {
// We want overlay scrollbars to always be on top of the scrolled content,
// but we don't want them to unnecessarily cover overlapping elements from
// outside our scroll frame.
- nsDisplayList* positionedDescendants = aLists.PositionedDescendants();
- if (!positionedDescendants->IsEmpty()) {
- newItem->SetOverrideZIndex(MaxZIndexInList(positionedDescendants, aBuilder));
- positionedDescendants->AppendNewToTop(newItem);
- } else {
- aLists.Outlines()->AppendNewToTop(newItem);
- }
+ int32_t zIndex = MaxZIndexInList(aLists.PositionedDescendants(), aBuilder);
+ AppendInternalItemToTop(aLists, newItem, zIndex);
} else {
aLists.BorderBackground()->AppendNewToTop(newItem);
}
}
struct HoveredStateComparator
{
bool Equals(nsIFrame* A, nsIFrame* B) const {
@@ -3568,27 +3577,19 @@ ScrollFrameHelper::BuildDisplayList(nsDi
!mWillBuildScrollableLayer &&
aBuilder->IsBuildingLayerEventRegions())
{
inactiveRegionItem = new (aBuilder) nsDisplayLayerEventRegions(aBuilder, mScrolledFrame);
inactiveRegionItem->AddInactiveScrollPort(mScrollPort + aBuilder->ToReferenceFrame(mOuter));
}
if (inactiveRegionItem) {
- nsDisplayList* positionedDescendants = scrolledContent.PositionedDescendants();
- nsDisplayList* destinationList = nullptr;
- int32_t zindex =
- MaxZIndexInListOfItemsContainedInFrame(positionedDescendants, mOuter);
- if (zindex >= 0) {
- destinationList = positionedDescendants;
- inactiveRegionItem->SetOverrideZIndex(zindex);
- } else {
- destinationList = scrolledContent.Outlines();
- }
- destinationList->AppendNewToTop(inactiveRegionItem);
+ int32_t zIndex =
+ MaxZIndexInListOfItemsContainedInFrame(scrolledContent.PositionedDescendants(), mOuter);
+ AppendInternalItemToTop(scrolledContent, inactiveRegionItem, zIndex);
}
if (aBuilder->ShouldBuildScrollInfoItemsForHoisting()) {
aBuilder->AppendNewScrollInfoItemForHoisting(
new (aBuilder) nsDisplayScrollInfoLayer(aBuilder, mScrolledFrame,
mOuter));
}
}