Bug 70395 - REGRESSION: rtl horizontal scrollbar / resize bug - Body shifts on resize when scrolled all the way to the left
Summary: REGRESSION: rtl horizontal scrollbar / resize bug - Body shifts on resize whe...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Mac OS X 10.6
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on: 71236
Blocks:
  Show dependency treegraph
 
Reported: 2011-10-18 20:08 PDT by numero2dos
Modified: 2011-12-02 13:58 PST (History)
14 users (show)

See Also:


Attachments
Simple Repro File (374 bytes, text/html)
2011-10-18 20:08 PDT, numero2dos
no flags Details
patch (33.79 KB, patch)
2011-10-21 15:47 PDT, Xiaomei Ji
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
wip (13.92 KB, patch)
2011-10-26 18:53 PDT, Xiaomei Ji
no flags Details | Formatted Diff | Diff
patch w/ layout test (48.64 KB, patch)
2011-10-27 18:56 PDT, Xiaomei Ji
no flags Details | Formatted Diff | Diff
patch w/ layout test (37.75 KB, patch)
2011-11-01 17:15 PDT, Xiaomei Ji
no flags Details | Formatted Diff | Diff
patch w/ layout test (37.78 KB, patch)
2011-11-02 11:00 PDT, Xiaomei Ji
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
patch w/ layout test (37.35 KB, patch)
2011-11-02 13:46 PDT, Xiaomei Ji
tony: review+
Details | Formatted Diff | Diff
WIP (2.39 KB, patch)
2011-11-10 16:14 PST, Xiaomei Ji
no flags Details | Formatted Diff | Diff
patch w/ layout test (17.28 KB, patch)
2011-11-11 17:10 PST, Xiaomei Ji
tony: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description numero2dos 2011-10-18 20:08:28 PDT
Created attachment 111555 [details]
Simple Repro File

NOTE: I am not sure about the webkit version. In Chrome, navigator.userAgent has  AppleWebKit/535.1

What steps will reproduce the problem?
1. Open RtlContentShift.html
2. Resize browser so that the content window is less than 500 px wide.
3. Scroll to the left all the way.
4. Resize browser, increasing the width.

Browsers tested:
     Chrome 13.0.782.112: FAIL
     Safari 5: FAIL
     Firefox 7.x: N/A - scrolling appears to be disabled in rtl
     IE 7: MIXED - the body still covers the whole window, but the rest of the layout is not correct
     IE 8/9: OK

What is the expected result?
The body still covers the entire window, since it has width:100%;height:100%

What happens instead?
The body is shifted over by the amount that the window was resized.
Comment 2 Xiaomei Ji 2011-10-19 16:17:13 PDT
It appears regressed in http://trac.webkit.org/changeset/76395/trunk.

If I remove the condition checking in ScrollAnimator::scrollToOffsetWithoutAnimation(), the test case works ok (tested in chromium, Safari in Mac works fine since it has its own ScrollAnimatorMac.mm, in which, ScollTo() is always called without condition).

