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

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.

Bug: 877132
Change-Id: Iee838f50e0a52b5048081d79f91442ddf0467e8f
Reviewed-on: https://chromium-review.googlesource.com/c/1211907
Commit-Queue: Lan Wei <lanwei@chromium.org>
Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarNavid Zolghadr <nzolghadr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596049}
parent 0780e76b
......@@ -499,6 +499,9 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::EnableNoHoverAfterLayoutChange(
base::FeatureList::IsEnabled(features::kNoHoverAfterLayoutChange));
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 moveto 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, 100);
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
......@@ -113,6 +113,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
......
......@@ -216,6 +216,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);
}
......
......@@ -817,6 +817,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