From 6fb059abcc8ca05e0a79d8c0b019344dbd2579ba Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Mon, 24 Feb 2014 23:42:11 -0600 Subject: [PATCH] Bug 976370. Move overlay scrollbar display items above scroll layer items for the same scroll frame. r=roc This has two desirable side effects. The first and more important is that it prevents a scrollbar item from sitting between scroll layer items and preventing them from merging into one and thus preventing the creation of an async scrollable layer. The second is that scrollbars should be on top of the content they are scrolling in general, and this will make that happen in more cases. --- layout/base/nsDisplayList.cpp | 36 +++++++++++++++++++++++++++++++++++ layout/base/nsDisplayList.h | 1 + 2 files changed, 37 insertions(+) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 89a27a58ef02..b4a1014580d6 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1004,6 +1004,31 @@ TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder) return opaqueClipped; } +/* Checks if aPotentialScrollItem is a scroll layer item and aPotentialScrollbarItem + * is an overlay scrollbar item for the same scroll frame. + */ +static bool +IsScrollLayerItemAndOverlayScrollbarForScrollFrame( + nsDisplayItem* aPotentialScrollItem, nsDisplayItem* aPotentialScrollbarItem) +{ + if (aPotentialScrollItem->GetType() == nsDisplayItem::TYPE_SCROLL_LAYER && + aPotentialScrollbarItem && + aPotentialScrollbarItem->GetType() == nsDisplayItem::TYPE_OWN_LAYER && + LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars)) { + nsDisplayScrollLayer* scrollItem = + static_cast(aPotentialScrollItem); + nsDisplayOwnLayer* layerItem = + static_cast(aPotentialScrollbarItem); + if ((layerItem->GetFlags() & + (nsDisplayOwnLayer::VERTICAL_SCROLLBAR | + nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR)) && + layerItem->Frame()->GetParent() == scrollItem->GetScrollFrame()) { + return true; + } + } + return false; +} + bool nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, @@ -1036,6 +1061,17 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, continue; } + // If an overlay scrollbar item is between a scroll layer item and the + // other scroll layer items that we need to merge with just move the + // scrollbar item up, that way it will be on top of the scrolled content + // and we can try to merge all the scroll layer items. + if (IsScrollLayerItemAndOverlayScrollbarForScrollFrame(item, belowItem)) { + elements[i] = belowItem; + elements[i-1] = item; + i++; + continue; + } + if (list && item->ShouldFlattenAway(aBuilder)) { // The elements on the list >= i no longer serve any use. elements.SetLength(i); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index be5de2252a4d..fa16d73a83fc 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2688,6 +2688,7 @@ public: // Don't allow merging, each sublist must have its own layer return false; } + uint32_t GetFlags() { return mFlags; } NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER) private: uint32_t mFlags;