diff options
author | dtapuska <dtapuska@chromium.org> | 2016-02-05 13:36:02 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-05 21:36:53 +0000 |
commit | f206a40dcff89bf50517b1b4e109c25c277bad43 (patch) | |
tree | f9166c0d889fc3f82c0fbb51ec8e79150cd393c6 | |
parent | e674fac322ad46a261ee6e9b4d1b40ee3c3958f2 (diff) | |
download | chromium_src-f206a40dcff89bf50517b1b4e109c25c277bad43.zip chromium_src-f206a40dcff89bf50517b1b4e109c25c277bad43.tar.gz chromium_src-f206a40dcff89bf50517b1b4e109c25c277bad43.tar.bz2 |
Communicate whether passive event listeners exist to cc.
cc does nothing with these new fields being set other than plumbing them
through the pipeline to be later queried on the layer_impl.
Add an additional field whether touch event listeners exist on the layer
(which unfortunately is effectively implement as an entire document field
in the blink EventListenerRegistry; this can be improved). There still
exists TouchRegionRects that indicate the areas of blocking event
listeners; but whether a passive event listener exists will be indicated
in this field. It is intended that this model will be replicated
with property trees when it is ready.
BUG=489802
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1577263004
Cr-Commit-Position: refs/heads/master@{#373915}
48 files changed, 433 insertions, 142 deletions
diff --git a/cc/debug/debug_rect_history.cc b/cc/debug/debug_rect_history.cc index 59ca9de..87d83b8 100644 --- a/cc/debug/debug_rect_history.cc +++ b/cc/debug/debug_rect_history.cc @@ -181,8 +181,14 @@ void DebugRectHistory::SaveWheelEventHandlerRects(LayerImpl* layer) { } void DebugRectHistory::SaveWheelEventHandlerRectsCallback(LayerImpl* layer) { - if (!layer->layer_tree_impl()->have_wheel_event_handlers()) + EventListenerProperties event_properties = + layer->layer_tree_impl()->event_listener_properties( + EventListenerClass::kMouseWheel); + if (event_properties == EventListenerProperties::kNone || + (layer->layer_tree_impl()->settings().use_mouse_wheel_gestures && + event_properties == EventListenerProperties::kPassive)) { return; + } debug_rects_.push_back( DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE, diff --git a/cc/input/event_listener_properties.h b/cc/input/event_listener_properties.h new file mode 100644 index 0000000..2755c6e --- /dev/null +++ b/cc/input/event_listener_properties.h @@ -0,0 +1,16 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_INPUT_EVENT_LISTENER_PROPERTIES_H_ +#define CC_INPUT_EVENT_LISTENER_PROPERTIES_H_ + +namespace cc { + +enum class EventListenerClass { kTouch, kMouseWheel, kNumClasses }; + +enum class EventListenerProperties { kNone, kPassive, kBlocking, kMax }; + +} // namespace cc + +#endif // CC_INPUT_EVENT_LISTENER_PROPERTIES_H_ diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 449c471..9a39562 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" +#include "cc/input/event_listener_properties.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/input/scroll_state.h" #include "cc/input/scrollbar.h" @@ -170,7 +171,8 @@ class CC_EXPORT InputHandler { virtual bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, ScrollInputType type) const = 0; - virtual bool HaveWheelEventHandlers() const = 0; + virtual EventListenerProperties GetEventListenerProperties( + EventListenerClass event_class) const = 0; // Whether the page should be given the opportunity to suppress scrolling by // consuming touch events that started at |viewport_point|. diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 173237a..56b79e8 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -556,13 +556,19 @@ InputHandler::ScrollStatus LayerImpl::TryScroll( } } - if ((type == InputHandler::WHEEL || type == InputHandler::ANIMATED_WHEEL) && - layer_tree_impl_->have_wheel_event_handlers()) { - TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers"); - scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kEventHandlers; - return scroll_status; + if (type == InputHandler::WHEEL || type == InputHandler::ANIMATED_WHEEL) { + EventListenerProperties event_properties = + layer_tree_impl_->event_listener_properties( + EventListenerClass::kMouseWheel); + if (event_properties == EventListenerProperties::kBlocking || + (!layer_tree_impl_->settings().use_mouse_wheel_gestures && + event_properties == EventListenerProperties::kPassive)) { + TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers"); + scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD; + scroll_status.main_thread_scrolling_reasons = + MainThreadScrollingReason::kEventHandlers; + return scroll_status; + } } if (!scrollable()) { diff --git a/cc/proto/layer_tree_host.proto b/cc/proto/layer_tree_host.proto index 9a6ac11..d1d78e7 100644 --- a/cc/proto/layer_tree_host.proto +++ b/cc/proto/layer_tree_host.proto @@ -53,6 +53,7 @@ message LayerTreeHost { optional PropertyTrees property_trees = 31; optional uint32 surface_id_namespace = 32; optional uint32 next_surface_sequence = 33; - optional bool have_wheel_event_handlers = 34; + optional uint32 wheel_event_listener_properties = 34; optional bool have_scroll_event_handlers = 35; + optional uint32 touch_event_listener_properties = 36; } diff --git a/cc/proto/layer_tree_settings.proto b/cc/proto/layer_tree_settings.proto index 1c0bb85..844d75b1 100644 --- a/cc/proto/layer_tree_settings.proto +++ b/cc/proto/layer_tree_settings.proto @@ -70,4 +70,5 @@ message LayerTreeSettings { optional int32 max_staging_buffer_usage_in_bytes = 47; optional ManagedMemoryPolicy memory_policy = 48; optional LayerTreeDebugState initial_debug_state = 49; + optional bool use_mouse_wheel_gestures = 50; } diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 2de6b3b..c2e08dd 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -184,7 +184,7 @@ LayerTreeHost::LayerTreeHost(InitParams* params, CompositorMode mode) background_color_(SK_ColorWHITE), has_transparent_background_(false), have_scroll_event_handlers_(false), - have_wheel_event_handlers_(false), + event_listener_properties_(), did_complete_scale_animation_(false), in_paint_layer_contents_(false), id_(s_layer_tree_host_sequence_number.GetNext() + 1), @@ -401,7 +401,12 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { sync_tree->set_background_color(background_color_); sync_tree->set_has_transparent_background(has_transparent_background_); sync_tree->set_have_scroll_event_handlers(have_scroll_event_handlers_); - sync_tree->set_have_wheel_event_handlers(have_wheel_event_handlers_); + sync_tree->set_event_listener_properties( + EventListenerClass::kTouch, + event_listener_properties(EventListenerClass::kTouch)); + sync_tree->set_event_listener_properties( + EventListenerClass::kMouseWheel, + event_listener_properties(EventListenerClass::kMouseWheel)); if (page_scale_layer_.get() && inner_viewport_scroll_layer_.get()) { sync_tree->SetViewportLayersFromIds( @@ -1124,11 +1129,14 @@ void LayerTreeHost::SetHaveScrollEventHandlers(bool have_event_handlers) { SetNeedsCommit(); } -void LayerTreeHost::SetHaveWheelEventHandlers(bool have_event_handlers) { - if (have_wheel_event_handlers_ == have_event_handlers) +void LayerTreeHost::SetEventListenerProperties( + EventListenerClass event_class, + EventListenerProperties properties) { + const size_t index = static_cast<size_t>(event_class); + if (event_listener_properties_[index] == properties) return; - have_wheel_event_handlers_ = have_event_handlers; + event_listener_properties_[index] = properties; SetNeedsCommit(); } @@ -1458,7 +1466,10 @@ void LayerTreeHost::ToProtobufForCommit(proto::LayerTreeHost* proto) const { proto->set_background_color(background_color_); proto->set_has_transparent_background(has_transparent_background_); proto->set_have_scroll_event_handlers(have_scroll_event_handlers_); - proto->set_have_wheel_event_handlers(have_wheel_event_handlers_); + proto->set_wheel_event_listener_properties(static_cast<uint32_t>( + event_listener_properties(EventListenerClass::kMouseWheel))); + proto->set_touch_event_listener_properties(static_cast<uint32_t>( + event_listener_properties(EventListenerClass::kTouch))); proto->set_in_paint_layer_contents(in_paint_layer_contents_); proto->set_id(id_); proto->set_next_commit_forces_redraw(next_commit_forces_redraw_); @@ -1525,7 +1536,13 @@ void LayerTreeHost::FromProtobufForCommit(const proto::LayerTreeHost& proto) { background_color_ = proto.background_color(); has_transparent_background_ = proto.has_transparent_background(); have_scroll_event_handlers_ = proto.have_scroll_event_handlers(); - have_wheel_event_handlers_ = proto.have_wheel_event_handlers(); + event_listener_properties_[static_cast<size_t>( + EventListenerClass::kMouseWheel)] = + static_cast<EventListenerProperties>( + proto.wheel_event_listener_properties()); + event_listener_properties_[static_cast<size_t>(EventListenerClass::kTouch)] = + static_cast<EventListenerProperties>( + proto.touch_event_listener_properties()); in_paint_layer_contents_ = proto.in_paint_layer_contents(); id_ = proto.id(); next_commit_forces_redraw_ = proto.next_commit_forces_redraw(); diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 9118e12..ffc028e 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -25,6 +25,7 @@ #include "cc/debug/frame_timing_tracker.h" #include "cc/debug/micro_benchmark.h" #include "cc/debug/micro_benchmark_controller.h" +#include "cc/input/event_listener_properties.h" #include "cc/input/input_handler.h" #include "cc/input/layer_selection_bound.h" #include "cc/input/scrollbar.h" @@ -229,8 +230,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { } void SetHaveScrollEventHandlers(bool have_event_handlers); - bool have_wheel_event_handlers() const { return have_wheel_event_handlers_; } - void SetHaveWheelEventHandlers(bool have_event_handlers); + void SetEventListenerProperties(EventListenerClass event_class, + EventListenerProperties event_properties); + EventListenerProperties event_listener_properties( + EventListenerClass event_class) const { + return event_listener_properties_[static_cast<size_t>(event_class)]; + } const LayerTreeSettings& settings() const { return settings_; } @@ -538,7 +543,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient { bool has_transparent_background_; bool have_scroll_event_handlers_; - bool have_wheel_event_handlers_; + EventListenerProperties event_listener_properties_[static_cast<size_t>( + EventListenerClass::kNumClasses)]; scoped_ptr<AnimationRegistrar> animation_registrar_; scoped_ptr<AnimationHost> animation_host_; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index f2e31d6..7eaa142 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -572,8 +572,9 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( return false; } -bool LayerTreeHostImpl::HaveWheelEventHandlers() const { - return active_tree_->have_wheel_event_handlers(); +EventListenerProperties LayerTreeHostImpl::GetEventListenerProperties( + EventListenerClass event_class) const { + return active_tree_->event_listener_properties(event_class); } bool LayerTreeHostImpl::DoTouchEventsBlockScrollAt( diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 343cc77..6962fad 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -192,7 +192,8 @@ class CC_EXPORT LayerTreeHostImpl bool IsCurrentlyScrollingLayerAt( const gfx::Point& viewport_point, InputHandler::ScrollInputType type) const override; - bool HaveWheelEventHandlers() const override; + EventListenerProperties GetEventListenerProperties( + EventListenerClass event_class) const override; bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_port) override; scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( ui::LatencyInfo* latency) override; diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 9ea8484..fe913c3 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -717,7 +717,8 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) { // With registered event handlers, wheel scrolls don't necessarily // have to go to the main thread. - host_impl_->active_tree()->set_have_wheel_event_handlers(true); + host_impl_->active_tree()->set_event_listener_properties( + EventListenerClass::kMouseWheel, EventListenerProperties::kBlocking); InputHandler::ScrollStatus status = host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); @@ -734,8 +735,9 @@ TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) { host_impl_->ScrollEnd(EndState().get()); // And if the handlers go away, wheel scrolls can again be processed - // on impl (despite the scroll-blocks-on mode). - host_impl_->active_tree()->set_have_wheel_event_handlers(false); + // on impl. + host_impl_->active_tree()->set_event_listener_properties( + EventListenerClass::kMouseWheel, EventListenerProperties::kNone); status = host_impl_->ScrollBegin(BeginState(gfx::Point()).get(), InputHandler::WHEEL); EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 560df10..89c47e1 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -1333,7 +1333,10 @@ class LayerTreeHostTestCommit : public LayerTreeHostTest { void BeginTest() override { layer_tree_host()->SetViewportSize(gfx::Size(20, 20)); layer_tree_host()->set_background_color(SK_ColorGRAY); - layer_tree_host()->SetHaveWheelEventHandlers(true); + layer_tree_host()->SetEventListenerProperties( + EventListenerClass::kMouseWheel, EventListenerProperties::kPassive); + layer_tree_host()->SetEventListenerProperties( + EventListenerClass::kTouch, EventListenerProperties::kBlocking); layer_tree_host()->SetHaveScrollEventHandlers(true); PostSetNeedsCommitToMainThread(); @@ -1342,7 +1345,12 @@ class LayerTreeHostTestCommit : public LayerTreeHostTest { void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override { EXPECT_EQ(gfx::Size(20, 20), impl->DrawViewportSize()); EXPECT_EQ(SK_ColorGRAY, impl->active_tree()->background_color()); - EXPECT_TRUE(impl->active_tree()->have_wheel_event_handlers()); + EXPECT_EQ(EventListenerProperties::kPassive, + impl->active_tree()->event_listener_properties( + EventListenerClass::kMouseWheel)); + EXPECT_EQ(EventListenerProperties::kBlocking, + impl->active_tree()->event_listener_properties( + EventListenerClass::kTouch)); EXPECT_TRUE(impl->active_tree()->have_scroll_event_handlers()); EndTest(); diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 156996d..46561da 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -77,7 +77,7 @@ LayerTreeImpl::LayerTreeImpl( has_ever_been_drawn_(false), render_surface_layer_list_id_(0), have_scroll_event_handlers_(false), - have_wheel_event_handlers_(false), + event_listener_properties_(), top_controls_shrink_blink_size_(false), top_controls_height_(0), top_controls_shown_ratio_(top_controls_shown_ratio) {} @@ -348,7 +348,12 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) { target_tree->set_background_color(background_color()); target_tree->set_has_transparent_background(has_transparent_background()); target_tree->set_have_scroll_event_handlers(have_scroll_event_handlers()); - target_tree->set_have_wheel_event_handlers(have_wheel_event_handlers()); + target_tree->set_event_listener_properties( + EventListenerClass::kTouch, + event_listener_properties(EventListenerClass::kTouch)); + target_tree->set_event_listener_properties( + EventListenerClass::kMouseWheel, + event_listener_properties(EventListenerClass::kMouseWheel)); if (ViewportSizeInvalid()) target_tree->SetViewportSizeInvalid(); @@ -1690,7 +1695,9 @@ struct HitTestVisibleScrollableOrTouchableFunctor { return layer->IsDrawnRenderSurfaceLayerListMember() || ScrollsAnyDrawnRenderSurfaceLayerListMember(layer) || !layer->touch_event_handler_region().IsEmpty() || - layer->layer_tree_impl()->have_wheel_event_handlers(); + layer->layer_tree_impl()->event_listener_properties( + EventListenerClass::kMouseWheel) != + EventListenerProperties::kNone; } }; diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 7f4c89c..5614035 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h @@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/values.h" #include "cc/base/synced_property.h" +#include "cc/input/event_listener_properties.h" #include "cc/input/layer_selection_bound.h" #include "cc/layers/layer_impl.h" #include "cc/output/begin_frame_args.h" @@ -443,9 +444,14 @@ class CC_EXPORT LayerTreeImpl { have_scroll_event_handlers_ = have_event_handlers; } - bool have_wheel_event_handlers() const { return have_wheel_event_handlers_; } - void set_have_wheel_event_handlers(bool have_event_handlers) { - have_wheel_event_handlers_ = have_event_handlers; + EventListenerProperties event_listener_properties( + EventListenerClass event_class) const { + return event_listener_properties_[static_cast<size_t>(event_class)]; + } + void set_event_listener_properties(EventListenerClass event_class, + EventListenerProperties event_properties) { + event_listener_properties_[static_cast<size_t>(event_class)] = + event_properties; } protected: @@ -536,7 +542,8 @@ class CC_EXPORT LayerTreeImpl { int render_surface_layer_list_id_; bool have_scroll_event_handlers_; - bool have_wheel_event_handlers_; + EventListenerProperties event_listener_properties_[static_cast<size_t>( + EventListenerClass::kNumClasses)]; // Whether or not Blink's viewport size was shrunk by the height of the top // controls at the time of the last layout. diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index ee0c957..da6c031 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc @@ -103,6 +103,7 @@ LayerTreeSettings::LayerTreeSettings() image_decode_tasks_enabled(false), use_compositor_animation_timelines(true), wait_for_beginframe_interval(true), + use_mouse_wheel_gestures(false), max_staging_buffer_usage_in_bytes(32 * 1024 * 1024), memory_policy_(64 * 1024 * 1024, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, @@ -171,6 +172,7 @@ bool LayerTreeSettings::operator==(const LayerTreeSettings& other) const { use_compositor_animation_timelines == other.use_compositor_animation_timelines && wait_for_beginframe_interval == other.wait_for_beginframe_interval && + use_mouse_wheel_gestures == other.use_mouse_wheel_gestures && max_staging_buffer_usage_in_bytes == other.max_staging_buffer_usage_in_bytes && memory_policy_ == other.memory_policy_ && @@ -235,6 +237,7 @@ void LayerTreeSettings::ToProtobuf(proto::LayerTreeSettings* proto) const { proto->set_use_compositor_animation_timelines( use_compositor_animation_timelines); proto->set_wait_for_beginframe_interval(wait_for_beginframe_interval); + proto->set_use_mouse_wheel_gestures(use_mouse_wheel_gestures); proto->set_max_staging_buffer_usage_in_bytes( max_staging_buffer_usage_in_bytes); memory_policy_.ToProtobuf(proto->mutable_memory_policy()); @@ -303,6 +306,7 @@ void LayerTreeSettings::FromProtobuf(const proto::LayerTreeSettings& proto) { use_compositor_animation_timelines = proto.use_compositor_animation_timelines(); wait_for_beginframe_interval = proto.wait_for_beginframe_interval(); + use_mouse_wheel_gestures = proto.use_mouse_wheel_gestures(); max_staging_buffer_usage_in_bytes = proto.max_staging_buffer_usage_in_bytes(); memory_policy_.FromProtobuf(proto.memory_policy()); initial_debug_state.FromProtobuf(proto.initial_debug_state()); diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index b5e983b..ff00f5d 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h @@ -88,6 +88,7 @@ class CC_EXPORT LayerTreeSettings { bool image_decode_tasks_enabled; bool use_compositor_animation_timelines; bool wait_for_beginframe_interval; + bool use_mouse_wheel_gestures; int max_staging_buffer_usage_in_bytes; ManagedMemoryPolicy memory_policy_; diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 9bd5b80..063e2dd 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -257,6 +257,9 @@ void RenderWidgetCompositor::Initialize(float device_scale_factor) { blink::WebRuntimeFeatures::enableCompositorAnimationTimelines( settings.use_compositor_animation_timelines); + settings.use_mouse_wheel_gestures = + cmd->HasSwitch(switches::kEnableWheelGestures); + settings.default_tile_size = CalculateDefaultTileSize(device_scale_factor); if (cmd->HasSwitch(switches::kDefaultTileWidth)) { int tile_width = 0; @@ -743,12 +746,42 @@ void RenderWidgetCompositor::clearSelection() { layer_tree_host_->RegisterSelection(empty_selection); } -void RenderWidgetCompositor::setHaveWheelEventHandlers(bool value) { - layer_tree_host_->SetHaveWheelEventHandlers(value); -} - -bool RenderWidgetCompositor::haveWheelEventHandlers() const { - return layer_tree_host_->have_wheel_event_handlers(); +static_assert( + static_cast<cc::EventListenerClass>(blink::WebEventListenerClass::Touch) == + cc::EventListenerClass::kTouch, + "EventListenerClass and WebEventListenerClass enums must match"); +static_assert(static_cast<cc::EventListenerClass>( + blink::WebEventListenerClass::MouseWheel) == + cc::EventListenerClass::kMouseWheel, + "EventListenerClass and WebEventListenerClass enums must match"); + +static_assert(static_cast<cc::EventListenerProperties>( + blink::WebEventListenerProperties::Nothing) == + cc::EventListenerProperties::kNone, + "EventListener and WebEventListener enums must match"); +static_assert(static_cast<cc::EventListenerProperties>( + blink::WebEventListenerProperties::Passive) == + cc::EventListenerProperties::kPassive, + "EventListener and WebEventListener enums must match"); +static_assert(static_cast<cc::EventListenerProperties>( + blink::WebEventListenerProperties::Blocking) == + cc::EventListenerProperties::kBlocking, + "EventListener and WebEventListener enums must match"); + +void RenderWidgetCompositor::setEventListenerProperties( + blink::WebEventListenerClass eventClass, + blink::WebEventListenerProperties properties) { + layer_tree_host_->SetEventListenerProperties( + static_cast<cc::EventListenerClass>(eventClass), + static_cast<cc::EventListenerProperties>(properties)); +} + +blink::WebEventListenerProperties +RenderWidgetCompositor::eventListenerProperties( + blink::WebEventListenerClass event_class) const { + return static_cast<blink::WebEventListenerProperties>( + layer_tree_host_->event_listener_properties( + static_cast<cc::EventListenerClass>(event_class))); } void RenderWidgetCompositor::setHaveScrollEventHandlers(bool has_handlers) { diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index 2e19c20..3844b37 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h @@ -135,8 +135,11 @@ class CONTENT_EXPORT RenderWidgetCompositor void clearViewportLayers() override; void registerSelection(const blink::WebSelection& selection) override; void clearSelection() override; - void setHaveWheelEventHandlers(bool) override; - bool haveWheelEventHandlers() const override; + void setEventListenerProperties( + blink::WebEventListenerClass eventClass, + blink::WebEventListenerProperties properties) override; + blink::WebEventListenerProperties eventListenerProperties( + blink::WebEventListenerClass eventClass) const override; void setHaveScrollEventHandlers(bool) override; bool haveScrollEventHandlers() const override; int layerTreeId() const override; diff --git a/content/test/web_layer_tree_view_impl_for_testing.cc b/content/test/web_layer_tree_view_impl_for_testing.cc index 929cde2..343dc67 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.cc +++ b/content/test/web_layer_tree_view_impl_for_testing.cc @@ -200,13 +200,22 @@ void WebLayerTreeViewImplForTesting::registerSelection( void WebLayerTreeViewImplForTesting::clearSelection() { } -void WebLayerTreeViewImplForTesting::setHaveWheelEventHandlers( - bool have_event_handlers) { - layer_tree_host_->SetHaveWheelEventHandlers(have_event_handlers); -} - -bool WebLayerTreeViewImplForTesting::haveWheelEventHandlers() const { - return layer_tree_host_->have_wheel_event_handlers(); +void WebLayerTreeViewImplForTesting::setEventListenerProperties( + blink::WebEventListenerClass eventClass, + blink::WebEventListenerProperties properties) { + // Equality of static_cast is checked in render_widget_compositor.cc. + layer_tree_host_->SetEventListenerProperties( + static_cast<cc::EventListenerClass>(eventClass), + static_cast<cc::EventListenerProperties>(properties)); +} + +blink::WebEventListenerProperties +WebLayerTreeViewImplForTesting::eventListenerProperties( + blink::WebEventListenerClass event_class) const { + // Equality of static_cast is checked in render_widget_compositor.cc. + return static_cast<blink::WebEventListenerProperties>( + layer_tree_host_->event_listener_properties( + static_cast<cc::EventListenerClass>(event_class))); } void WebLayerTreeViewImplForTesting::setHaveScrollEventHandlers( diff --git a/content/test/web_layer_tree_view_impl_for_testing.h b/content/test/web_layer_tree_view_impl_for_testing.h index d3d5ed0..01901c4 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.h +++ b/content/test/web_layer_tree_view_impl_for_testing.h @@ -67,8 +67,11 @@ class WebLayerTreeViewImplForTesting void clearViewportLayers() override; void registerSelection(const blink::WebSelection& selection) override; void clearSelection() override; - void setHaveWheelEventHandlers(bool have_event_handlers) override; - bool haveWheelEventHandlers() const override; + void setEventListenerProperties( + blink::WebEventListenerClass event_class, + blink::WebEventListenerProperties properties) override; + blink::WebEventListenerProperties eventListenerProperties( + blink::WebEventListenerClass event_class) const override; void setHaveScrollEventHandlers(bool) override; bool haveScrollEventHandlers() const override; diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index 89d93e2..1bbe752 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp @@ -1823,7 +1823,7 @@ bool Node::addEventListenerInternal(const AtomicString& eventType, PassRefPtrWil document().addListenerTypeIfNeeded(eventType); if (FrameHost* frameHost = document().frameHost()) - frameHost->eventHandlerRegistry().didAddEventHandler(*this, eventType); + frameHost->eventHandlerRegistry().didAddEventHandler(*this, eventType, options); return true; } @@ -1836,7 +1836,7 @@ bool Node::removeEventListenerInternal(const AtomicString& eventType, PassRefPtr // FIXME: Notify Document that the listener has vanished. We need to keep track of a number of // listeners for each type, not just a bool - see https://bugs.webkit.org/show_bug.cgi?id=33861 if (FrameHost* frameHost = document().frameHost()) - frameHost->eventHandlerRegistry().didRemoveEventHandler(*this, eventType); + frameHost->eventHandlerRegistry().didRemoveEventHandler(*this, eventType, options); return true; } diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp index 1a8c32c..b889e6c 100644 --- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp +++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.cpp @@ -4,6 +4,7 @@ #include "core/frame/EventHandlerRegistry.h" +#include "core/events/EventListenerOptions.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/LocalFrame.h" #include "core/html/HTMLFrameOwnerElement.h" @@ -37,6 +38,15 @@ inline bool isPointerEventType(const AtomicString& eventType) || eventType == EventTypeNames::pointerup; } +WebEventListenerProperties webEventListenerProperties(bool hasBlocking, bool hasPassive) +{ + if (hasBlocking) + return WebEventListenerProperties::Blocking; + if (hasPassive) + return WebEventListenerProperties::Passive; + return WebEventListenerProperties::Nothing; +} + } // namespace EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost) @@ -49,18 +59,19 @@ EventHandlerRegistry::~EventHandlerRegistry() checkConsistency(); } -bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result) +bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, const EventListenerOptions& options, EventHandlerClass* result) { if (eventType == EventTypeNames::scroll) { *result = ScrollEvent; } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) { - *result = WheelEvent; + *result = options.passive() ? WheelEventPassive : WheelEventBlocking; } else if (isTouchEventType(eventType)) { - *result = TouchEvent; + *result = options.passive() ? TouchEventPassive : TouchEventBlocking; } else if (isPointerEventType(eventType)) { - // The EventHandlerClass is still TouchEvent below since we are firing PointerEvents only from - // EventHandler::handleTouchEvent for now. See crbug.com/476565. - *result = TouchEvent; + // The EventHandlerClass is TouchEventPassive since the pointer events + // never block scrolling and the compositor only needs to know + // about the touch listeners. + *result = TouchEventPassive; #if ENABLE(ASSERT) } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) { *result = EventsForTesting; @@ -122,22 +133,22 @@ void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventH notifyDidAddOrRemoveEventHandlerTarget(handlerClass); } -void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target) +void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, const EventListenerOptions& options, EventTarget* target) { EventHandlerClass handlerClass; - if (!eventTypeToClass(eventType, &handlerClass)) + if (!eventTypeToClass(eventType, options, &handlerClass)) return; updateEventHandlerInternal(op, handlerClass, target); } -void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType) +void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType, const EventListenerOptions& options) { - updateEventHandlerOfType(Add, eventType, &target); + updateEventHandlerOfType(Add, eventType, options, &target); } -void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType) +void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType, const EventListenerOptions& options) { - updateEventHandlerOfType(Remove, eventType, &target); + updateEventHandlerOfType(Remove, eventType, options, &target); } void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass) @@ -155,16 +166,19 @@ void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target) if (!target.hasEventListeners()) return; + // This code is not efficient at all. Vector<AtomicString> eventTypes = target.eventTypes(); for (size_t i = 0; i < eventTypes.size(); ++i) { - EventHandlerClass handlerClass; - if (!eventTypeToClass(eventTypes[i], &handlerClass)) - continue; EventListenerVector* listeners = target.getEventListeners(eventTypes[i]); if (!listeners) continue; - for (unsigned count = listeners->size(); count > 0; --count) + for (unsigned count = listeners->size(); count > 0; --count) { + EventHandlerClass handlerClass; + if (!eventTypeToClass(eventTypes[i], (*listeners)[count - 1].options(), &handlerClass)) + continue; + didAddEventHandler(target, handlerClass); + } } } @@ -199,11 +213,13 @@ void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla case ScrollEvent: m_frameHost->chromeClient().setHaveScrollEventHandlers(hasActiveHandlers); break; - case WheelEvent: - m_frameHost->chromeClient().setHaveWheelEventHandlers(hasActiveHandlers); + case WheelEventBlocking: + case WheelEventPassive: + m_frameHost->chromeClient().setEventListenerProperties(WebEventListenerClass::MouseWheel, webEventListenerProperties(hasEventHandlers(WheelEventBlocking), hasEventHandlers(WheelEventPassive))); break; - case TouchEvent: - m_frameHost->chromeClient().needTouchEvents(hasActiveHandlers); + case TouchEventBlocking: + case TouchEventPassive: + m_frameHost->chromeClient().setEventListenerProperties(WebEventListenerClass::Touch, webEventListenerProperties(hasEventHandlers(TouchEventBlocking), hasEventHandlers(TouchEventPassive))); break; #if ENABLE(ASSERT) case EventsForTesting: @@ -218,7 +234,7 @@ void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerCla void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass handlerClass) { ScrollingCoordinator* scrollingCoordinator = m_frameHost->page().scrollingCoordinator(); - if (scrollingCoordinator && handlerClass == TouchEvent) + if (scrollingCoordinator && handlerClass == TouchEventBlocking) scrollingCoordinator->touchEventTargetRectsDidChange(); } diff --git a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h index 18de823..38a8e95 100644 --- a/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h +++ b/third_party/WebKit/Source/core/frame/EventHandlerRegistry.h @@ -12,6 +12,7 @@ namespace blink { class Document; +class EventListenerOptions; class EventTarget; typedef HashCountedSet<RawPtrWillBeUntracedMember<EventTarget>> EventTargetSet; @@ -29,8 +30,10 @@ public: // multiple event types. enum EventHandlerClass { ScrollEvent, - WheelEvent, - TouchEvent, + WheelEventBlocking, + WheelEventPassive, + TouchEventBlocking, + TouchEventPassive, #if ENABLE(ASSERT) // Additional event categories for verifying handler tracking logic. EventsForTesting, @@ -45,9 +48,9 @@ public: const EventTargetSet* eventHandlerTargets(EventHandlerClass) const; // Registration and management of event handlers attached to EventTargets. - void didAddEventHandler(EventTarget&, const AtomicString& eventType); + void didAddEventHandler(EventTarget&, const AtomicString& eventType, const EventListenerOptions&); void didAddEventHandler(EventTarget&, EventHandlerClass); - void didRemoveEventHandler(EventTarget&, const AtomicString& eventType); + void didRemoveEventHandler(EventTarget&, const AtomicString& eventType, const EventListenerOptions&); void didRemoveEventHandler(EventTarget&, EventHandlerClass); void didRemoveAllEventHandlers(EventTarget&); @@ -72,7 +75,7 @@ private: }; // Returns true if |eventType| belongs to a class this registry tracks. - static bool eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result); + static bool eventTypeToClass(const AtomicString& eventType, const EventListenerOptions&, EventHandlerClass* result); // Returns true if the operation actually added a new target or completely // removed an existing one. @@ -91,7 +94,7 @@ private: // Record a change operation to a given event handler class and notify any // parent registry and other clients accordingly. - void updateEventHandlerOfType(ChangeOperation, const AtomicString& eventType, EventTarget*); + void updateEventHandlerOfType(ChangeOperation, const AtomicString& eventType, const EventListenerOptions&, EventTarget*); void updateEventHandlerInternal(ChangeOperation, EventHandlerClass, EventTarget*); diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index 31164e3..af33c13 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp @@ -1305,7 +1305,7 @@ bool LocalDOMWindow::addEventListenerInternal(const AtomicString& eventType, Pas return false; if (frame() && frame()->host()) - frame()->host()->eventHandlerRegistry().didAddEventHandler(*this, eventType); + frame()->host()->eventHandlerRegistry().didAddEventHandler(*this, eventType, options); if (Document* document = this->document()) { document->addListenerTypeIfNeeded(eventType); @@ -1338,7 +1338,7 @@ bool LocalDOMWindow::removeEventListenerInternal(const AtomicString& eventType, return false; if (frame() && frame()->host()) - frame()->host()->eventHandlerRegistry().didRemoveEventHandler(*this, eventType); + frame()->host()->eventHandlerRegistry().didRemoveEventHandler(*this, eventType, options); notifyRemoveEventListener(this, eventType); diff --git a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp index 4e1fd34..b516a88 100644 --- a/third_party/WebKit/Source/core/html/HTMLInputElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLInputElement.cpp @@ -175,8 +175,10 @@ HTMLInputElement::~HTMLInputElement() // We should unregister it to avoid accessing a deleted object. if (type() == InputTypeNames::radio) document().formController().radioButtonGroupScope().removeButton(this); + + // TODO(dtapuska): Make this passive touch listener see crbug.com/584438 if (m_hasTouchEventHandler && document().frameHost()) - document().frameHost()->eventHandlerRegistry().didRemoveEventHandler(*this, EventHandlerRegistry::TouchEvent); + document().frameHost()->eventHandlerRegistry().didRemoveEventHandler(*this, EventHandlerRegistry::TouchEventBlocking); #endif } @@ -426,10 +428,11 @@ void HTMLInputElement::updateTouchEventHandlerRegistry() // If the Document is being or has been stopped, don't register any handlers. if (document().frameHost() && document().lifecycle().state() < DocumentLifecycle::Stopping) { EventHandlerRegistry& registry = document().frameHost()->eventHandlerRegistry(); + // TODO(dtapuska): Make this passive touch listener see crbug.com/584438 if (hasTouchEventHandler) - registry.didAddEventHandler(*this, EventHandlerRegistry::TouchEvent); + registry.didAddEventHandler(*this, EventHandlerRegistry::TouchEventBlocking); else - registry.didRemoveEventHandler(*this, EventHandlerRegistry::TouchEvent); + registry.didRemoveEventHandler(*this, EventHandlerRegistry::TouchEventBlocking); m_hasTouchEventHandler = hasTouchEventHandler; } } diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index 5ec337e..4939887 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp @@ -104,6 +104,12 @@ namespace blink { namespace { +bool hasTouchHandlers(const EventHandlerRegistry& registry) +{ + return registry.hasEventHandlers(EventHandlerRegistry::TouchEventBlocking) + || registry.hasEventHandlers(EventHandlerRegistry::TouchEventPassive); +} + WebInputEventResult mergeEventResult(WebInputEventResult responseA, WebInputEventResult responseB) { // The ordering of the enumeration is specific. There are times that @@ -4002,7 +4008,7 @@ WebInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEvent& eve // If there's no document receiving touch events, or no handlers on the // document set to receive the events, then we can skip all the rest of // this work. - if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !m_touchSequenceDocument->frameHost()->eventHandlerRegistry().hasEventHandlers(EventHandlerRegistry::TouchEvent) || !m_touchSequenceDocument->frame()) { + if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !hasTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) { if (allTouchReleased) { m_touchSequenceDocument.clear(); m_touchSequenceUserGestureToken.clear(); diff --git a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp index c29f82e..602466e 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorLayerTreeAgent.cpp @@ -212,9 +212,9 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> > InspectorLayerTre RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> > layers = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create(); buildLayerIdToNodeIdMap(compositor->rootLayer(), layerIdToNodeIdMap); int scrollingLayerId = m_inspectedFrames->root()->view()->layerForScrolling()->platformLayer()->id(); - bool haveWheelEventHandlers = m_inspectedFrames->root()->chromeClient().haveWheelEventHandlers(); + bool haveBlockingWheelEventHandlers = m_inspectedFrames->root()->chromeClient().eventListenerProperties(WebEventListenerClass::MouseWheel) == WebEventListenerProperties::Blocking; - gatherGraphicsLayers(rootGraphicsLayer(), layerIdToNodeIdMap, layers, haveWheelEventHandlers, scrollingLayerId); + gatherGraphicsLayers(rootGraphicsLayer(), layerIdToNodeIdMap, layers, haveBlockingWheelEventHandlers, scrollingLayerId); return layers.release(); } diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index 4d1fd3e..96e6990 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp @@ -2044,13 +2044,14 @@ void LayoutObject::styleWillChange(StyleDifference diff, const ComputedStyle& ne // // Since a CSS property cannot be applied directly to a text node, a // handler will have already been added for its parent so ignore it. + // TODO: Remove this blocking event handler; crbug.com/318381 TouchAction oldTouchAction = m_style ? m_style->touchAction() : TouchActionAuto; if (node() && !node()->isTextNode() && (oldTouchAction == TouchActionAuto) != (newStyle.touchAction() == TouchActionAuto)) { EventHandlerRegistry& registry = document().frameHost()->eventHandlerRegistry(); if (newStyle.touchAction() != TouchActionAuto) - registry.didAddEventHandler(*node(), EventHandlerRegistry::TouchEvent); + registry.didAddEventHandler(*node(), EventHandlerRegistry::TouchEventBlocking); else - registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchEvent); + registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchEventBlocking); } } @@ -2572,8 +2573,8 @@ void LayoutObject::willBeDestroyed() // previously may have already been removed by the Document independently. if (node() && !node()->isTextNode() && m_style && m_style->touchAction() != TouchActionAuto) { EventHandlerRegistry& registry = document().frameHost()->eventHandlerRegistry(); - if (registry.eventHandlerTargets(EventHandlerRegistry::TouchEvent)->contains(node())) - registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchEvent); + if (registry.eventHandlerTargets(EventHandlerRegistry::TouchEventBlocking)->contains(node())) + registry.didRemoveEventHandler(*node(), EventHandlerRegistry::TouchEventBlocking); } setAncestorLineBoxDirty(false); diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h index f7eb8bf..8ab1166 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.h +++ b/third_party/WebKit/Source/core/loader/EmptyClients.h @@ -156,9 +156,8 @@ public: void attachRootGraphicsLayer(GraphicsLayer*, LocalFrame* localRoot) override {} - void needTouchEvents(bool) override {} - void setHaveWheelEventHandlers(bool) override {} - bool haveWheelEventHandlers() const override { return false; } + void setEventListenerProperties(WebEventListenerClass, WebEventListenerProperties) override {} + WebEventListenerProperties eventListenerProperties(WebEventListenerClass) const override { return WebEventListenerProperties::Nothing; } void setHaveScrollEventHandlers(bool) override {} bool haveScrollEventHandlers() const override { return false; } diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index d9ff102..c4784a02 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp @@ -1095,8 +1095,10 @@ void FrameLoader::commitProvisionalLoad() if (!prepareForCommit()) return; - if (isLoadingMainFrame()) - m_frame->page()->chromeClient().needTouchEvents(false); + if (isLoadingMainFrame()) { + m_frame->page()->chromeClient().setEventListenerProperties(WebEventListenerClass::Touch, WebEventListenerProperties::Nothing); + m_frame->page()->chromeClient().setEventListenerProperties(WebEventListenerClass::MouseWheel, WebEventListenerProperties::Nothing); + } client()->transitionToCommittedForNewPage(); m_frame->navigationScheduler().cancel(); diff --git a/third_party/WebKit/Source/core/page/ChromeClient.h b/third_party/WebKit/Source/core/page/ChromeClient.h index 9ae983b..f28f6f5 100644 --- a/third_party/WebKit/Source/core/page/ChromeClient.h +++ b/third_party/WebKit/Source/core/page/ChromeClient.h @@ -35,6 +35,7 @@ #include "platform/PopupMenu.h" #include "platform/heap/Handle.h" #include "platform/scroll/ScrollTypes.h" +#include "public/platform/WebEventListenerProperties.h" #include "public/platform/WebFocusType.h" #include "wtf/Forward.h" #include "wtf/PassOwnPtr.h" @@ -198,9 +199,8 @@ public: virtual void clearCompositedSelection() { } virtual void updateCompositedSelection(const CompositedSelection&) { } - virtual void needTouchEvents(bool) = 0; - virtual void setHaveWheelEventHandlers(bool) = 0; - virtual bool haveWheelEventHandlers() const = 0; + virtual void setEventListenerProperties(WebEventListenerClass, WebEventListenerProperties) = 0; + virtual WebEventListenerProperties eventListenerProperties(WebEventListenerClass) const = 0; virtual void setHaveScrollEventHandlers(bool) = 0; virtual bool haveScrollEventHandlers() const = 0; diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp index 3a64da2..5f013b1 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp @@ -792,7 +792,7 @@ Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion( static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects, const Document* document) { ASSERT(document); - const EventTargetSet* targets = document->frameHost()->eventHandlerRegistry().eventHandlerTargets(EventHandlerRegistry::TouchEvent); + const EventTargetSet* targets = document->frameHost()->eventHandlerRegistry().eventHandlerTargets(EventHandlerRegistry::TouchEventBlocking); if (!targets) return; diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 624aaa7..0b11442 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp @@ -1259,7 +1259,7 @@ static unsigned eventHandlerCount(Document& document, EventHandlerRegistry::Even unsigned Internals::wheelEventHandlerCount(Document* document) { ASSERT(document); - return eventHandlerCount(*document, EventHandlerRegistry::WheelEvent); + return eventHandlerCount(*document, EventHandlerRegistry::WheelEventBlocking); } unsigned Internals::scrollEventHandlerCount(Document* document) @@ -1271,7 +1271,7 @@ unsigned Internals::scrollEventHandlerCount(Document* document) unsigned Internals::touchEventHandlerCount(Document* document) { ASSERT(document); - return eventHandlerCount(*document, EventHandlerRegistry::TouchEvent); + return eventHandlerCount(*document, EventHandlerRegistry::TouchEventBlocking); } static PaintLayer* findLayerForGraphicsLayer(PaintLayer* searchRoot, GraphicsLayer* graphicsLayer, IntSize* layerOffset, String* layerType) diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index 02bb02e..c5af44a 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp @@ -876,22 +876,20 @@ bool ChromeClientImpl::shouldOpenModalDialogDuringPageDismissal(const DialogType return false; } -void ChromeClientImpl::needTouchEvents(bool needsTouchEvents) +void ChromeClientImpl::setEventListenerProperties(WebEventListenerClass eventClass, WebEventListenerProperties properties) { - m_webView->hasTouchEventHandlers(needsTouchEvents); -} + if (eventClass == WebEventListenerClass::Touch) + m_webView->hasTouchEventHandlers(properties != WebEventListenerProperties::Nothing); -void ChromeClientImpl::setHaveWheelEventHandlers(bool hasEventHandlers) -{ if (WebLayerTreeView* treeView = m_webView->layerTreeView()) - treeView->setHaveWheelEventHandlers(hasEventHandlers); + treeView->setEventListenerProperties(eventClass, properties); } -bool ChromeClientImpl::haveWheelEventHandlers() const +WebEventListenerProperties ChromeClientImpl::eventListenerProperties(WebEventListenerClass eventClass) const { if (WebLayerTreeView* treeView = m_webView->layerTreeView()) - return treeView->haveWheelEventHandlers(); - return false; + return treeView->eventListenerProperties(eventClass); + return WebEventListenerProperties::Nothing; } void ChromeClientImpl::setHaveScrollEventHandlers(bool hasEventHandlers) diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.h b/third_party/WebKit/Source/web/ChromeClientImpl.h index a4deb53..f72432e 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.h +++ b/third_party/WebKit/Source/web/ChromeClientImpl.h @@ -111,9 +111,8 @@ public: void enumerateChosenDirectory(FileChooser*) override; void setCursor(const Cursor&, LocalFrame* localRoot) override; Cursor lastSetCursorForTesting() const override; - void needTouchEvents(bool needTouchEvents) override; - void setHaveWheelEventHandlers(bool hasEventHandlers) override; - bool haveWheelEventHandlers() const override; + void setEventListenerProperties(WebEventListenerClass, WebEventListenerProperties) override; + WebEventListenerProperties eventListenerProperties(WebEventListenerClass) const override; void setHaveScrollEventHandlers(bool hasEventHandlers) override; bool haveScrollEventHandlers() const override; void setTouchAction(TouchAction) override; diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp index 61cb672..379526b 100644 --- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp +++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp @@ -163,22 +163,18 @@ private: m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor)); } - void needTouchEvents(bool needsTouchEvents) override - { - m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents); - } - - void setHaveWheelEventHandlers(bool haveEventHandlers) override + void setEventListenerProperties(WebEventListenerClass eventClass, WebEventListenerProperties properties) override { + if (eventClass == WebEventListenerClass::Touch) + m_popup->widgetClient()->hasTouchEventHandlers(properties != WebEventListenerProperties::Nothing); if (m_popup->m_layerTreeView) - return m_popup->m_layerTreeView->setHaveWheelEventHandlers(haveEventHandlers); + m_popup->m_layerTreeView->setEventListenerProperties(eventClass, properties); } - - bool haveWheelEventHandlers() const override + WebEventListenerProperties eventListenerProperties(WebEventListenerClass eventClass) const override { if (m_popup->m_layerTreeView) - return m_popup->m_layerTreeView->haveWheelEventHandlers(); - return false; + return m_popup->m_layerTreeView->eventListenerProperties(eventClass); + return WebEventListenerProperties::Nothing; } void setHaveScrollEventHandlers(bool hasEventHandlers) override diff --git a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp index 8334f59..60ba3f8 100644 --- a/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp +++ b/third_party/WebKit/Source/web/WebPluginContainerImpl.cpp @@ -538,9 +538,9 @@ void WebPluginContainerImpl::requestTouchEventType(TouchEventRequestType request if (m_element->document().frameHost()) { EventHandlerRegistry& registry = m_element->document().frameHost()->eventHandlerRegistry(); if (requestType != TouchEventRequestTypeNone && m_touchEventRequestType == TouchEventRequestTypeNone) - registry.didAddEventHandler(*m_element, EventHandlerRegistry::TouchEvent); + registry.didAddEventHandler(*m_element, EventHandlerRegistry::TouchEventBlocking); else if (requestType == TouchEventRequestTypeNone && m_touchEventRequestType != TouchEventRequestTypeNone) - registry.didRemoveEventHandler(*m_element, EventHandlerRegistry::TouchEvent); + registry.didRemoveEventHandler(*m_element, EventHandlerRegistry::TouchEventBlocking); } m_touchEventRequestType = requestType; } diff --git a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp index 84c605e..e113df1 100644 --- a/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp +++ b/third_party/WebKit/Source/web/tests/ScrollingCoordinatorTest.cpp @@ -126,7 +126,8 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingByDefault) WebLayer* rootScrollLayer = getRootScrollLayer(); ASSERT_TRUE(rootScrollLayer->scrollable()); ASSERT_FALSE(rootScrollLayer->shouldScrollOnMainThread()); - ASSERT_FALSE(webLayerTreeView()->haveWheelEventHandlers()); + ASSERT_EQ(WebEventListenerProperties::Nothing, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::Touch)); + ASSERT_EQ(WebEventListenerProperties::Nothing, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::MouseWheel)); } TEST_F(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) @@ -306,13 +307,58 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingForFixedPosition) } } +TEST_F(ScrollingCoordinatorTest, touchEventHandler) +{ + registerMockedHttpURLLoad("touch-event-handler.html"); + navigateTo(m_baseURL + "touch-event-handler.html"); + forceFullCompositingUpdate(); + + ASSERT_EQ(WebEventListenerProperties::Blocking, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::Touch)); +} + +TEST_F(ScrollingCoordinatorTest, touchEventHandlerPassive) +{ + registerMockedHttpURLLoad("touch-event-handler-passive.html"); + navigateTo(m_baseURL + "touch-event-handler-passive.html"); + forceFullCompositingUpdate(); + + ASSERT_EQ(WebEventListenerProperties::Passive, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::Touch)); +} + +TEST_F(ScrollingCoordinatorTest, touchEventHandlerBoth) +{ + registerMockedHttpURLLoad("touch-event-handler-both.html"); + navigateTo(m_baseURL + "touch-event-handler-both.html"); + forceFullCompositingUpdate(); + + ASSERT_EQ(WebEventListenerProperties::Blocking, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::Touch)); +} + TEST_F(ScrollingCoordinatorTest, wheelEventHandler) { registerMockedHttpURLLoad("wheel-event-handler.html"); navigateTo(m_baseURL + "wheel-event-handler.html"); forceFullCompositingUpdate(); - ASSERT_TRUE(webLayerTreeView()->haveWheelEventHandlers()); + ASSERT_EQ(WebEventListenerProperties::Blocking, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::MouseWheel)); +} + +TEST_F(ScrollingCoordinatorTest, wheelEventHandlerPassive) +{ + registerMockedHttpURLLoad("wheel-event-handler-passive.html"); + navigateTo(m_baseURL + "wheel-event-handler-passive.html"); + forceFullCompositingUpdate(); + + ASSERT_EQ(WebEventListenerProperties::Passive, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::MouseWheel)); +} + +TEST_F(ScrollingCoordinatorTest, wheelEventHandlerBoth) +{ + registerMockedHttpURLLoad("wheel-event-handler-both.html"); + navigateTo(m_baseURL + "wheel-event-handler-both.html"); + forceFullCompositingUpdate(); + + ASSERT_EQ(WebEventListenerProperties::Blocking, webLayerTreeView()->eventListenerProperties(WebEventListenerClass::MouseWheel)); } TEST_F(ScrollingCoordinatorTest, scrollEventHandler) diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp index 46ce4ec..15bc88c 100644 --- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp @@ -2308,7 +2308,7 @@ TEST_F(WebViewTest, HasTouchEventHandlers) std::string url = m_baseURL + "has_touch_event_handlers.html"; URLTestHelpers::registerMockedURLLoad(toKURL(url), "has_touch_event_handlers.html"); WebViewImpl* webViewImpl = m_webViewHelper.initializeAndLoad(url, true, 0, &client); - const EventHandlerRegistry::EventHandlerClass touchEvent = EventHandlerRegistry::TouchEvent; + const EventHandlerRegistry::EventHandlerClass touchEvent = EventHandlerRegistry::TouchEventBlocking; // The page is initialized with at least one no-handlers call. // In practice we get two such calls because WebViewHelper::initializeAndLoad first diff --git a/third_party/WebKit/Source/web/tests/data/touch-event-handler-both.html b/third_party/WebKit/Source/web/tests/data/touch-event-handler-both.html new file mode 100644 index 0000000..b04bb10 --- /dev/null +++ b/third_party/WebKit/Source/web/tests/data/touch-event-handler-both.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <script type="text/javascript"> + window.addEventListener('touchstart', function(event) { + }, {passive: true} ); + window.addEventListener('touchstart', function(event) { + }, {passive: false} ); + </script> +</head> + +</html> diff --git a/third_party/WebKit/Source/web/tests/data/touch-event-handler-passive.html b/third_party/WebKit/Source/web/tests/data/touch-event-handler-passive.html new file mode 100644 index 0000000..a76699c --- /dev/null +++ b/third_party/WebKit/Source/web/tests/data/touch-event-handler-passive.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <script type="text/javascript"> + window.addEventListener('touchstart', function(event) { + }, {passive: true} ); + </script> +</head> + +</html> diff --git a/third_party/WebKit/Source/web/tests/data/touch-event-handler.html b/third_party/WebKit/Source/web/tests/data/touch-event-handler.html new file mode 100644 index 0000000..208be23 --- /dev/null +++ b/third_party/WebKit/Source/web/tests/data/touch-event-handler.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <script type="text/javascript"> + window.addEventListener('touchstart', function(event) { + }); + </script> +</head> + +</html> diff --git a/third_party/WebKit/Source/web/tests/data/wheel-event-handler-both.html b/third_party/WebKit/Source/web/tests/data/wheel-event-handler-both.html new file mode 100644 index 0000000..24d7d146 --- /dev/null +++ b/third_party/WebKit/Source/web/tests/data/wheel-event-handler-both.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <script type="text/javascript"> + window.addEventListener('mousewheel', function(event) { + }, {passive: true}); + window.addEventListener('mousewheel', function(event) { + }, {passive: false}); + </script> +</head> + +</html> diff --git a/third_party/WebKit/Source/web/tests/data/wheel-event-handler-passive.html b/third_party/WebKit/Source/web/tests/data/wheel-event-handler-passive.html new file mode 100644 index 0000000..5f15b59 --- /dev/null +++ b/third_party/WebKit/Source/web/tests/data/wheel-event-handler-passive.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <script type="text/javascript"> + window.addEventListener('mousewheel', function(event) { + }, {passive: true}); + </script> +</head> + +</html> diff --git a/third_party/WebKit/public/platform/WebEventListenerProperties.h b/third_party/WebKit/public/platform/WebEventListenerProperties.h new file mode 100644 index 0000000..56ec72f --- /dev/null +++ b/third_party/WebKit/public/platform/WebEventListenerProperties.h @@ -0,0 +1,26 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebEventListenerProperties_h +#define WebEventListenerProperties_h + +#include "WebCommon.h" + +namespace blink { + +enum class WebEventListenerClass { + Touch, // This value includes "pointer" events. + MouseWheel // This value includes "wheel" and "mousewheel" events. +}; + +// Indicates the variety of event listener types for a given WebEventListenerClass. +enum class WebEventListenerProperties { + Nothing, // This should be "None"; but None #defined in X11's X.h + Passive, + Blocking, // This indicates >= 1 blocking listener (and >= 0 passive listeners) +}; + +} // namespace blink + +#endif diff --git a/third_party/WebKit/public/platform/WebLayerTreeView.h b/third_party/WebKit/public/platform/WebLayerTreeView.h index fc9688d..c21285d 100644 --- a/third_party/WebKit/public/platform/WebLayerTreeView.h +++ b/third_party/WebKit/public/platform/WebLayerTreeView.h @@ -28,6 +28,7 @@ #include "WebColor.h" #include "WebCommon.h" +#include "WebEventListenerProperties.h" #include "WebFloatPoint.h" #include "WebNonCopyable.h" #include "WebPrivateOwnPtr.h" @@ -142,12 +143,12 @@ public: virtual void clearSelection() { } // Input properties --------------------------------------------------- - virtual void setHaveWheelEventHandlers(bool) { }; + virtual void setEventListenerProperties(WebEventListenerClass, WebEventListenerProperties) { }; virtual void setHaveScrollEventHandlers(bool) { }; // Debugging / dangerous --------------------------------------------- - virtual bool haveWheelEventHandlers() const { return false; }; + virtual WebEventListenerProperties eventListenerProperties(WebEventListenerClass) const { return WebEventListenerProperties::Nothing; }; virtual bool haveScrollEventHandlers() const { return false; }; virtual int layerTreeId() const { return 0; } diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index b22957e..cecf7df 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc @@ -288,7 +288,9 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( const WebGestureEvent& gesture_event = static_cast<const WebGestureEvent&>(event); if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad && - input_handler_->HaveWheelEventHandlers()) { + input_handler_->GetEventListenerProperties( + cc::EventListenerClass::kMouseWheel) != + cc::EventListenerProperties::kNone) { return DID_NOT_HANDLE; } else { input_handler_->PinchGestureBegin(); diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index 16e3542..8106b12 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc @@ -131,7 +131,9 @@ class MockInputHandler : public cc::InputHandler { bool(const gfx::Point& point, cc::InputHandler::ScrollInputType type)); - MOCK_CONST_METHOD0(HaveWheelEventHandlers, bool()); + MOCK_CONST_METHOD1( + GetEventListenerProperties, + cc::EventListenerProperties(cc::EventListenerClass event_class)); MOCK_METHOD1(DoTouchEventsBlockScrollAt, bool(const gfx::Point& point)); MOCK_METHOD0(RequestUpdateForSynchronousInputHandler, void()); @@ -625,8 +627,9 @@ TEST_P(InputHandlerProxyTest, GesturePinch) { VERIFY_AND_RESET_MOCKS(); gesture_.type = WebInputEvent::GesturePinchBegin; - EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlers()) - .WillOnce(testing::Return(false)); + EXPECT_CALL(mock_input_handler_, + GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) + .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -674,8 +677,9 @@ TEST_P(InputHandlerProxyTest, GesturePinchWithWheelHandler) { VERIFY_AND_RESET_MOCKS(); gesture_.type = WebInputEvent::GesturePinchBegin; - EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlers()) - .WillOnce(testing::Return(true)); + EXPECT_CALL(mock_input_handler_, + GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) + .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -723,8 +727,9 @@ TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { VERIFY_AND_RESET_MOCKS(); gesture_.type = WebInputEvent::GesturePinchBegin; - EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlers()) - .WillOnce(testing::Return(false)); + EXPECT_CALL(mock_input_handler_, + GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) + .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); |