I think we definitely want to make scrolled items have coordinates
relative to their scrolled root.
The problem with just doing this, and applying a transform to the
context when drawing them is that it makes visibility calcuations much
harder.
nsDisplayList::ComputeVisibility assumes that all child items are in the
same coordinate space, and changing this would be difficult.
I think we instead need to make sure that all scrolled items are within
a 'wrapper' item and have that as the point where we change coordinate
systems. This is what we are currently doing for nsDisplayTransform.
Things that need to be done:
Make sure we always build nsDisplayScrollLayer
(
http://mxr.mozilla.org/mozilla-central/source/layout/generic/nsGfxScrollFrame.cpp#2310)
for active scroll frames, instead of only when we have async scrolling.
Convert nsDisplayScrollLayer to be inherit directly from nsDisplayItem
instead of nsDisplayWrapList. nsDisplayWrapList implement
GetSameCoordinateSystemChildren
(
http://mxr.mozilla.org/mozilla-central/source/layout/base/nsDisplayList.h#2391)
which we *don't* want. We just want to implement GetChildren() instead.
Make nsDisplayScrollLayer::HitTest, BuildLayer, ComputeVisibility etc
handle the change in coordinate space. nsDisplayTransform does this by
adding a translate into the computed matrix in
nsDisplayTransform::GetTransform. I think we'll just want to manually
shift the visible rect/hit test rect before passing it on to our children.
Make children of the scrolled content choose the scrolled root as their
reference point. We currently do this calculation in two places:
http://mxr.mozilla.org/mozilla-central/source/layout/base/nsDisplayList.h#195,
and
http://mxr.mozilla.org/mozilla-central/source/layout/base/nsDisplayList.h#519.
Note that these have special handling for transforms, and we need to add
the equivalent for scrolled roots.
This function should be what decides if a scroll frame should be a
reference frame for its children:
http://mxr.mozilla.org/mozilla-central/source/layout/base/nsLayoutUtils.cpp#1079
Hopefully that helps! Let me know if you have any more questions :)
- Matt
>> On Thu, Aug 22, 2013 at 10:34 PM, Thinker K.F. Li <
thi...@codemud.net>wrote:
>>
>>> After a discussion with Kan-Ru, I get more about the problem itself.
>>> Since the positions of all display items in a nsIScrollableFrame are
>>> relative to nsIScrollableFrame itself. By keeping display itmes in the
>>> cache and applying a translation (shift) to the gfxContext before
>>> calling paint() on display items, we don't need to change the display
>>> items in the cache. Of course, invalidate regions should be translated
>>> too.
>>>
>> The offset to apply to each display item would have to be stored somewhere,
>> and then those offsets will all have to be updated.
>>
>> It seems simpler and more efficient to me to make the display items be
>> relative to their active scrolled root, then nothing will have to be
>> updated. Matt can explain more of the details of what we think needs to be
>> done.