Commit d6bf5e89 authored by Lan Wei's avatar Lan Wei Committed by Commit Bot

Reland "Do not apply hover during scroll"

In order to improve the performance and eliminate the issues that the
fake mouse move events cause to the testing and web developers, we
should not send fake mouse move events during scroll. This is
implemented behind a flag.

We will update the hover effect after scroll finishes in a following
patch.

TBR=bokan@chromium.org,nzolghadr@chromium.org,dtapuska@chromium.org,
dgozman@chromium.org

Bug: 877132
Change-Id: I484d7457f13d66e8add6faf5bc6c6d14c805af75
Reviewed-on: https://chromium-review.googlesource.com/c/1262423
Commit-Queue: Lan Wei <lanwei@chromium.org>
Reviewed-by: default avatarLan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597102}
parent 096c8366
......@@ -503,6 +503,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableJankTracking(
base::FeatureList::IsEnabled(blink::features::kJankTracking) ||
enableExperimentalWebPlatformFeatures);
WebRuntimeFeatures::EnableNoHoverDuringScroll(
base::FeatureList::IsEnabled(features::kNoHoverDuringScroll));
}
} // namespace content
<!DOCTYPE html>
<script src='../../resources/testharness.js'></script>
<script src='../../resources/testharnessreport.js'></script>
<script src='../../resources/gesture-util.js'></script>
<style>
body, html {
margin: 0;
}
div {
height: 50px;
width: 100%;
}
.hoverme {
background-color: rgb(0, 0, 255);
}
.hoverme:hover {
background-color: rgb(255, 255, 0);
}
.message {
width: 100%;
text-align: left;
}
</style>
<div class="message">
First move your mouse cursor to the page, you will see the text under the mouse cursor changed to "currently hovered". <br>
Scroll mouse wheel slowly, you should not see any text under the mouse changed to "currently hovered" while the scrolling is in process and finishes.
</div>
<script>
let array;
const numHoverElements = 30;
const elementHeight = 50;
const textWhenNotHovered = "hover over me";
const textWhenHovered = "currently hovered";
const textWhenWasHovered = "was hovered";
const mouse = GestureSourceType.MOUSE_INPUT;
function buildPage() {
for (let i = 0; i < numHoverElements; i++) {
let div = document.createElement('div');
div.className = "hoverme";
div.innerHTML = textWhenNotHovered;
document.body.appendChild(div);
}
array = document.getElementsByClassName('hoverme');
for (let element of array) {
element.addEventListener('mouseover', function (e) {
this.innerHTML = textWhenHovered;
});
element.addEventListener('mouseout', function (e) {
this.innerHTML = textWhenWasHovered;
});
}
}
window.onload = async () => {
if (window.internals) {
internals.settings.setScrollAnimatorEnabled(false);
internals.runtimeFlags.noHoverDuringScrollEnabled = true;
}
buildPage();
await waitForCompositorCommit();
promise_test(async () => {
let x = array[0].offsetLeft + 10;
let y = array[0].offsetTop + 10;
// Move cursor to 1st element.
await mouseMoveTo(x, y);
await waitFor( () => { return array[0].innerHTML == textWhenHovered;}, 'wait for move to 1st element');
assert_equals(array[0].innerHTML, textWhenHovered);
assert_equals(array[1].innerHTML, textWhenNotHovered);
assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)');
// Scroll end up at 4th element. Hover state does not update during scrolling
// so that 2nd, 3rd and 4th elements do not see the mouseover and mouseout events.
assert_equals(document.scrollingElement.scrollTop, 0);
await smoothScroll(3 * elementHeight, x, y, mouse, 'down', SPEED_INSTANT);
// Wait enough time to see if we fire a fake mouse move event to update the hover state.
await waitForAnimationEnd(() => { return document.scrollingElement.scrollTop; }, 200, 60);
assert_approx_equals(document.scrollingElement.scrollTop, 3 * elementHeight, 10);
assert_equals(array[0].innerHTML, textWhenHovered);
assert_equals(array[1].innerHTML, textWhenNotHovered);
assert_equals(array[2].innerHTML, textWhenNotHovered);
assert_equals(array[3].innerHTML, textWhenNotHovered);
assert_equals(array[4].innerHTML, textWhenNotHovered);
assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)');
assert_equals(getComputedStyle(array[1]).backgroundColor, 'rgb(0, 0, 255)');
assert_equals(getComputedStyle(array[2]).backgroundColor, 'rgb(0, 0, 255)');
assert_equals(getComputedStyle(array[3]).backgroundColor, 'rgb(0, 0, 255)');
}, 'Mouse wheel scroll on the page, no hover update during scrolling.');
}
</script>
\ No newline at end of file
......@@ -114,6 +114,7 @@ class WebRuntimeFeatures {
BLINK_PLATFORM_EXPORT static void EnableNetInfoDownlinkMax(bool);
BLINK_PLATFORM_EXPORT static void EnableNetworkService(bool);
BLINK_PLATFORM_EXPORT static void EnableNoHoverAfterLayoutChange(bool);
BLINK_PLATFORM_EXPORT static void EnableNoHoverDuringScroll(bool);
BLINK_PLATFORM_EXPORT static void EnableNotificationConstructor(bool);
BLINK_PLATFORM_EXPORT static void EnableNotificationContentImage(bool);
BLINK_PLATFORM_EXPORT static void EnableNotifications(bool);
......
......@@ -620,8 +620,10 @@ void MouseEventManager::MayUpdateHoverWhenContentUnderMouseChanged(
if (update_hover_reason ==
MouseEventManager::UpdateHoverReason::kScrollOffsetChanged &&
mouse_pressed_)
(RuntimeEnabledFeatures::NoHoverDuringScrollEnabled() ||
mouse_pressed_)) {
return;
}
// TODO(lanwei): When the mouse position is unknown, we do not send the fake
// mousemove event for now, so we cannot update the hover states and mouse
......
......@@ -220,6 +220,10 @@ void WebRuntimeFeatures::EnableNoHoverAfterLayoutChange(bool enable) {
RuntimeEnabledFeatures::SetNoHoverAfterLayoutChangeEnabled(enable);
}
void WebRuntimeFeatures::EnableNoHoverDuringScroll(bool enable) {
RuntimeEnabledFeatures::SetNoHoverDuringScrollEnabled(enable);
}
void WebRuntimeFeatures::EnableNotificationConstructor(bool enable) {
RuntimeEnabledFeatures::SetNotificationConstructorEnabled(enable);
}
......
......@@ -820,6 +820,10 @@
name: "NoHoverAfterLayoutChange",
settable_from_internals: true,
},
{
name: "NoHoverDuringScroll",
settable_from_internals: true,
},
{
name: "NoIdleEncodingForLayoutTests",
status: "test",
......
......@@ -19,4 +19,7 @@ const base::Feature kSendMouseLeaveEvents{"SendMouseLeaveEvents",
const base::Feature kNoHoverAfterLayoutChange{
"NoHoverAfterLayoutChange", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kNoHoverDuringScroll{"NoHoverDuringScroll",
base::FEATURE_DISABLED_BY_DEFAULT};
}
......@@ -20,8 +20,15 @@ extern const base::Feature kResamplingScrollEvents;
// the native platforms. crbug.com/450631
extern const base::Feature kSendMouseLeaveEvents;
// Do not update hover after the layout is changed.
// When enabled, this feature prevents Blink from changing the hover state and
// dispatching mouse enter/exit events for elements under the mouse after the
// layout under the mouse cursor is changed.
extern const base::Feature kNoHoverAfterLayoutChange;
// When enabled, this feature prevents Blink from changing the hover state and
// dispatching mouse enter/exit events for elements under the mouse as the page
// is scrolled.
extern const base::Feature kNoHoverDuringScroll;
}
#endif // UI_EVENTS_BLINK_BLINK_FEATURES_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment