Tilted carets become normal if they're scroll out of and back into viewport
Categories
(Core :: DOM: Selection, defect, P4)
Tracking
()
Tracking | Status | |
---|---|---|
firefox84 | --- | fixed |
People
(Reporter: TYLin, Assigned: lonocvb)
References
(Blocks 1 open bug)
Details
Attachments
(3 files, 1 obsolete file)
Reporter | ||
Updated•4 years ago
|
Reporter | ||
Updated•4 years ago
|
Reporter | ||
Comment 1•4 years ago
|
||
Lono, I assign the bug to you per your message on #layout channel. Feel free to ask questions, or let us know if you are unable to work on this problem. Thanks!
The bug is caused by incorrect carets intersection under the onScrollEnd() -> UpdateCarets() -> UpdateCaretsForOverlappingTilt() without FlushLayout();
- The condition is false; the firstCaretResult and secondCaretResult are both NotChanged.
mIsCaretPositionChanged =
firstCaretResult == PositionChangedResult::Position ||
secondCaretResult == PositionChangedResult::Position;
if (mIsCaretPositionChanged) {
// Flush layout to make the carets intersection correct.
if (!FlushLayout()) {
- Even we make the condition pass, it seems that is not allowed to call FlushLayout() in the
onScrollEnd()
callback by the change https://phabricator.services.mozilla.com/D15537
void AccessibleCaretManager::OnScrollStart() {
AC_LOG("%s", __FUNCTION__);
AutoRestore<bool> saveAllowFlushingLayout(mAllowFlushingLayout);
mAllowFlushingLayout = false;
Reporter | ||
Comment 3•4 years ago
|
||
Yeah, we deliberately forbid AccessibleCaret to flush layout after certain operations due to security issues (as flushing the layout can trigger arbitrary javascript script of the web pages, and it can possibly destroy the frame tree in which AccessibleCaret lives).
It seems AccessibleCaret::Intersects
doesn't work if the caret is being scrolling back into the viewport. As their position is not changed, but their appearance is changing from Appearance::NormalNotShown
back to something visible. This does require layout to flush to regenerate the real frame for AccessibleCaret's element because the caret's element is just a <div>
and currently we tweak its class to none
in AccessibleCaret::SetAppearance
[1] so that its hidden by applying display:none
[2].
It may worth trying to simply set visibility: hidden
when the caret has Appearance::NormalNotShown
to preserve the frame so that caret's intersection can work. If it's not working, I'll be curious to know why. Otherwise, I imaging if we want to cache the caret's rect in C++, it'd be tricky to invalidate the cache at the right place, because we certainly need to store the value after we really does the layout flush. I hope we don't need to pursue this path.
[1] https://searchfox.org/mozilla-central/rev/61728de8273c04fe2417c475fc0637e8b79210d7/layout/base/AccessibleCaret.cpp#89
[2] https://searchfox.org/mozilla-central/rev/61728de8273c04fe2417c475fc0637e8b79210d7/layout/style/res/ua.css#454-456
The bug is fixed as you suggest, submitted for review.
I get a lot out of the information from your comment. Thank you for your advice.
Reporter | ||
Comment 6•4 years ago
|
||
Reporter | ||
Comment 7•4 years ago
|
||
Reporter | ||
Updated•4 years ago
|
Reporter | ||
Comment 8•4 years ago
|
||
No problem! Thanks for fixing this bug.
Actually, changing both Appearance::NormalNotShown
and Appearance::None
to use visibility:hidden
introduces a bug.
We might want to set the visibility: hidden
only if Appearance::NormalNotShown
, and keep display: none
when Appearance::None
. We can add something like the following to ua.css
,
div:-moz-native-anonymous.moz-accessiblecaret.hidden {
visibility: hidden;
}
and add a new switch case arm to AccessibleCaret::AppearanceString
[1] to return "hidden"
if Appearance::NormalNotShown
.
I attached patch with a testcase that fails with your current approach. I believe the testcase should pass with my thoughts above. You can merge my patch into your final revision.
Comment 10•4 years ago
|
||
Backed out for high frequency failures.
Log: https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=319338856&repo=autoland&lineNumber=54568
Backout: https://hg.mozilla.org/integration/autoland/rev/a6ba6ed8e1c9873f7a3b288a73cf2d257be07089
Assignee | ||
Comment 11•4 years ago
|
||
Oops, I will check that. I can reproduce the issue and the fail rate is about 5/10 in my local machine.
Assignee | ||
Comment 12•4 years ago
|
||
@TYLin, there is a CSS transition when we change the appearance to Normal(visibility:visible) from NormalNotShown (visibility:hidden), the caret may not be exactly at the left or right of the selection rectangle yet, so we may fail some of the tests at test_accessiblecaret_selection_mode.py
when we try to touch caret.
Not sure what is the preferred way to fix the side effect, do you have any suggestions?
- Avoid triggering the CSS transition, to cancel the CSS transition, e.g. add a ".notransition" for AccessibleCaret, and then remove in a short timeout.
- Add a delay (250ms) in the tests; make sure that the animation is complete before touching it.
- Others ..?
Reporter | ||
Comment 13•4 years ago
|
||
Nice observation!
I failed to reproduce the failure by running ./mach marionette-test layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
locally on my machine. However, on testcase test_long_press_to_select_when_partial_visible_word_is_selected
, when "AAAAAAAA" is selected, I see the second caret (right caret) has a transition animation shifting it from right to left to its correct position. I guess this is because of the margin-left
transition effect specified at [2].
I believe this can only happen when the appearance is changing from NormalNotShow
to Normal
the very first time when the page is loaded since this is the first time the caret gets the margin-left
style [1]. This is rare on the field, and the animation won't impact the user interaction so I'm reluctant to fix AccessibleCaret.
How about we fix the test by forcing the second caret to have Normal
appearance once? For example, adding the following code after word0_x, word0_y = self.word_location(el, 0)
[2].
# Long press on the first word to make both carets show to avoid
# transition effect on margin-left later on.
self.long_press_on_location(el, word0_x, word0_y)
If the above works for you locally, feel free to add it to your patch and add "check-in needed" tag to land it. Feel free to needinfo me if you fix other testcases and would like me to take look at the patch again; or you need help to run your patch on Firefox CI (try server) if you don't have the access.
[1] https://searchfox.org/mozilla-central/rev/d866b96d74ec2a63f09ee418f048d23f4fd379a2/layout/base/AccessibleCaret.cpp#302-304
[2] https://searchfox.org/mozilla-central/rev/d866b96d74ec2a63f09ee418f048d23f4fd379a2/layout/style/res/ua.css#412-413
[3] https://searchfox.org/mozilla-central/rev/d866b96d74ec2a63f09ee418f048d23f4fd379a2/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py#639
[4] https://firefox-source-docs.mozilla.org/tools/try/index.html
Comment 14•4 years ago
|
||
Could have bug 1663928 and bug 1663511 the same underlying reason with the transitioning?
Reporter | ||
Comment 15•4 years ago
|
||
Re comment 14:
Both bugs are for intermittent in the single caret mode, and the caret's appearace is changing from None
to Normal
the first time. So it doesn't seem likely to be the same underlying reason as comment 13.
Assignee | ||
Comment 16•4 years ago
|
||
(In reply to Ting-Yu Lin [:TYLin] (UTC-7) from comment #13)
How about we fix the test by forcing the second caret to have
Normal
appearance once? For example, adding the following code afterword0_x, word0_y = self.word_location(el, 0)
[2].# Long press on the first word to make both carets show to avoid # transition effect on margin-left later on. self.long_press_on_location(el, word0_x, word0_y)
The test_long_press_to_select_when_partial_visible_word_is_selected() is just the case to test the appearance change from 'NormalNotShown' to 'Normal', so it did not work.
How about adding a preference for the transition-duration of AccessibleCaret? We can set it to 0 before testing, so we will not worry about the timing at all.
Reporter | ||
Comment 17•4 years ago
|
||
How about adding a preference for the transition-duration of AccessibleCaret? We can set it to 0 before testing, so we will not worry about the timing at all.
Yes, adding a preference to control transition-duration
sounds good to me. Please add another patch for this change. Thanks!
Assignee | ||
Comment 18•4 years ago
|
||
Updated•4 years ago
|
Comment 19•4 years ago
|
||
Comment 20•4 years ago
|
||
Comment 21•4 years ago
|
||
bugherder |
Comment 22•4 years ago
|
||
bugherder |
Description
•