Commit 54c64ba3 authored by Lan Wei's avatar Lan Wei Committed by Commit Bot

Update hover after GestureScrollEnd of wheel scroll is handled

Since we are not updating hover during mouse wheel scroll, we should
update hover when we handle the GestureScrollEnd event on compositor or
main thread.

Bug: 877132
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I732aea455db927ff5ad44b89e7a446917ad94e35
Reviewed-on: https://chromium-review.googlesource.com/c/1265555Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Commit-Queue: Lan Wei <lanwei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605873}
parent 3afdf9f8
...@@ -861,7 +861,8 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) { ...@@ -861,7 +861,8 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) {
if (inner_viewport_scroll_delta.IsZero() && info.page_scale_delta == 1.f && if (inner_viewport_scroll_delta.IsZero() && info.page_scale_delta == 1.f &&
info.elastic_overscroll_delta.IsZero() && !info.top_controls_delta && info.elastic_overscroll_delta.IsZero() && !info.top_controls_delta &&
!info.browser_controls_constraint_changed) { !info.browser_controls_constraint_changed &&
!info.scroll_gesture_did_end) {
return; return;
} }
...@@ -879,10 +880,10 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) { ...@@ -879,10 +880,10 @@ void LayerTreeHost::ApplyViewportChanges(const ScrollAndScaleSet& info) {
info.elastic_overscroll_delta); info.elastic_overscroll_delta);
// TODO(ccameron): pass the elastic overscroll here so that input events // TODO(ccameron): pass the elastic overscroll here so that input events
// may be translated appropriately. // may be translated appropriately.
client_->ApplyViewportChanges({inner_viewport_scroll_delta, client_->ApplyViewportChanges(
info.elastic_overscroll_delta, {inner_viewport_scroll_delta, info.elastic_overscroll_delta,
info.page_scale_delta, info.top_controls_delta, info.page_scale_delta, info.top_controls_delta,
info.browser_controls_constraint}); info.browser_controls_constraint, info.scroll_gesture_did_end});
SetNeedsUpdateLayers(); SetNeedsUpdateLayers();
} }
......
...@@ -42,6 +42,10 @@ struct ApplyViewportChangesArgs { ...@@ -42,6 +42,10 @@ struct ApplyViewportChangesArgs {
// Whether the browser controls have been locked to fully hidden or shown or // Whether the browser controls have been locked to fully hidden or shown or
// whether they can be freely moved. // whether they can be freely moved.
BrowserControlsState browser_controls_constraint; BrowserControlsState browser_controls_constraint;
// Set to true when a scroll gesture being handled on the compositor has
// ended.
bool scroll_gesture_did_end;
}; };
// A LayerTreeHost is bound to a LayerTreeHostClient. The main rendering // A LayerTreeHost is bound to a LayerTreeHostClient. The main rendering
......
...@@ -181,7 +181,8 @@ ScrollAndScaleSet::ScrollAndScaleSet() ...@@ -181,7 +181,8 @@ ScrollAndScaleSet::ScrollAndScaleSet()
browser_controls_constraint(BrowserControlsState::kBoth), browser_controls_constraint(BrowserControlsState::kBoth),
browser_controls_constraint_changed(false), browser_controls_constraint_changed(false),
has_scrolled_by_wheel(false), has_scrolled_by_wheel(false),
has_scrolled_by_touch(false) {} has_scrolled_by_touch(false),
scroll_gesture_did_end(false) {}
ScrollAndScaleSet::~ScrollAndScaleSet() = default; ScrollAndScaleSet::~ScrollAndScaleSet() = default;
......
...@@ -177,6 +177,10 @@ struct CC_EXPORT ScrollAndScaleSet { ...@@ -177,6 +177,10 @@ struct CC_EXPORT ScrollAndScaleSet {
bool has_scrolled_by_wheel; bool has_scrolled_by_wheel;
bool has_scrolled_by_touch; bool has_scrolled_by_touch;
// Set to true when a scroll gesture being handled on the compositor has
// ended.
bool scroll_gesture_did_end;
private: private:
DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet); DISALLOW_COPY_AND_ASSIGN(ScrollAndScaleSet);
}; };
......
...@@ -331,7 +331,8 @@ LayerTreeHostImpl::LayerTreeHostImpl( ...@@ -331,7 +331,8 @@ LayerTreeHostImpl::LayerTreeHostImpl(
frame_metrics_(LTHI_FrameMetricsSettings(settings_)), frame_metrics_(LTHI_FrameMetricsSettings(settings_)),
skipped_frame_tracker_(&frame_metrics_), skipped_frame_tracker_(&frame_metrics_),
is_animating_for_snap_(false), is_animating_for_snap_(false),
paint_image_generator_client_id_(PaintImage::GetNextGeneratorClientId()) { paint_image_generator_client_id_(PaintImage::GetNextGeneratorClientId()),
scroll_gesture_did_end_(false) {
DCHECK(mutator_host_); DCHECK(mutator_host_);
mutator_host_->SetMutatorHostClient(this); mutator_host_->SetMutatorHostClient(this);
...@@ -4600,6 +4601,8 @@ void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) { ...@@ -4600,6 +4601,8 @@ void LayerTreeHostImpl::ScrollEndImpl(ScrollState* scroll_state) {
} }
void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) { void LayerTreeHostImpl::ScrollEnd(ScrollState* scroll_state, bool should_snap) {
scroll_gesture_did_end_ = true;
if (should_snap && SnapAtScrollEnd()) if (should_snap && SnapAtScrollEnd())
return; return;
...@@ -4779,6 +4782,7 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { ...@@ -4779,6 +4782,7 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
// Record and reset scroll source flags. // Record and reset scroll source flags.
scroll_info->has_scrolled_by_wheel = has_scrolled_by_wheel_; scroll_info->has_scrolled_by_wheel = has_scrolled_by_wheel_;
scroll_info->has_scrolled_by_touch = has_scrolled_by_touch_; scroll_info->has_scrolled_by_touch = has_scrolled_by_touch_;
scroll_info->scroll_gesture_did_end = scroll_gesture_did_end_;
has_scrolled_by_wheel_ = has_scrolled_by_touch_ = false; has_scrolled_by_wheel_ = has_scrolled_by_touch_ = false;
if (browser_controls_manager()) { if (browser_controls_manager()) {
...@@ -4787,6 +4791,7 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { ...@@ -4787,6 +4791,7 @@ std::unique_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
&scroll_info->browser_controls_constraint_changed); &scroll_info->browser_controls_constraint_changed);
} }
scroll_gesture_did_end_ = false;
return scroll_info; return scroll_info;
} }
......
...@@ -1110,6 +1110,10 @@ class CC_EXPORT LayerTreeHostImpl ...@@ -1110,6 +1110,10 @@ class CC_EXPORT LayerTreeHostImpl
const PaintImage::GeneratorClientId paint_image_generator_client_id_; const PaintImage::GeneratorClientId paint_image_generator_client_id_;
// Set to true when a scroll gesture being handled on the compositor has
// ended.
bool scroll_gesture_did_end_;
DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl); DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImpl);
}; };
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
const textWhenHovered = "currently hovered"; const textWhenHovered = "currently hovered";
const textWhenWasHovered = "was hovered"; const textWhenWasHovered = "was hovered";
const mouse = GestureSourceType.MOUSE_INPUT; const mouse = GestureSourceType.MOUSE_INPUT;
const scrollSpeed = 350;
const hoveredColor = "rgb(255, 255, 0)";
const unhoveredColor = "rgb(0, 0, 255)";
function buildPage() { function buildPage() {
for (let i = 0; i < numHoverElements; i++) { for (let i = 0; i < numHoverElements; i++) {
...@@ -71,31 +74,33 @@ ...@@ -71,31 +74,33 @@
promise_test(async () => { promise_test(async () => {
let x = array[0].offsetLeft + 10; let x = array[0].offsetLeft + 10;
let y = array[0].offsetTop + 10; let y = array[0].offsetTop + 25;
// Move cursor to 1st element. // Move cursor to 1st element.
await mouseMoveTo(x, y); await mouseMoveTo(x, y);
await waitFor( () => { return array[0].innerHTML == textWhenHovered;}, 'wait for move to 1st element'); await waitFor( () => { return array[0].innerHTML == textWhenHovered;}, 'wait for move to 1st element');
assert_equals(array[0].innerHTML, textWhenHovered); assert_equals(array[0].innerHTML, textWhenHovered);
assert_equals(array[1].innerHTML, textWhenNotHovered); assert_equals(array[1].innerHTML, textWhenNotHovered);
assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)'); assert_equals(getComputedStyle(array[0]).backgroundColor, hoveredColor);
// Scroll end up at 4th element. Hover state does not update during scrolling // 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. // so that 2nd, 3rd elements do not see the mouseover and mouseout events, but hover state
// is updated at the end of scroll, so 4th element does see a mouseover and mouseout events.
assert_equals(document.scrollingElement.scrollTop, 0); assert_equals(document.scrollingElement.scrollTop, 0);
await smoothScroll(3 * elementHeight, x, y, mouse, 'down', SPEED_INSTANT); await smoothScroll(3 * elementHeight, x, y, mouse, 'down', scrollSpeed);
// Wait enough time to see if we fire a fake mouse move event to update the hover state. // 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); await waitForAnimationEnd(() => { return document.scrollingElement.scrollTop; }, 200, 60);
assert_approx_equals(document.scrollingElement.scrollTop, 3 * elementHeight, 10); // TODO(crbug/902438): Support wheel scroll at low speeds in GpuBenchmarking::SmoothScrollBy.
assert_equals(array[0].innerHTML, textWhenHovered); assert_approx_equals(document.scrollingElement.scrollTop, 3 * elementHeight, 25);
assert_equals(array[0].innerHTML, textWhenWasHovered);
assert_equals(array[1].innerHTML, textWhenNotHovered); assert_equals(array[1].innerHTML, textWhenNotHovered);
assert_equals(array[2].innerHTML, textWhenNotHovered); assert_equals(array[2].innerHTML, textWhenNotHovered);
assert_equals(array[3].innerHTML, textWhenNotHovered); assert_equals(array[3].innerHTML, textWhenHovered);
assert_equals(array[4].innerHTML, textWhenNotHovered); assert_equals(array[4].innerHTML, textWhenNotHovered);
assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)'); assert_equals(getComputedStyle(array[0]).backgroundColor, unhoveredColor);
assert_equals(getComputedStyle(array[1]).backgroundColor, 'rgb(0, 0, 255)'); assert_equals(getComputedStyle(array[1]).backgroundColor, unhoveredColor);
assert_equals(getComputedStyle(array[2]).backgroundColor, 'rgb(0, 0, 255)'); assert_equals(getComputedStyle(array[2]).backgroundColor, unhoveredColor);
assert_equals(getComputedStyle(array[3]).backgroundColor, 'rgb(0, 0, 255)'); assert_equals(getComputedStyle(array[3]).backgroundColor, hoveredColor);
}, 'Mouse wheel scroll on the page, no hover update during scrolling.'); }, 'Mouse wheel scroll on the page, no hover update during scrolling, but updating hover at the end of scroll.');
} }
</script> </script>
\ No newline at end of file
...@@ -3265,6 +3265,10 @@ void WebViewImpl::ApplyViewportChanges(const ApplyViewportChangesArgs& args) { ...@@ -3265,6 +3265,10 @@ void WebViewImpl::ApplyViewportChanges(const ApplyViewportChangesArgs& args) {
elastic_overscroll_ += FloatSize(args.elastic_overscroll_delta.x(), elastic_overscroll_ += FloatSize(args.elastic_overscroll_delta.x(),
args.elastic_overscroll_delta.y()); args.elastic_overscroll_delta.y());
UpdateBrowserControlsConstraint(args.browser_controls_constraint); UpdateBrowserControlsConstraint(args.browser_controls_constraint);
if (RuntimeEnabledFeatures::NoHoverDuringScrollEnabled() &&
args.scroll_gesture_did_end)
MainFrameImpl()->GetFrame()->GetEventHandler().RecomputeMouseHoverState();
} }
void WebViewImpl::RecordWheelAndTouchScrollingCount( void WebViewImpl::RecordWheelAndTouchScrollingCount(
......
...@@ -1238,6 +1238,10 @@ void EventHandler::AnimateSnapFling(base::TimeTicks monotonic_time) { ...@@ -1238,6 +1238,10 @@ void EventHandler::AnimateSnapFling(base::TimeTicks monotonic_time) {
scroll_manager_->AnimateSnapFling(monotonic_time); scroll_manager_->AnimateSnapFling(monotonic_time);
} }
void EventHandler::RecomputeMouseHoverState() {
mouse_event_manager_->RecomputeMouseHoverState();
}
void EventHandler::SetCapturingMouseEventsNode(Node* n) { void EventHandler::SetCapturingMouseEventsNode(Node* n) {
CaptureMouseEventsToWidget(n); CaptureMouseEventsToWidget(n);
capturing_mouse_events_node_ = n; capturing_mouse_events_node_ = n;
...@@ -2028,6 +2032,11 @@ bool EventHandler::FakeMouseMovePending() const { ...@@ -2028,6 +2032,11 @@ bool EventHandler::FakeMouseMovePending() const {
void EventHandler::MayUpdateHoverWhenContentUnderMouseChanged( void EventHandler::MayUpdateHoverWhenContentUnderMouseChanged(
MouseEventManager::UpdateHoverReason update_hover_reason) { MouseEventManager::UpdateHoverReason update_hover_reason) {
if (update_hover_reason ==
MouseEventManager::UpdateHoverReason::kScrollOffsetChanged &&
RuntimeEnabledFeatures::NoHoverDuringScrollEnabled()) {
return;
}
mouse_event_manager_->MayUpdateHoverWhenContentUnderMouseChanged( mouse_event_manager_->MayUpdateHoverWhenContentUnderMouseChanged(
update_hover_reason); update_hover_reason);
} }
......
...@@ -286,6 +286,8 @@ class CORE_EXPORT EventHandler final ...@@ -286,6 +286,8 @@ class CORE_EXPORT EventHandler final
void AnimateSnapFling(base::TimeTicks monotonic_time); void AnimateSnapFling(base::TimeTicks monotonic_time);
void RecomputeMouseHoverState();
private: private:
enum NoCursorChangeType { kNoCursorChange }; enum NoCursorChangeType { kNoCursorChange };
......
...@@ -350,6 +350,10 @@ void MouseEventManager::FakeMouseMoveEventTimerFired(TimerBase* timer) { ...@@ -350,6 +350,10 @@ void MouseEventManager::FakeMouseMoveEventTimerFired(TimerBase* timer) {
TRACE_EVENT0("input", "MouseEventManager::fakeMouseMoveEventTimerFired"); TRACE_EVENT0("input", "MouseEventManager::fakeMouseMoveEventTimerFired");
DCHECK(timer == &fake_mouse_move_event_timer_); DCHECK(timer == &fake_mouse_move_event_timer_);
RecomputeMouseHoverState();
}
void MouseEventManager::RecomputeMouseHoverState() {
if (is_mouse_position_unknown_) if (is_mouse_position_unknown_)
return; return;
......
...@@ -154,6 +154,8 @@ class CORE_EXPORT MouseEventManager final ...@@ -154,6 +154,8 @@ class CORE_EXPORT MouseEventManager final
bool FakeMouseMovePending() const; bool FakeMouseMovePending() const;
void RecomputeMouseHoverState();
private: private:
class MouseEventBoundaryEventDispatcher : public BoundaryEventDispatcher { class MouseEventBoundaryEventDispatcher : public BoundaryEventDispatcher {
public: public:
......
...@@ -607,6 +607,8 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd( ...@@ -607,6 +607,8 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd(
} }
ClearGestureScrollState(); ClearGestureScrollState();
if (RuntimeEnabledFeatures::NoHoverDuringScrollEnabled())
frame_->GetEventHandler().RecomputeMouseHoverState();
return WebInputEventResult::kNotHandled; return WebInputEventResult::kNotHandled;
} }
......
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