But I am not sure removing the condition checking is the right fix.
Would appreciate comments from mitz (who added ScrollView.cpp#L586) and/or weinig (who is more familiar with ScrollAnimation).

The reason of the failure is that:
when horizontal scrollbar is at leftmost, ScrollAnimator::m_currentPosX/Y == 0.

when enlarge browser size, following is part of the call stack:
        ......
 	ScrollView::updateScrollbars(...)
 	ScrollView::setScrollOrigin(...)
 	FrameView::adjustViewSize(...)
        .....

Assume m_scrollOrigin.x was 200 previously, and is 150 now, at inline http://trac.webkit.org/browser/trunk/Source/WebCore/platform/ScrollView.cpp#L586
desiredOffset is the old scroll offset, which is -200, and adjustScrollPositionWithinRange() will adjust it within the range of (-150, 0) using current m_scrollOrigin, and scrollPoint is always >= 0.

After the above line, the scrollPoint passed to ScrollAnimator::scrollToOffsetWithoutAnimation() is (0, 0), since it is the same as m_currentPosX/Y, notifyPositionChanged() will *not* be called, so FrameView::scrollTo() using current m_scrollOrigin etc. are not called, caused wrong/mis-match of scroll position with document body.

It looks to me that ScrollAnimator::m_currentPosX and the parameter passing to ScrollAnimator::scrollToOffsetWithoutAnimation() are positive values even the scroll positions are negative values for RTL pages. I do not know the reason, but if that is the case, ScrollView.cpp#L58 seems doing the right thing, and we probably have to always scroll without condition checking.
Comment 3 Tony Chang 2011-10-19 16:24:19 PDT
For reference, that code was to fix a regression caught by a chromium browser test.  The original bug is here: http://code.google.com/p/chromium/issues/detail?id=70408
Comment 4 Xiaomei Ji 2011-10-19 16:56:10 PDT
The condition at following line seems wrong to me.
http://trac.webkit.org/browser/trunk/Source/WebCore/platform/ScrollView.cpp#L587
I think we should compare adjustScrollPositionWithinRange(IntPoint(desiredOffset)) with scrollPosition() which are in the same coordinates (both negative for RTL pages).

After which, we do not (and should not) need to check the condition anymore in ScrollAnimator::scrollToOffsetWithoutAnimation().

I will need to run chromium's test case tony mentioned in #3.


Index: ScrollAnimator.cpp
===================================================================
--- ScrollAnimator.cpp  (revision 96967)
+++ ScrollAnimator.cpp  (working copy)
@@ -74,11 +74,11 @@

 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
 {
-    if (m_currentPosX != offset.x() || m_currentPosY != offset.y()) {
+    //if (m_currentPosX != offset.x() || m_currentPosY != offset.y()) {
         m_currentPosX = offset.x();
         m_currentPosY = offset.y();
         notifyPositionChanged();
-    }
+    //}
 }

 bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
Index: ScrollView.cpp
===================================================================
--- ScrollView.cpp      (revision 96967)
+++ ScrollView.cpp      (working copy)
@@ -582,7 +582,8 @@
     }

     IntPoint scrollPoint = adjustScrollPositionWithinRange(IntPoint(desiredOffs
et)) + IntSize(m_scrollOrigin.x(), m_scrollOrigin.y());
-    if (scrollPoint != scrollPosition())
+//    if (scrollPoint != scrollPosition())
+    if (adjustScrollPositionWithinRange(IntPoint(desiredOffset)) != scrollPosit
ion())
         ScrollableArea::scrollToOffsetWithoutAnimation(scrollPoint);

     // Make sure the scrollbar offsets are up to date.
Comment 5 Xiaomei Ji 2011-10-19 18:32:19 PDT
hm... with ScrollAnimator change, but with or without the ScrollView change mentioned in comment #4, RenderViewTest.OnNavStateChanged passed in my local chrome win build.
Comment 6 Xiaomei Ji 2011-10-19 22:38:33 PDT
(In reply to comment #5)
> hm... with ScrollAnimator change, but with or without the ScrollView change mentioned in comment #4, RenderViewTest.OnNavStateChanged passed in my local chrome win build.

For  LTR page,
http://trac.webkit.org/browser/trunk/Source/WebCore/platform/ScrollView.cpp#L587 filters those un-necessary scrolls correctly, that is why the test pass even without change to ScrolView.cpp as in comment #4.
Comment 7 Xiaomei Ji 2011-10-21 15:47:01 PDT
Created attachment 112038 [details]
patch

The test here does not add much value because:
1. Mac in safari works fine previously.
2. loading the test itself in Safari in Mac resize the browser window, but the png result seems not reflecting that (is it a DRT problem?). Without png result reflecting window resize, the test is not really useful.
3. Mac buildbot does not run png test. Chrome does, but chrome does not support resize top-level window, so this test wont be really useful to catch regression.

I'd appreciate if you have any suggestions on testing.
Comment 8 Tony Chang 2011-10-21 16:08:11 PDT
Comment on attachment 112038 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=112038&action=review

What do you mean that chromium DRT doesn't support resizing the main window?  It looks like chromium passes the fast/dom/Window/window-resize* tests.

> LayoutTests/fast/dom/rtl-scroll-to-leftmost-and-resize.html:9
> +    window.resizeTo(350, window.innerHeight);

Does the bug repro if you resize the window smaller then resize it back to 800x600?
Comment 9 WebKit Review Bot 2011-10-21 16:10:01 PDT
Comment on attachment 112038 [details]
patch

Attachment 112038 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10199061

New failing tests:
fast/dom/horizontal-scrollbar-in-rtl.html
Comment 10 Xiaomei Ji 2011-10-21 16:39:54 PDT
(In reply to comment #8)
> (From update of attachment 112038 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=112038&action=review
> 
> What do you mean that chromium DRT doesn't support resizing the main window?  It looks like chromium passes the fast/dom/Window/window-resize* tests.

Good point!
I did not try chromium DRT, I mean chromium itself does not support top-level window resize. 
If I load this test in chromium directly, it wont resize the window.
I will try DRT.

> 
> > LayoutTests/fast/dom/rtl-scroll-to-leftmost-and-resize.html:9
> > +    window.resizeTo(350, window.innerHeight);
> 
> Does the bug repro if you resize the window smaller then resize it back to 800x600?

the bug repro if I do it manually.
Comment 11 Xiaomei Ji 2011-10-26 18:53:38 PDT
Created attachment 112630 [details]
wip
Comment 12 Xiaomei Ji 2011-10-27 18:56:23 PDT
Created attachment 112805 [details]
patch w/ layout test
Comment 13 Tony Chang 2011-10-28 17:22:19 PDT
Comment on attachment 112805 [details]
patch w/ layout test

I don't know this code well enough to review this patch, however, I have 2 suggestions:
1) Do a refactor patch first that adds the getter methods and makes the member variables private.  This will make the patch much smaller.
2) I don't really like m_scrollOriginChanged.  It's hard to tell when you're supposed to set it and when it's valid to read it.  It would be more clear to pass the bool around where needed.
Comment 14 Xiaomei Ji 2011-10-28 17:51:31 PDT
(In reply to comment #13)
> (From update of attachment 112805 [details])
> I don't know this code well enough to review this patch, however, I have 2 suggestions:
> 1) Do a refactor patch first that adds the getter methods and makes the member variables private.  This will make the patch much smaller.

Good suggestion!

> 2) I don't really like m_scrollOriginChanged.  It's hard to tell when you're supposed to set it and when it's valid to read it.  It would be more clear to pass the bool around where needed.

it would be nice to pass the bool around. but the problem is updateScrollbar() might not be called Synchronously when m_scrollOrigin changes, besides m_scrollOrigin could be changed in RenderLayer as well.

I tried to modify updateScrollbar() with an extra bool parameter, and change the caller side to pass true/false depends on the functionality. But that introduce more un-necessary scrolling.
Comment 15 Xiaomei Ji 2011-10-28 17:56:26 PDT
(In reply to comment #14)
> (In reply to comment #13)
> > (From update of attachment 112805 [details] [details])
> > I don't know this code well enough to review this patch, however, I have 2 suggestions:
> > 1) Do a refactor patch first that adds the getter methods and makes the member variables private.  This will make the patch much smaller.
> 
> Good suggestion!

BTW, changing m_scrollOrigin to be private is due to the introduction of m_scrollOriginChanged.
the setter will update m_scrollOriginChanged as well. If there is a better way to not introduce m _scrollOriginChanged, m_scrollOrigin does not need to be private.
Comment 16 Tony Chang 2011-10-31 09:54:01 PDT
(In reply to comment #15)
> (In reply to comment #14)
> > (In reply to comment #13)
> > > (From update of attachment 112805 [details] [details] [details])
> > > I don't know this code well enough to review this patch, however, I have 2 suggestions:
> > > 1) Do a refactor patch first that adds the getter methods and makes the member variables private.  This will make the patch much smaller.
> > 
> > Good suggestion!
> 
> BTW, changing m_scrollOrigin to be private is due to the introduction of m_scrollOriginChanged.
> the setter will update m_scrollOriginChanged as well. If there is a better way to not introduce m _scrollOriginChanged, m_scrollOrigin does not need to be private.

I think it's ok to make m_scrollOrigin private in a refactor patch and add m_scrollOriginChanged in the bug fix patch.

If having m_scrollOriginChanged is unavoidable, maybe name it to be more specific like m_scrollOriginChangedDuringResize or something.
Comment 17 Xiaomei Ji 2011-11-01 17:15:24 PDT
Created attachment 113261 [details]
patch w/ layout test

I did not change the name of m_scrollOriginChanged.
resize cause it to change, but resize probably is not the only way cause it to change.
Comment 18 Tony Chang 2011-11-01 17:31:52 PDT
Comment on attachment 113261 [details]
patch w/ layout test

View in context: https://bugs.webkit.org/attachment.cgi?id=113261&action=review

Just a drive by review.  I don't really understand how the various Scroll* classes fit together.

> Source/WebCore/platform/ScrollAnimator.cpp:82
>          m_currentPosX = offset.x();
>          m_currentPosY = offset.y();
>          notifyPositionChanged();

Nit: unindent

> Source/WebCore/platform/ScrollableArea.cpp:73
> +    } else
> +        m_scrollOriginChanged = false;

Is this else necessary?  If so, why don't we set m_scrollOriginChanged = false in setScrollOrigin(X|Y)?
Comment 19 Xiaomei Ji 2011-11-02 11:00:19 PDT
Created attachment 113335 [details]
patch w/ layout test

updated per comment #18. Thanks for the quick drive-by review.



(In reply to comment #18)
> (From update of attachment 113261 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=113261&action=review
> 
> Just a drive by review.  I don't really understand how the various Scroll* classes fit together.
> 
> > Source/WebCore/platform/ScrollAnimator.cpp:82
> >          m_currentPosX = offset.x();
> >          m_currentPosY = offset.y();
> >          notifyPositionChanged();
> 
> Nit: unindent

done.

> 
> > Source/WebCore/platform/ScrollableArea.cpp:73
> > +    } else
> > +        m_scrollOriginChanged = false;
> 
> Is this else necessary?  If so, why don't we set m_scrollOriginChanged = false in setScrollOrigin(X|Y)?

That is a good question.
Look at it again, I think the same as m_scrollOriginChanged is only accessed in ScrollView::updateScrollbars(), its value should be only reset to false in ScrollView::updateScrollbars(), so that ScrollView::updateScrollbars() is able to catch the once changed m_scrollOrigin and set ScrollAnimator::m_currentPosX|Y correctly.

As to the reason why not set m_scrollOriginChanged = false in setScrollOrigin(X|Y) is that: if you setScrollOriginX with a different scrollOriginX value, but then setScrollOriginY with the same scrollOriginY value, resetting m_scrollOriginChanged = false in setScrollOriginY will override the m_scrollOriginChanged = true value set in setScrollOriginX.
Comment 20 WebKit Review Bot 2011-11-02 11:35:56 PDT
Comment on attachment 113335 [details]
patch w/ layout test

Attachment 113335 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/10148313

New failing tests:
fast/block/positioning/auto/vertical-rl/007.html
fast/block/basic/truncation-rtl.html
fast/multicol/vertical-rl/float-avoidance.html
fast/multicol/vertical-rl/column-rules.html
fast/multicol/vertical-rl/column-break-with-balancing.html
Comment 21 Xiaomei Ji 2011-11-02 13:46:03 PDT
Created attachment 113368 [details]
patch w/ layout test

fix cr-linux failure.
Comment 22 Tony Chang 2011-11-03 15:39:09 PDT
scottbyer or sail might be able to give an informal review.
Comment 23 Scott Byer 2011-11-03 16:28:16 PDT
This patch makes sense to me; I like getting the condition check in one place instead of having it in two. It looks correct as far as I understand the scrolling code (which isn't really far enough yet).
Comment 24 Xiaomei Ji 2011-11-03 17:22:55 PDT
(In reply to comment #23)
> This patch makes sense to me; I like getting the condition check in one place instead of having it in two.

which condition check you meant? m_scrollOriginChanged()?

I've emailed Sam (weinig) and Dan (mitz) too, hope they could give it a review.

> It looks correct as far as I understand the scrolling code (which isn't really far enough yet).
Comment 25 Tony Chang 2011-11-07 15:01:19 PST
Comment on attachment 113368 [details]
patch w/ layout test

This seems safe and well scoped.

Please add suppressions in test_expectations.txt so the Linux/Win bots don't go red.
Comment 26 Xiaomei Ji 2011-11-08 14:22:42 PST
Committed r99616: <http://trac.webkit.org/changeset/99616>
Comment 27 Xiaomei Ji 2011-11-08 17:23:02 PST
I do not know what went wrong (I tried test in Safari Mac and remembered it works fine there).
But the bug did reproduce in Safari Mac, and it also reproduce in chromium mac.
r99616 fix the problem in chromium win/linux, but it did not fix it in chromium mac and safari mac.
Comment 28 Xiaomei Ji 2011-11-08 17:28:58 PST
Comment on attachment 113368 [details]
patch w/ layout test

clear flag.
Comment 29 Xiaomei Ji 2011-11-08 17:32:14 PST
reopened for Mac port and cr-mac.
(r99616 fix the problem in chromium win/linux, but it did not fix it in chromium mac and safari mac.)
Comment 30 Xiaomei Ji 2011-11-10 16:14:07 PST
Created attachment 114594 [details]
WIP

it fixes the problem in Safari in Mac (tried manually).
One thing I am not sure of is that there are several callers of scrollToOffsetWithoutAnimation(), some of them are passing different scroll offsets, but probably not all of them. Without offset checking, it might trigger unnecessary "notifyPositionChanged()".
Comment 31 Xiaomei Ji 2011-11-11 17:10:46 PST
Created attachment 114803 [details]
patch w/ layout test

One thing I am not sure of is that there are several callers of scrollToOffsetWithoutAnimation(), some of them are passing different scroll offsets, but probably not all of them. Without offset checking, it might trigger unnecessary "notifyPositionChanged()".
Comment 32 Xiaomei Ji 2011-11-18 15:22:53 PST
Committed r100819: <http://trac.webkit.org/changeset/100819>
Comment 33 Beth Dakin 2011-11-29 12:30:02 PST
This change causes a new assertion failure in Debug builds. I am filing a bug for it now.
Comment 34 Beth Dakin 2011-11-29 12:35:21 PST
https://bugs.webkit.org/show_bug.cgi?id=73348 REGRESSION: Assertion when loading a page with a scrollable RenderLayer
Comment 35 Eric Seidel (no email) 2011-12-02 13:58:46 PST
This appears to be missing results for Lion: fast/dom/rtl-scroll-to-leftmost-and-resize.html