From 51f6c2793adab2d864b3d2b360000ef8db1d3e92 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Dec 2018 16:19:40 +0100 Subject: BASELINE: Update Chromium to 71.0.3578.93 Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d Reviewed-by: Alexandru Croitor --- chromium/ui/aura/BUILD.gn | 5 + chromium/ui/aura/client/aura_constants.cc | 6 +- chromium/ui/aura/client/aura_constants.h | 14 +- chromium/ui/aura/env.cc | 28 +-- chromium/ui/aura/env.h | 7 + chromium/ui/aura/event_injector.cc | 21 +- .../aura/gestures/gesture_recognizer_unittest.cc | 3 +- .../aura/hit_test_data_provider_aura_unittest.cc | 23 ++- chromium/ui/aura/local/window_port_local.cc | 15 +- chromium/ui/aura/mus/client_surface_embedder.cc | 14 ++ chromium/ui/aura/mus/client_surface_embedder.h | 5 + chromium/ui/aura/mus/embed_root.cc | 1 + chromium/ui/aura/mus/gesture_synchronizer.cc | 55 ++++++ chromium/ui/aura/mus/gesture_synchronizer.h | 45 +++++ .../ui/aura/mus/gesture_synchronizer_unittest.cc | 90 +++++++++ chromium/ui/aura/mus/input_method_mus.cc | 45 +++-- chromium/ui/aura/mus/input_method_mus.h | 9 +- chromium/ui/aura/mus/input_method_mus_unittest.cc | 94 +++++++-- chromium/ui/aura/mus/mus_mouse_location_updater.cc | 24 +-- chromium/ui/aura/mus/mus_types.h | 10 +- .../ui/aura/mus/os_exchange_data_provider_mus.cc | 3 +- chromium/ui/aura/mus/property_converter.cc | 109 ++++++++++- chromium/ui/aura/mus/property_converter.h | 20 ++ .../ui/aura/mus/property_converter_unittest.cc | 91 +++++++++ chromium/ui/aura/mus/text_input_client_impl.cc | 5 +- chromium/ui/aura/mus/window_mus.h | 2 - chromium/ui/aura/mus/window_port_mus.cc | 163 +++++++++++----- chromium/ui/aura/mus/window_port_mus.h | 28 ++- chromium/ui/aura/mus/window_port_mus_unittest.cc | 62 ++++-- chromium/ui/aura/mus/window_tree_client.cc | 192 +++++++------------ chromium/ui/aura/mus/window_tree_client.h | 41 ++-- .../ui/aura/mus/window_tree_client_unittest.cc | 213 +++++++-------------- chromium/ui/aura/mus/window_tree_host_mus.cc | 4 - chromium/ui/aura/mus/window_tree_host_mus.h | 3 - .../ui/aura/mus/window_tree_host_mus_delegate.h | 5 - .../ui/aura/mus/window_tree_host_mus_unittest.cc | 26 --- chromium/ui/aura/screen_ozone.h | 2 + chromium/ui/aura/test/ui_controls_factory_ozone.cc | 64 ++++--- chromium/ui/aura/window.cc | 67 +++++-- chromium/ui/aura/window.h | 15 +- chromium/ui/aura/window_delegate.h | 8 - chromium/ui/aura/window_event_dispatcher.cc | 16 +- chromium/ui/aura/window_event_dispatcher.h | 2 + .../ui/aura/window_event_dispatcher_unittest.cc | 93 ++++++++- chromium/ui/aura/window_occlusion_tracker.cc | 59 +++--- chromium/ui/aura/window_occlusion_tracker.h | 35 ++-- .../ui/aura/window_occlusion_tracker_unittest.cc | 35 ++-- chromium/ui/aura/window_port.cc | 2 + chromium/ui/aura/window_port.h | 24 +++ chromium/ui/aura/window_port_for_shutdown.cc | 3 +- chromium/ui/aura/window_targeter.cc | 57 +++++- chromium/ui/aura/window_targeter.h | 22 ++- chromium/ui/aura/window_targeter_unittest.cc | 31 +++ chromium/ui/aura/window_tree_host.cc | 13 +- chromium/ui/aura/window_tree_host.h | 19 +- chromium/ui/aura/window_tree_host_platform.cc | 23 ++- chromium/ui/aura/window_tree_host_platform.h | 3 + chromium/ui/aura/window_tree_host_unittest.cc | 41 ++++ chromium/ui/aura/window_unittest.cc | 6 +- 59 files changed, 1433 insertions(+), 688 deletions(-) create mode 100644 chromium/ui/aura/mus/gesture_synchronizer.cc create mode 100644 chromium/ui/aura/mus/gesture_synchronizer.h create mode 100644 chromium/ui/aura/mus/gesture_synchronizer_unittest.cc (limited to 'chromium/ui/aura') diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn index c97d5dda9cf..cba785ad544 100644 --- a/chromium/ui/aura/BUILD.gn +++ b/chromium/ui/aura/BUILD.gn @@ -47,6 +47,7 @@ jumbo_component("aura") { "mus/focus_synchronizer.h", "mus/focus_synchronizer_delegate.h", "mus/focus_synchronizer_observer.h", + "mus/gesture_synchronizer.h", "mus/in_flight_change.h", "mus/input_method_mus.h", "mus/input_method_mus_delegate.h", @@ -118,6 +119,7 @@ jumbo_component("aura") { "mus/drag_drop_controller_mus.cc", "mus/embed_root.cc", "mus/focus_synchronizer.cc", + "mus/gesture_synchronizer.cc", "mus/in_flight_change.cc", "mus/input_method_mus.cc", "mus/mus_context_factory.cc", @@ -250,6 +252,8 @@ jumbo_static_library("test_support") { "test/mus/test_window_tree_client_delegate.h", "test/mus/test_window_tree_client_setup.cc", "test/mus/test_window_tree_client_setup.h", + "test/mus/window_port_mus_test_helper.cc", + "test/mus/window_port_mus_test_helper.h", "test/mus/window_tree_client_private.cc", "test/mus/window_tree_client_private.h", "test/test_cursor_client.cc", @@ -370,6 +374,7 @@ test("aura_unittests") { "mouse_location_manager_unittest.cc", "mus/drag_drop_controller_mus_unittest.cc", "mus/focus_synchronizer_unittest.cc", + "mus/gesture_synchronizer_unittest.cc", "mus/input_method_mus_unittest.cc", "mus/os_exchange_data_provider_mus_unittest.cc", "mus/property_converter_unittest.cc", diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc index c0b3bf9c200..1ed7c6e50d9 100644 --- a/chromium/ui/aura/client/aura_constants.cc +++ b/chromium/ui/aura/client/aura_constants.cc @@ -24,8 +24,6 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, void*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, SkColor) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t) -DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, - aura::client::WindowEmbedType) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*) DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*) @@ -54,9 +52,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kImmersiveFullscreenKey, false); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kMirroringEnabledKey, false); -DEFINE_UI_CLASS_PROPERTY_KEY(WindowEmbedType, - kEmbedType, - WindowEmbedType::NONE); DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr); @@ -68,6 +63,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY( DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kResizeBehaviorKey, ws::mojom::kResizeBehaviorCanResize); +DEFINE_UI_CLASS_PROPERTY_KEY(int, kResizeHandleInset, 0); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY( ui::WindowShowState, kShowStateKey, ui::SHOW_STATE_DEFAULT); diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h index a184412827a..65dc33a5477 100644 --- a/chromium/ui/aura/client/aura_constants.h +++ b/chromium/ui/aura/client/aura_constants.h @@ -23,11 +23,6 @@ namespace aura { namespace client { class FocusClient; -enum class WindowEmbedType { - NONE, - EMBED_IN_OWNER, -}; - // Alphabetical sort. // A property key to store whether accessibility focus falls back to widget or @@ -124,6 +119,12 @@ AURA_EXPORT extern const WindowProperty* const // ws::mojom::kResizeBehavior values. AURA_EXPORT extern const WindowProperty* const kResizeBehaviorKey; +// Reserves a number of dip around the window (i.e. inset from its exterior +// border) for event routing back to the top level window. This is used for +// routing events to toplevel window resize handles. It should only be respected +// for restored windows (maximized and fullscreen can't be drag-resized). +AURA_EXPORT extern const WindowProperty* const kResizeHandleInset; + // A property key to store the restore bounds in screen coordinates for a // window. AURA_EXPORT extern const WindowProperty* const kRestoreBoundsKey; @@ -149,9 +150,6 @@ AURA_EXPORT extern const WindowProperty* const kTopViewInset; // A property key to store the window icon, typically 16x16 for title bars. AURA_EXPORT extern const WindowProperty* const kWindowIconKey; -// Indicates the type of embedding within the given window. -AURA_EXPORT extern const WindowProperty* const kEmbedType; - // The corner radius of a window in DIPs. Currently only used for shadows. // Default is -1, meaning "unspecified". 0 Ensures corners are square. AURA_EXPORT extern const WindowProperty* const kWindowCornerRadiusKey; diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc index 07ff6f5bf18..bbd91404c0f 100644 --- a/chromium/ui/aura/env.cc +++ b/chromium/ui/aura/env.cc @@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" +#include "base/memory/ptr_util.h" #include "services/ws/public/mojom/window_tree.mojom.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env_input_state_controller.h" @@ -20,6 +21,7 @@ #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher_observer.h" +#include "ui/aura/window_occlusion_tracker.h" #include "ui/aura/window_port_for_shutdown.h" #include "ui/base/ui_base_features.h" #include "ui/events/event_target_iterator.h" @@ -113,19 +115,8 @@ std::unique_ptr Env::CreateWindowPort(Window* window) { return std::make_unique(); DCHECK(window_tree_client_); - WindowMusType window_mus_type; - switch (window->GetProperty(aura::client::kEmbedType)) { - case aura::client::WindowEmbedType::NONE: - window_mus_type = WindowMusType::LOCAL; - break; - case aura::client::WindowEmbedType::EMBED_IN_OWNER: - window_mus_type = WindowMusType::EMBED_IN_OWNER; - break; - default: - NOTREACHED(); - } - // Use LOCAL as all other cases are created by WindowTreeClient explicitly. - return std::make_unique(window_tree_client_, window_mus_type); + return std::make_unique(window_tree_client_, + WindowMusType::LOCAL); } void Env::AddObserver(EnvObserver* observer) { @@ -196,6 +187,17 @@ void Env::ScheduleEmbed( window_tree_client_->ScheduleEmbed(std::move(client), std::move(callback)); } +WindowOcclusionTracker* Env::GetWindowOcclusionTracker() { + // TODO(https://crbug.com/867150): DCHECK to ensure LOCAL aura after mus + // code path is wired up. + if (!window_occlusion_tracker_) { + // Use base::WrapUnique + new because of the constructor is private. + window_occlusion_tracker_ = base::WrapUnique(new WindowOcclusionTracker()); + } + + return window_occlusion_tracker_.get(); +} + //////////////////////////////////////////////////////////////////////////////// // Env, private: diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h index f8fb629389f..3738281bedd 100644 --- a/chromium/ui/aura/env.h +++ b/chromium/ui/aura/env.h @@ -59,6 +59,7 @@ class MouseLocationManager; class MusMouseLocationUpdater; class Window; class WindowEventDispatcherObserver; +class WindowOcclusionTracker; class WindowPort; class WindowTreeClient; class WindowTreeHost; @@ -191,6 +192,9 @@ class AURA_EXPORT Env : public ui::EventTarget, mojo::InterfacePtr client, base::OnceCallback callback); + // Get WindowOcclusionTracker instance. Create it if it is not yet created. + WindowOcclusionTracker* GetWindowOcclusionTracker(); + private: friend class test::EnvTestHelper; friend class test::EnvWindowTreeClientSetter; @@ -285,6 +289,9 @@ class AURA_EXPORT Env : public ui::EventTarget, // Only created if CreateMouseLocationManager() was called. std::unique_ptr mouse_location_manager_; + // Lazily created for LOCAL aura. + std::unique_ptr window_occlusion_tracker_; + DISALLOW_COPY_AND_ASSIGN(Env); }; diff --git a/chromium/ui/aura/event_injector.cc b/chromium/ui/aura/event_injector.cc index fd2a7423c05..f67d1fe5721 100644 --- a/chromium/ui/aura/event_injector.cc +++ b/chromium/ui/aura/event_injector.cc @@ -13,24 +13,6 @@ #include "ui/events/event.h" #include "ui/events/event_sink.h" -namespace { -std::unique_ptr MapEvent(const ui::Event& event) { - if (event.IsScrollEvent()) { - return std::make_unique( - ui::MouseWheelEvent(*event.AsScrollEvent())); - } - - if (event.IsMouseEvent()) - return std::make_unique(*event.AsMouseEvent()); - - if (event.IsTouchEvent()) - return std::make_unique(*event.AsTouchEvent()); - - return ui::Event::Clone(event); -} - -} // namespace - namespace aura { EventInjector::EventInjector() {} @@ -60,7 +42,8 @@ ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host, env->window_tree_client_->connector()->BindInterface( ws::mojom::kServiceName, &event_injector_); } - event_injector_->InjectEventNoAck(host->GetDisplayId(), MapEvent(*event)); + event_injector_->InjectEventNoAck(host->GetDisplayId(), + ui::Event::Clone(*event)); return ui::EventDispatchDetails(); } diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc index 86b08db290d..ee72e003826 100644 --- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -4705,8 +4705,7 @@ TEST_F(GestureRecognizerTest, TransferEventsToRoutesAckCorrectly) { // Transfer event sequence from previous window to the new window. aura::Env::GetInstance()->gesture_recognizer()->TransferEventsTo( - window_1.get(), window_2.get(), - ui::GestureRecognizer::ShouldCancelTouches::DontCancel); + window_1.get(), window_2.get(), ui::TransferTouchesBehavior::kDontCancel); delegate_1->Reset(); delegate_1->ReceivedAck(); diff --git a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc index b120625ed1a..79f73481cad 100644 --- a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc +++ b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc @@ -8,6 +8,7 @@ #include "components/viz/common/hit_test/hit_test_region_list.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/mus/window_port_mus_test_helper.h" #include "ui/aura/window.h" #include "ui/aura/window_targeter.h" #include "ui/gfx/geometry/rect.h" @@ -28,15 +29,15 @@ namespace { // | ---------- | // | hit hit | // ---------------------- -class TestHoleWindowTargeter : public aura::WindowTargeter { +class TestHoleWindowTargeter : public WindowTargeter { public: TestHoleWindowTargeter() = default; ~TestHoleWindowTargeter() override {} private: - // aura::WindowTargeter: - std::unique_ptr GetExtraHitTestShapeRects( - aura::Window* target) const override { + // WindowTargeter: + std::unique_ptr GetExtraHitTestShapeRects( + Window* target) const override { gfx::Rect bounds = target->bounds(); int x0 = 0; int x1 = bounds.width() / 3; @@ -46,7 +47,7 @@ class TestHoleWindowTargeter : public aura::WindowTargeter { int y1 = bounds.height() / 3; int y2 = bounds.height() - bounds.height() / 3; int y3 = bounds.height(); - auto shape_rects = std::make_unique(); + auto shape_rects = std::make_unique(); shape_rects->emplace_back(x0, y0, bounds.width(), y1 - y0); shape_rects->emplace_back(x0, y1, x1 - x0, y2 - y1); shape_rects->emplace_back(x2, y1, x3 - x2, y2 - y1); @@ -73,23 +74,17 @@ class HitTestDataProviderAuraTest : public test::AuraTestBaseMus { test::AuraTestBaseMus::SetUp(); root_ = std::make_unique(nullptr); - root_->SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); root_->Init(ui::LAYER_NOT_DRAWN); root_->SetEventTargeter(std::make_unique()); root_->SetBounds(gfx::Rect(0, 0, 300, 200)); root_->Show(); window2_ = new Window(nullptr); - window2_->SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); window2_->Init(ui::LAYER_TEXTURED); window2_->SetBounds(gfx::Rect(20, 30, 40, 60)); window2_->Show(); window3_ = new Window(nullptr); - window3_->SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); window3_->Init(ui::LAYER_TEXTURED); window3_->SetEventTargeter(std::make_unique()); window3_->SetBounds(gfx::Rect(50, 60, 100, 40)); @@ -175,10 +170,14 @@ TEST_F(HitTestDataProviderAuraTest, Stacking) { TEST_F(HitTestDataProviderAuraTest, CustomTargeter) { constexpr int kMouseInset = -5; constexpr int kTouchInset = -10; - auto targeter = std::make_unique(); + auto targeter = std::make_unique(); targeter->SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset)); window3()->SetEventTargeter(std::move(targeter)); + targeter = std::make_unique(); + targeter->SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset)); + window4()->SetEventTargeter(std::move(targeter)); + window2()->SetEmbedFrameSinkId(viz::FrameSinkId(1, 2)); const base::Optional hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); diff --git a/chromium/ui/aura/local/window_port_local.cc b/chromium/ui/aura/local/window_port_local.cc index 56c7db037cc..454a3dea5b2 100644 --- a/chromium/ui/aura/local/window_port_local.cc +++ b/chromium/ui/aura/local/window_port_local.cc @@ -9,6 +9,7 @@ #include "components/viz/client/local_surface_id_provider.h" #include "components/viz/common/features.h" #include "components/viz/host/host_frame_sink_manager.h" +#include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" #include "ui/aura/hit_test_data_provider_aura.h" @@ -19,7 +20,9 @@ #include "ui/display/screen.h" namespace aura { + namespace { +static const char* kExo = "Exo"; class ScopedCursorHider { public: @@ -63,7 +66,9 @@ class ScopedCursorHider { } // namespace WindowPortLocal::WindowPortLocal(Window* window) - : window_(window), weak_factory_(this) {} + : WindowPort(WindowPort::Type::kLocal), + window_(window), + weak_factory_(this) {} WindowPortLocal::~WindowPortLocal() { if (frame_sink_id_.is_valid()) { @@ -156,10 +161,16 @@ WindowPortLocal::CreateLayerTreeFrameSink() { params.pipes.compositor_frame_sink_info = std::move(sink_info); params.pipes.client_request = std::move(client_request); params.enable_surface_synchronization = true; + params.client_name = kExo; if (features::IsVizHitTestingDrawQuadEnabled()) { + bool root_accepts_events = + (window_->event_targeting_policy() == + ws::mojom::EventTargetingPolicy::TARGET_ONLY) || + (window_->event_targeting_policy() == + ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); params.hit_test_data_provider = std::make_unique( - true /* should_ask_for_child_region */); + true /* should_ask_for_child_region */, root_accepts_events); } else { params.hit_test_data_provider = std::make_unique(window_); diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc index 21913636c50..340eef15b1f 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.cc +++ b/chromium/ui/aura/mus/client_surface_embedder.cc @@ -43,6 +43,10 @@ void ClientSurfaceEmbedder::SetPrimarySurfaceId( false /* stretch_content_to_fill_bounds */); } +bool ClientSurfaceEmbedder::HasPrimarySurfaceId() const { + return surface_layer_owner_->layer()->GetPrimarySurfaceId() != nullptr; +} + void ClientSurfaceEmbedder::SetFallbackSurfaceInfo( const viz::SurfaceInfo& surface_info) { fallback_surface_info_ = surface_info; @@ -50,6 +54,16 @@ void ClientSurfaceEmbedder::SetFallbackSurfaceInfo( UpdateSizeAndGutters(); } +void ClientSurfaceEmbedder::SetClientAreaInsets( + const gfx::Insets& client_area_insets) { + if (client_area_insets_ == client_area_insets) + return; + + client_area_insets_ = client_area_insets; + if (inject_gutter_) + UpdateSizeAndGutters(); +} + void ClientSurfaceEmbedder::UpdateSizeAndGutters() { surface_layer_owner_->layer()->SetBounds(gfx::Rect(window_->bounds().size())); if (!inject_gutter_) diff --git a/chromium/ui/aura/mus/client_surface_embedder.h b/chromium/ui/aura/mus/client_surface_embedder.h index cec86d00c37..bcf1ce1bace 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.h +++ b/chromium/ui/aura/mus/client_surface_embedder.h @@ -37,10 +37,15 @@ class AURA_EXPORT ClientSurfaceEmbedder { // on the provided |surface_id|. void SetPrimarySurfaceId(const viz::SurfaceId& surface_id); + bool HasPrimarySurfaceId() const; + // Sets the fallback SurfaceInfo of the surface layer. The clip layer is not // updated. void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info); + void SetClientAreaInsets(const gfx::Insets& client_area_insets); + const gfx::Insets& client_area_insets() const { return client_area_insets_; } + // Update the surface layer size and the right and bottom gutter layers for // the current window size. void UpdateSizeAndGutters(); diff --git a/chromium/ui/aura/mus/embed_root.cc b/chromium/ui/aura/mus/embed_root.cc index 372988eaa30..32fa6b55747 100644 --- a/chromium/ui/aura/mus/embed_root.cc +++ b/chromium/ui/aura/mus/embed_root.cc @@ -123,6 +123,7 @@ void EmbedRoot::OnEmbed(std::unique_ptr window_tree_host) { focus_client_ = std::make_unique(window_tree_host->window()); window_tree_host_ = std::move(window_tree_host); + window_tree_host_->Show(); delegate_->OnEmbed(window()); } diff --git a/chromium/ui/aura/mus/gesture_synchronizer.cc b/chromium/ui/aura/mus/gesture_synchronizer.cc new file mode 100644 index 00000000000..ce216f54f35 --- /dev/null +++ b/chromium/ui/aura/mus/gesture_synchronizer.cc @@ -0,0 +1,55 @@ +// Copyright 2018 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. + +#include "ui/aura/mus/gesture_synchronizer.h" + +#include "services/ws/public/mojom/window_tree.mojom.h" +#include "ui/aura/env.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/window.h" +#include "ui/events/gestures/gesture_recognizer.h" + +namespace aura { + +GestureSynchronizer::GestureSynchronizer(ws::mojom::WindowTree* window_tree) + : window_tree_(window_tree) { + Env::GetInstance()->gesture_recognizer()->AddObserver(this); +} + +GestureSynchronizer::~GestureSynchronizer() { + Env::GetInstance()->gesture_recognizer()->RemoveObserver(this); +} + +void GestureSynchronizer::OnActiveTouchesCanceledExcept( + ui::GestureConsumer* not_cancelled) { + ws::Id not_cancelled_window_id = kInvalidServerId; + if (not_cancelled) { + WindowMus* not_cancelled_window = + WindowMus::Get(static_cast(not_cancelled)); + not_cancelled_window_id = not_cancelled_window->server_id(); + } + window_tree_->CancelActiveTouchesExcept(not_cancelled_window_id); +} + +void GestureSynchronizer::OnEventsTransferred( + ui::GestureConsumer* current_consumer, + ui::GestureConsumer* new_consumer, + ui::TransferTouchesBehavior transfer_touches_behavior) { + WindowMus* current_window = + WindowMus::Get(static_cast(current_consumer)); + WindowMus* new_window = WindowMus::Get(static_cast(new_consumer)); + DCHECK(current_window); + DCHECK(new_window); + window_tree_->TransferGestureEventsTo( + current_window->server_id(), new_window->server_id(), + transfer_touches_behavior == ui::TransferTouchesBehavior::kCancel); +} + +void GestureSynchronizer::OnActiveTouchesCanceled( + ui::GestureConsumer* consumer) { + WindowMus* window = WindowMus::Get(static_cast(consumer)); + window_tree_->CancelActiveTouches(window->server_id()); +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/gesture_synchronizer.h b/chromium/ui/aura/mus/gesture_synchronizer.h new file mode 100644 index 00000000000..66ab563d33f --- /dev/null +++ b/chromium/ui/aura/mus/gesture_synchronizer.h @@ -0,0 +1,45 @@ +// Copyright 2018 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 UI_AURA_MUS_GESTURE_SYNCHRONIZER_H_ +#define UI_AURA_MUS_GESTURE_SYNCHRONIZER_H_ + +#include "base/macros.h" +#include "ui/events/gestures/gesture_recognizer_observer.h" + +namespace ws { +namespace mojom { + +class WindowTree; + +} // namespace mojom +} // namespace ws + +namespace aura { + +// GestureSynchronizer is responsible for keeping GestureRecognizer's state +// synchronized between aura and the mus server. +class GestureSynchronizer : public ui::GestureRecognizerObserver { + public: + explicit GestureSynchronizer(ws::mojom::WindowTree* window_tree); + ~GestureSynchronizer() override; + + private: + // ui::GestureRecognizerObserver: + void OnActiveTouchesCanceledExcept( + ui::GestureConsumer* not_cancelled) override; + void OnEventsTransferred( + ui::GestureConsumer* current_consumer, + ui::GestureConsumer* new_consumer, + ui::TransferTouchesBehavior transfer_touches_behavior) override; + void OnActiveTouchesCanceled(ui::GestureConsumer* consumer) override; + + ws::mojom::WindowTree* window_tree_; + + DISALLOW_COPY_AND_ASSIGN(GestureSynchronizer); +}; + +} // namespace aura + +#endif // UI_AURA_MUS_GESTURE_SYNCHRONIZER_H_ diff --git a/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc b/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc new file mode 100644 index 00000000000..cd1e7e0dee8 --- /dev/null +++ b/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc @@ -0,0 +1,90 @@ +// Copyright 2018 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. + +#include "ui/aura/mus/gesture_synchronizer.h" + +#include + +#include "ui/aura/env.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/mus/window_tree_host_mus.h" +#include "ui/aura/mus/window_tree_host_mus_init_params.h" +#include "ui/aura/test/aura_mus_test_base.h" +#include "ui/aura/test/mus/test_window_tree.h" + +namespace aura { + +class GestureSynchronizerTest : public test::AuraMusClientTestBase { + public: + GestureSynchronizerTest() = default; + ~GestureSynchronizerTest() override = default; + + void SetUp() override { + test::AuraMusClientTestBase::SetUp(); + + window_tree_host_ = std::make_unique( + CreateInitParamsForTopLevel(window_tree_client_impl())); + window_tree_host_->InitHost(); + window_tree_host_->Show(); + } + + protected: + ui::GestureRecognizer* gesture_recognizer() { + return Env::GetInstance()->gesture_recognizer(); + } + + std::unique_ptr NewWindow() { + auto window = std::make_unique(nullptr); + window->Init(ui::LAYER_NOT_DRAWN); + window_tree_host_->window()->AddChild(window.get()); + window->Show(); + return window; + } + + private: + std::unique_ptr window_tree_host_; + + DISALLOW_COPY_AND_ASSIGN(GestureSynchronizerTest); +}; + +TEST_F(GestureSynchronizerTest, CancelActiveTouchesExcept) { + std::unique_ptr window = NewWindow(); + gesture_recognizer()->CancelActiveTouchesExcept(window.get()); + EXPECT_EQ(window_tree()->last_not_cancelled_window_id(), + WindowMus::Get(window.get())->server_id()); +} + +TEST_F(GestureSynchronizerTest, CancelActiveTouchesExceptForNullptr) { + gesture_recognizer()->CancelActiveTouchesExcept(nullptr); + EXPECT_EQ(window_tree()->last_not_cancelled_window_id(), kInvalidServerId); +} + +TEST_F(GestureSynchronizerTest, CancelActiveTouches) { + std::unique_ptr window = NewWindow(); + gesture_recognizer()->CancelActiveTouches(window.get()); + EXPECT_EQ(window_tree()->last_cancelled_window_id(), + WindowMus::Get(window.get())->server_id()); +} + +TEST_F(GestureSynchronizerTest, TransferGestureEventsTo) { + std::unique_ptr window1 = NewWindow(); + std::unique_ptr window2 = NewWindow(); + gesture_recognizer()->TransferEventsTo(window1.get(), window2.get(), + ui::TransferTouchesBehavior::kCancel); + EXPECT_EQ(window_tree()->last_transfer_current(), + WindowMus::Get(window1.get())->server_id()); + EXPECT_EQ(window_tree()->last_transfer_new(), + WindowMus::Get(window2.get())->server_id()); + EXPECT_TRUE(window_tree()->last_transfer_should_cancel()); + + gesture_recognizer()->TransferEventsTo( + window2.get(), window1.get(), ui::TransferTouchesBehavior::kDontCancel); + EXPECT_EQ(window_tree()->last_transfer_current(), + WindowMus::Get(window2.get())->server_id()); + EXPECT_EQ(window_tree()->last_transfer_new(), + WindowMus::Get(window1.get())->server_id()); + EXPECT_FALSE(window_tree()->last_transfer_should_cancel()); +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/input_method_mus.cc b/chromium/ui/aura/mus/input_method_mus.cc index f840416fe0f..cf1328a6e05 100644 --- a/chromium/ui/aura/mus/input_method_mus.cc +++ b/chromium/ui/aura/mus/input_method_mus.cc @@ -19,6 +19,21 @@ using ws::mojom::EventResult; namespace aura { +namespace { + +void CallEventResultCallback(InputMethodMus::EventResultCallback ack_callback, + bool handled) { + // |ack_callback| can be null if the standard form of DispatchKeyEvent() is + // called instead of the version which provides a callback. In mus+ash we + // use the version with callback, but some unittests use the standard form. + if (!ack_callback) + return; + + std::move(ack_callback) + .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED); +} + +} // namespace //////////////////////////////////////////////////////////////////////////////// // InputMethodMus, public: @@ -34,7 +49,7 @@ InputMethodMus::~InputMethodMus() { // Mus won't dispatch the next key event until the existing one is acked. We // may have KeyEvents sent to IME and awaiting the result, we need to ack // them otherwise mus won't process the next event until it times out. - AckPendingCallbacksUnhandled(); + AckPendingCallbacks(); } void InputMethodMus::Init(service_manager::Connector* connector) { @@ -50,13 +65,9 @@ ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent( // If no text input client, do nothing. if (!GetTextInputClient()) { - ui::EventDispatchDetails dispatch_details = DispatchKeyEventPostIME(event); - if (ack_callback) { - std::move(ack_callback) - .Run(event->handled() ? EventResult::HANDLED - : EventResult::UNHANDLED); - } - return dispatch_details; + return DispatchKeyEventPostIME( + event, + base::BindOnce(&CallEventResultCallback, std::move(ack_callback))); } return SendKeyEventToInputMethod(*event, std::move(ack_callback)); @@ -136,7 +147,8 @@ ui::EventDispatchDetails InputMethodMus::SendKeyEventToInputMethod( // This code path is hit in tests that don't connect to the server. DCHECK(!ack_callback); std::unique_ptr event_clone = ui::Event::Clone(event); - return DispatchKeyEventPostIME(event_clone->AsKeyEvent()); + return DispatchKeyEventPostIME(event_clone->AsKeyEvent(), + base::NullCallback()); } // IME driver will notify us whether it handled the event or not by calling @@ -160,7 +172,7 @@ void InputMethodMus::OnDidChangeFocusedClient( // We are about to close the pipe with pending callbacks. Closing the pipe // results in none of the callbacks being run. We have to run the callbacks // else mus won't process the next event immediately. - AckPendingCallbacksUnhandled(); + AckPendingCallbacks(); if (!focused) { input_method_ = nullptr; @@ -200,10 +212,10 @@ void InputMethodMus::UpdateTextInputType() { } } -void InputMethodMus::AckPendingCallbacksUnhandled() { +void InputMethodMus::AckPendingCallbacks() { for (auto& callback : pending_callbacks_) { if (callback) - std::move(callback).Run(EventResult::UNHANDLED); + std::move(callback).Run(EventResult::HANDLED); } pending_callbacks_.clear(); } @@ -216,14 +228,7 @@ void InputMethodMus::ProcessKeyEventCallback( DCHECK(!pending_callbacks_.empty()); EventResultCallback ack_callback = std::move(pending_callbacks_.front()); pending_callbacks_.pop_front(); - - // |ack_callback| can be null if the standard form of DispatchKeyEvent() is - // called instead of the version which provides a callback. In mus+ash we - // use the version with callback, but some unittests use the standard form. - if (ack_callback) { - std::move(ack_callback) - .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED); - } + CallEventResultCallback(std::move(ack_callback), handled); } } // namespace aura diff --git a/chromium/ui/aura/mus/input_method_mus.h b/chromium/ui/aura/mus/input_method_mus.h index d47ed317001..d54bf4357cc 100644 --- a/chromium/ui/aura/mus/input_method_mus.h +++ b/chromium/ui/aura/mus/input_method_mus.h @@ -64,10 +64,13 @@ class AURA_EXPORT InputMethodMus : public ui::InputMethodBase { void UpdateTextInputType(); - // Runs all pending callbacks with UNHANDLED. This is called during shutdown, + // Runs all pending callbacks with HANDLED. This is called during shutdown, // or any time |input_method_ptr_| is reset to ensure we don't leave mus - // waiting for an ack. - void AckPendingCallbacksUnhandled(); + // waiting for an ack. We ack HANDLED because the input method can be reset + // due to focus changes in response to shortcuts (e.g. Ctrl-T opening a tab) + // and we don't want the window manager to try to process the accelerators. + // https://crbug.com/874098 + void AckPendingCallbacks(); // Called when the server responds to our request to process an event. void ProcessKeyEventCallback( diff --git a/chromium/ui/aura/mus/input_method_mus_unittest.cc b/chromium/ui/aura/mus/input_method_mus_unittest.cc index eaa79232a93..b70f26395ba 100644 --- a/chromium/ui/aura/mus/input_method_mus_unittest.cc +++ b/chromium/ui/aura/mus/input_method_mus_unittest.cc @@ -21,12 +21,22 @@ class TestInputMethodDelegate : public ui::internal::InputMethodDelegate { TestInputMethodDelegate() {} ~TestInputMethodDelegate() override {} + bool was_dispatch_key_event_post_ime_called() const { + return was_dispatch_key_event_post_ime_called_; + } + // ui::internal::InputMethodDelegate: - ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override { + ui::EventDispatchDetails DispatchKeyEventPostIME( + ui::KeyEvent* key, + base::OnceCallback ack_callback) override { + was_dispatch_key_event_post_ime_called_ = true; + CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback)); return ui::EventDispatchDetails(); } private: + bool was_dispatch_key_event_post_ime_called_ = false; + DISALLOW_COPY_AND_ASSIGN(TestInputMethodDelegate); }; @@ -94,23 +104,28 @@ using InputMethodMusTest = test::AuraTestBaseMus; namespace { // Used in closure supplied to processing the event. -void RunFunctionWithEventResult(bool* was_run, ws::mojom::EventResult result) { +void RunFunctionWithEventResult(bool* was_run, + ws::mojom::EventResult* result_out, + ws::mojom::EventResult result) { *was_run = true; + *result_out = result; } } // namespace TEST_F(InputMethodMusTest, PendingCallbackRunFromDestruction) { bool was_event_result_callback_run = false; - // Create an InputMethodMus and foward an event to it. + ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED; + // Create an InputMethodMus and forward an event to it. { TestInputMethodDelegate input_method_delegate; InputMethodMus input_method_mus(&input_method_delegate, nullptr); TestInputMethod test_input_method; InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); - EventResultCallback callback = base::BindOnce( - &RunFunctionWithEventResult, &was_event_result_callback_run); + EventResultCallback callback = + base::BindOnce(&RunFunctionWithEventResult, + &was_event_result_callback_run, &event_result); ui::EventDispatchDetails details = InputMethodMusTestApi::CallSendKeyEventToInputMethod( @@ -136,14 +151,16 @@ TEST_F(InputMethodMusTest, PendingCallbackRunFromDestruction) { TEST_F(InputMethodMusTest, PendingCallbackRunFromOnDidChangeFocusedClient) { bool was_event_result_callback_run = false; + ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED; ui::DummyTextInputClient test_input_client; - // Create an InputMethodMus and foward an event to it. + // Create an InputMethodMus and forward an event to it. TestInputMethodDelegate input_method_delegate; InputMethodMus input_method_mus(&input_method_delegate, nullptr); TestInputMethod test_input_method; InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); - EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult, - &was_event_result_callback_run); + EventResultCallback callback = + base::BindOnce(&RunFunctionWithEventResult, + &was_event_result_callback_run, &event_result); ui::EventDispatchDetails details = InputMethodMusTestApi::CallSendKeyEventToInputMethod( &input_method_mus, @@ -159,18 +176,21 @@ TEST_F(InputMethodMusTest, PendingCallbackRunFromOnDidChangeFocusedClient) { &input_method_mus, nullptr, &test_input_client); // Changing the focused client should trigger running the callback. EXPECT_TRUE(was_event_result_callback_run); + EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result); } TEST_F(InputMethodMusTest, PendingCallbackRunFromOnDidChangeFocusedClientToNull) { bool was_event_result_callback_run = false; - // Create an InputMethodMus and foward an event to it. + ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED; + // Create an InputMethodMus and forward an event to it. TestInputMethodDelegate input_method_delegate; InputMethodMus input_method_mus(&input_method_delegate, nullptr); TestInputMethod test_input_method; InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); - EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult, - &was_event_result_callback_run); + EventResultCallback callback = + base::BindOnce(&RunFunctionWithEventResult, + &was_event_result_callback_run, &event_result); ui::EventDispatchDetails details = InputMethodMusTestApi::CallSendKeyEventToInputMethod( &input_method_mus, @@ -186,6 +206,7 @@ TEST_F(InputMethodMusTest, nullptr, nullptr); // Changing the focused client should trigger running the callback. EXPECT_TRUE(was_event_result_callback_run); + EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result); } // See description of ChangeTextInputTypeWhileProcessingCallback for details. @@ -205,9 +226,12 @@ class TestInputMethodDelegate2 : public ui::internal::InputMethodDelegate { } // ui::internal::InputMethodDelegate: - ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override { + ui::EventDispatchDetails DispatchKeyEventPostIME( + ui::KeyEvent* key, + base::OnceCallback ack_callback) override { was_dispatch_key_event_post_ime_called_ = true; input_method_mus_->SetFocusedTextInputClient(text_input_client_); + CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback)); return ui::EventDispatchDetails(); } @@ -224,16 +248,18 @@ class TestInputMethodDelegate2 : public ui::internal::InputMethodDelegate { // scenario and the callback is correctly called. TEST_F(InputMethodMusTest, ChangeTextInputTypeWhileProcessingCallback) { bool was_event_result_callback_run = false; + ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED; ui::DummyTextInputClient test_input_client; - // Create an InputMethodMus and foward an event to it. + // Create an InputMethodMus and forward an event to it. TestInputMethodDelegate2 input_method_delegate; InputMethodMus input_method_mus(&input_method_delegate, nullptr); input_method_delegate.SetInputMethodAndClient(&input_method_mus, &test_input_client); TestInputMethod test_input_method; InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); - EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult, - &was_event_result_callback_run); + EventResultCallback callback = + base::BindOnce(&RunFunctionWithEventResult, + &was_event_result_callback_run, &event_result); const ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0); ui::EventDispatchDetails details = InputMethodMusTestApi::CallSendKeyEventToInputMethod( @@ -243,10 +269,13 @@ TEST_F(InputMethodMusTest, ChangeTextInputTypeWhileProcessingCallback) { ASSERT_EQ(1u, test_input_method.process_key_event_callbacks()->size()); // Callback should not have been run yet. EXPECT_FALSE(was_event_result_callback_run); - std::move((*test_input_method.process_key_event_callbacks())[0]).Run(false); + const bool handled = true; + std::move((*test_input_method.process_key_event_callbacks())[0]).Run(handled); // Callback should have been run. EXPECT_TRUE(was_event_result_callback_run); + EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result); + EXPECT_FALSE(input_method_delegate.was_dispatch_key_event_post_ime_called()); } // Calling OnTextInputTypeChanged from unfocused client should @@ -317,4 +346,37 @@ TEST_F(InputMethodMusTest, ShowVirtualKeyboardIfEnabled) { EXPECT_TRUE(test_input_method.was_show_virtual_keyboard_if_enabled_called()); } +TEST_F(InputMethodMusTest, AckUnhandledCallsDispatchKeyEventPostUnhandled) { + bool was_event_result_callback_run = false; + ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED; + // Create an InputMethodMus and forward an event to it. + TestInputMethodDelegate input_method_delegate; + InputMethodMus input_method_mus(&input_method_delegate, nullptr); + TestInputMethod test_input_method; + InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method); + EventResultCallback callback = + base::BindOnce(&RunFunctionWithEventResult, + &was_event_result_callback_run, &event_result); + const ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0); + ignore_result(InputMethodMusTestApi::CallSendKeyEventToInputMethod( + &input_method_mus, key_event, std::move(callback))); + // The event should have been queued. + ASSERT_EQ(1u, test_input_method.process_key_event_callbacks()->size()); + // Callback should not have been run yet. + EXPECT_FALSE(was_event_result_callback_run); + const bool handled = false; + std::move((*test_input_method.process_key_event_callbacks())[0]).Run(handled); + test_input_method.process_key_event_callbacks()->clear(); + + // Callback should have been run. + EXPECT_TRUE(was_event_result_callback_run); + EXPECT_EQ(ws::mojom::EventResult::UNHANDLED, event_result); + + // DispatchKeyEventPostIME() should not have beeen called. In production + // the following calls result: + // InputMethodChromeOS -> RemoteTextInputClient -> TextInputClientImpl -> + // InputMethodMus's delegate. + EXPECT_FALSE(input_method_delegate.was_dispatch_key_event_post_ime_called()); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/mus_mouse_location_updater.cc b/chromium/ui/aura/mus/mus_mouse_location_updater.cc index 32aa588cb61..ce61eab444f 100644 --- a/chromium/ui/aura/mus/mus_mouse_location_updater.cc +++ b/chromium/ui/aura/mus/mus_mouse_location_updater.cc @@ -38,27 +38,17 @@ MusMouseLocationUpdater::~MusMouseLocationUpdater() { } void MusMouseLocationUpdater::OnEventProcessingStarted(const ui::Event& event) { - if (!IsMouseEventWithLocation(event) || - Env::GetInstance()->always_use_last_mouse_location_) { + Env* env = Env::GetInstance(); + if (!IsMouseEventWithLocation(event) || env->always_use_last_mouse_location_) return; - } is_processing_trigger_event_ = true; - gfx::Point location_in_screen = event.AsMouseEvent()->root_location(); // event.target() may not exist in some tests. - if (event.target()) { - aura::Window* root_window = - static_cast(event.target())->GetRootWindow(); - auto* screen_position_client = - aura::client::GetScreenPositionClient(root_window); - // screen_position_client may not exist in tests. - if (screen_position_client) { - screen_position_client->ConvertPointToScreen(root_window, - &location_in_screen); - } - } - Env::GetInstance()->SetLastMouseLocation(location_in_screen); - Env::GetInstance()->get_last_mouse_location_from_mus_ = false; + const gfx::Point screen_location = + event.target() ? event.target()->GetScreenLocation(*event.AsMouseEvent()) + : event.AsMouseEvent()->root_location(); + env->SetLastMouseLocation(screen_location); + env->get_last_mouse_location_from_mus_ = false; } void MusMouseLocationUpdater::OnEventProcessingFinished() { diff --git a/chromium/ui/aura/mus/mus_types.h b/chromium/ui/aura/mus/mus_types.h index 4f406261d73..3a58e55eeb9 100644 --- a/chromium/ui/aura/mus/mus_types.h +++ b/chromium/ui/aura/mus/mus_types.h @@ -20,17 +20,9 @@ enum class WindowMusType { // The window is an embed root in the embedded client. That is, the client // received this window by way of another client calling Embed(). In other // words, this is the embedded side of an embedding. - // NOTE: in the client that called Embed() the window type is LOCAL (or - // EMBED_IN_OWNER). - // TODO(sky): ensure when Embed() is called type is always set to - // EMBED_IN_OWNER, and if the embedding is removed it goes back to LOCAL. - // https://crbug.com/834487 + // NOTE: in the client that called Embed() the window type is LOCAL. EMBED, - // Embed() was called on the window by the local client. In other words, this - // is the embedder side of an embedding. - EMBED_IN_OWNER, - // The window was created by requesting a top level // (WindowTree::NewTopLevel()). TOP_LEVEL, diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc index 9e41787ea96..f8e327cd09b 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc @@ -113,8 +113,7 @@ void OSExchangeDataProviderMus::SetFilename(const base::FilePath& path) { void OSExchangeDataProviderMus::SetFilenames( const std::vector& file_names) { std::vector paths; - for (std::vector::const_iterator it = file_names.begin(); - it != file_names.end(); ++it) { + for (auto it = file_names.begin(); it != file_names.end(); ++it) { std::string url_spec = net::FilePathToFileURL(it->path).spec(); if (!url_spec.empty()) paths.push_back(url_spec); diff --git a/chromium/ui/aura/mus/property_converter.cc b/chromium/ui/aura/mus/property_converter.cc index 51cd00e1d81..0d0e345318e 100644 --- a/chromium/ui/aura/mus/property_converter.cc +++ b/chromium/ui/aura/mus/property_converter.cc @@ -4,6 +4,7 @@ #include "ui/aura/mus/property_converter.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/type_converter.h" #include "services/ws/public/cpp/property_type_converters.h" @@ -108,10 +109,58 @@ PropertyConverter::PropertyConverter() { client::kAnimationsDisabledKey, ws::mojom::WindowManager::kAnimationsDisabled_Property, CreateAcceptAnyValueCallback()); + RegisterWindowPtrProperty( + client::kChildModalParentKey, + ws::mojom::WindowManager::kChildModalParent_Property); } PropertyConverter::~PropertyConverter() {} +const void* PropertyConverter::GetPropertyKeyFromTransportName( + const std::string& transport_name) { + for (const auto& primitive_property : primitive_properties_) { + if (primitive_property.second.transport_name == transport_name) + return primitive_property.first; + } + + for (const auto& image_property : image_properties_) { + if (image_property.second == transport_name) + return image_property.first->name; + } + + for (const auto& rect_property : rect_properties_) { + if (rect_property.second == transport_name) + return rect_property.first->name; + } + + for (const auto& size_property : size_properties_) { + if (size_property.second == transport_name) + return size_property.first->name; + } + + for (const auto& string_property : string_properties_) { + if (string_property.second == transport_name) + return string_property.first->name; + } + + for (const auto& string16_property : string16_properties_) { + if (string16_property.second == transport_name) + return string16_property.first->name; + } + + for (const auto& unguessable_token_property : unguessable_token_properties_) { + if (unguessable_token_property.second == transport_name) + return unguessable_token_property.first->name; + } + + for (const auto& window_ptr_property : window_ptr_properties_) { + if (window_ptr_property.second == transport_name) + return window_ptr_property.first->name; + } + + return nullptr; +} + bool PropertyConverter::IsTransportNameRegistered( const std::string& name) const { return transport_names_.count(name) > 0; @@ -131,7 +180,7 @@ bool PropertyConverter::ConvertPropertyForTransport( const gfx::ImageSkia* value = window->GetProperty(image_key); if (value) { // TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia]. - SkBitmap bitmap = value->GetRepresentation(1.f).sk_bitmap(); + SkBitmap bitmap = value->GetRepresentation(1.f).GetBitmap(); *transport_value = std::make_unique>( mojo::ConvertTo>(bitmap)); } else { @@ -171,6 +220,14 @@ bool PropertyConverter::ConvertPropertyForTransport( return true; } + // window_ptr_properties_ aren't processed here since Window* values aren't + // transferrable. A post processing step in WindowTree and WindowTreeClient + // takes care of the conversion. + if (IsWindowPtrPropertyRegistered( + static_cast*>(key))) { + return true; + } + // Handle primitive property types generically. DCHECK_GT(primitive_properties_.count(key), 0u); PrimitiveType default_value = primitive_properties_[key].default_value; @@ -210,6 +267,10 @@ std::string PropertyConverter::GetTransportNameForPropertyKey(const void* key) { if (unguessable_token_properties_.count(unguessable_token_key) > 0) return unguessable_token_properties_[unguessable_token_key]; + auto* window_ptr_key = static_cast*>(key); + if (window_ptr_properties_.count(window_ptr_key) > 0) + return window_ptr_properties_[window_ptr_key]; + return std::string(); } @@ -307,6 +368,20 @@ void PropertyConverter::SetPropertyFromTransportValue( } } + // window_ptr_properties_ aren't processed here since Window* values aren't + // transferrable. A post processing step in WindowTree and WindowTreeClient + // takes care of the conversion. + for (const auto& window_ptr_property : window_ptr_properties_) { + if (window_ptr_property.second == transport_name) { + LOG(ERROR) << transport_name << " is a registered window property but " + << "should not be processed here."; + return; + } + } + + // WARNING: Adding a new map, be sure and update + // GetPropertyKeyFromTransportName() as well. + DVLOG(2) << "Unknown mus property name: " << transport_name; } @@ -379,6 +454,15 @@ void PropertyConverter::RegisterString16Property( transport_names_.insert(transport_name); } +void PropertyConverter::RegisterTimeDeltaProperty( + const WindowProperty* property, + const char* transport_name) { + // TimeDelta is internally handled (by class_property) as a primitive + // value (int64_t) . See ClassPropertyCaster for details. + RegisterPrimitiveProperty(property, transport_name, + CreateAcceptAnyValueCallback()); +} + void PropertyConverter::RegisterUnguessableTokenProperty( const WindowProperty* property, const char* transport_name) { @@ -388,6 +472,29 @@ void PropertyConverter::RegisterUnguessableTokenProperty( transport_names_.insert(transport_name); } +void PropertyConverter::RegisterWindowPtrProperty( + const WindowProperty* property, + const char* transport_name) { + DCHECK(!IsTransportNameRegistered(transport_name)) + << "Property already registered: " << transport_name; + window_ptr_properties_[property] = transport_name; + transport_names_.insert(transport_name); +} + +const WindowProperty* PropertyConverter::GetWindowPtrProperty( + const std::string& transport_name) const { + for (const auto& iter : window_ptr_properties_) { + if (transport_name == iter.second) + return iter.first; + } + return nullptr; +} + +bool PropertyConverter::IsWindowPtrPropertyRegistered( + const WindowProperty* property) const { + return window_ptr_properties_.find(property) != window_ptr_properties_.end(); +} + base::flat_map> PropertyConverter::GetTransportProperties(Window* window) { base::flat_map> properties; diff --git a/chromium/ui/aura/mus/property_converter.h b/chromium/ui/aura/mus/property_converter.h index 8d13b2021cd..82650db1321 100644 --- a/chromium/ui/aura/mus/property_converter.h +++ b/chromium/ui/aura/mus/property_converter.h @@ -18,6 +18,7 @@ #include "ui/aura/window.h" namespace base { +class TimeDelta; class UnguessableToken; } @@ -45,6 +46,10 @@ class AURA_EXPORT PropertyConverter { // accept any value. static base::RepeatingCallback CreateAcceptAnyValueCallback(); + // Returns the key for the window property registered against the specified + // transport name. + const void* GetPropertyKeyFromTransportName(const std::string& name); + // Returns true if RegisterProperty() has been called with the specified // transport name. bool IsTransportNameRegistered(const std::string& name) const; @@ -111,9 +116,23 @@ class AURA_EXPORT PropertyConverter { const char* transport_name); void RegisterString16Property(const WindowProperty* property, const char* transport_name); + void RegisterTimeDeltaProperty( + const WindowProperty* property, + const char* transport_name); void RegisterUnguessableTokenProperty( const WindowProperty* property, const char* transport_name); + void RegisterWindowPtrProperty(const WindowProperty* property, + const char* transport_name); + + // Returns the window property key of Window* value which is registered with + // the transport_name. If the name is not registered or registered with a + // different type, returns nullptr. + const WindowProperty* GetWindowPtrProperty( + const std::string& transport_name) const; + + bool IsWindowPtrPropertyRegistered( + const WindowProperty* property) const; // Get a flat map of the window's registered properties, to use for transport. base::flat_map> GetTransportProperties( @@ -151,6 +170,7 @@ class AURA_EXPORT PropertyConverter { string16_properties_; std::map*, const char*> unguessable_token_properties_; + std::map*, const char*> window_ptr_properties_; // Set of transport names supplied to RegisterProperty(). std::set transport_names_; diff --git a/chromium/ui/aura/mus/property_converter_unittest.cc b/chromium/ui/aura/mus/property_converter_unittest.cc index 50838071d5f..2d0382cf08f 100644 --- a/chromium/ui/aura/mus/property_converter_unittest.cc +++ b/chromium/ui/aura/mus/property_converter_unittest.cc @@ -43,6 +43,10 @@ DEFINE_UI_CLASS_PROPERTY_KEY(int16_t, kTestPropertyKey7, 1); DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kTestPropertyKey8, -1); DEFINE_UI_CLASS_PROPERTY_KEY(int64_t, kTestPropertyKey9, 777); +DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta, + kTestTimeDeltaKey, + base::TimeDelta()); + DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kTestImageSkiaPropertyKey, nullptr); @@ -53,6 +57,9 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY( DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(base::string16, kTestString16PropertyKey, nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestWindowPtrPropertyKey, nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestWindowPtrUnregisteredKey, nullptr); + const char kTestPropertyServerKey0[] = "test-property-server0"; const char kTestPropertyServerKey1[] = "test-property-server1"; const char kTestPropertyServerKey2[] = "test-property-server2"; @@ -69,6 +76,10 @@ const char kTestRectPropertyServerKey[] = "test-rect-property-server"; const char kTestSizePropertyServerKey[] = "test-size-property-server"; const char kTestStringPropertyServerKey[] = "test-string-property-server"; const char kTestString16PropertyServerKey[] = "test-string16-property-server"; +const char kTestTimeDeltaPropertyServerKey[] = + "test-time-delta-property-server"; +const char kTestWindowPtrPropertyServerKey[] = + "test-window-ptr-property-server"; // Test registration, naming and value conversion for primitive property types. template @@ -369,4 +380,84 @@ TEST_F(PropertyConverterTest, String16Property) { EXPECT_EQ(value_2, *window->GetProperty(kTestString16PropertyKey)); } +TEST_F(PropertyConverterTest, TimeDeltaProperty) { + PropertyConverter property_converter; + property_converter.RegisterTimeDeltaProperty(kTestTimeDeltaKey, + kTestTimeDeltaPropertyServerKey); + EXPECT_EQ( + kTestTimeDeltaPropertyServerKey, + property_converter.GetTransportNameForPropertyKey(kTestTimeDeltaKey)); + EXPECT_TRUE(property_converter.IsTransportNameRegistered( + kTestTimeDeltaPropertyServerKey)); + + std::unique_ptr window(CreateNormalWindow(1, root_window(), nullptr)); + const base::TimeDelta time_delta = + base::TimeDelta::FromMilliseconds(123456789); + window->SetProperty(kTestTimeDeltaKey, time_delta); + + std::string transport_name_out; + std::unique_ptr> transport_value_out; + EXPECT_TRUE(property_converter.ConvertPropertyForTransport( + window.get(), kTestTimeDeltaKey, &transport_name_out, + &transport_value_out)); + EXPECT_EQ(kTestTimeDeltaPropertyServerKey, transport_name_out); + const int64_t storage_value_1 = time_delta.InMicroseconds(); + std::vector transport_value = + mojo::ConvertTo>(storage_value_1); + EXPECT_EQ(transport_value, *transport_value_out.get()); + + int64_t decoded_value_1 = 0; + EXPECT_TRUE(property_converter.GetPropertyValueFromTransportValue( + kTestTimeDeltaPropertyServerKey, *transport_value_out, &decoded_value_1)); + EXPECT_EQ(time_delta.InMicroseconds(), decoded_value_1); + + window->SetProperty(kTestTimeDeltaKey, base::TimeDelta()); + property_converter.SetPropertyFromTransportValue( + window.get(), kTestTimeDeltaPropertyServerKey, &transport_value); + EXPECT_EQ(time_delta, window->GetProperty(kTestTimeDeltaKey)); +} + +TEST_F(PropertyConverterTest, WindowPtrProperty) { + PropertyConverter property_converter; + property_converter.RegisterString16Property(kTestString16PropertyKey, + kTestString16PropertyServerKey); + property_converter.RegisterWindowPtrProperty(kTestWindowPtrPropertyKey, + kTestWindowPtrPropertyServerKey); + EXPECT_EQ(kTestWindowPtrPropertyServerKey, + property_converter.GetTransportNameForPropertyKey( + kTestWindowPtrPropertyKey)); + EXPECT_TRUE(property_converter.IsTransportNameRegistered( + kTestWindowPtrPropertyServerKey)); + + EXPECT_TRUE(property_converter.IsWindowPtrPropertyRegistered( + kTestWindowPtrPropertyKey)); + EXPECT_EQ(kTestWindowPtrPropertyKey, property_converter.GetWindowPtrProperty( + kTestWindowPtrPropertyServerKey)); + EXPECT_FALSE(property_converter.IsWindowPtrPropertyRegistered( + kTestWindowPtrUnregisteredKey)); + EXPECT_FALSE( + property_converter.GetWindowPtrProperty(kTestString16PropertyServerKey)); + + std::unique_ptr window1( + CreateNormalWindow(1, root_window(), nullptr)); + std::unique_ptr window2( + CreateNormalWindow(2, root_window(), nullptr)); + window1->SetProperty(kTestWindowPtrPropertyKey, window2.get()); + + std::string transport_name_out; + std::unique_ptr> transport_value_out; + EXPECT_TRUE(property_converter.ConvertPropertyForTransport( + window1.get(), kTestWindowPtrPropertyKey, &transport_name_out, + &transport_value_out)); + EXPECT_EQ(kTestWindowPtrPropertyServerKey, transport_name_out); + EXPECT_FALSE(transport_value_out); + + window1->ClearProperty(kTestWindowPtrPropertyKey); + std::vector transport_value = mojo::ConvertTo>( + reinterpret_cast(window2.get())); + property_converter.SetPropertyFromTransportValue( + window1.get(), kTestWindowPtrPropertyServerKey, &transport_value); + EXPECT_FALSE(window1->GetProperty(kTestWindowPtrPropertyKey)); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/text_input_client_impl.cc b/chromium/ui/aura/mus/text_input_client_impl.cc index 0ce8eb10c23..29121c53a7e 100644 --- a/chromium/ui/aura/mus/text_input_client_impl.cc +++ b/chromium/ui/aura/mus/text_input_client_impl.cc @@ -52,9 +52,8 @@ void TextInputClientImpl::DispatchKeyEventPostIME( std::unique_ptr event, DispatchKeyEventPostIMECallback callback) { if (delegate_) { - delegate_->DispatchKeyEventPostIME(event->AsKeyEvent()); - if (callback && !callback.is_null()) - std::move(callback).Run(event->stopped_propagation()); + delegate_->DispatchKeyEventPostIME(event->AsKeyEvent(), + std::move(callback)); } } diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h index bac124e8b37..3ee4b65d25a 100644 --- a/chromium/ui/aura/mus/window_mus.h +++ b/chromium/ui/aura/mus/window_mus.h @@ -28,7 +28,6 @@ enum class OrderDirection; namespace viz { class FrameSinkId; class LocalSurfaceId; -class SurfaceInfo; } namespace aura { @@ -95,7 +94,6 @@ class AURA_EXPORT WindowMus { const viz::FrameSinkId& frame_sink_id) = 0; virtual const viz::LocalSurfaceId& GetOrAllocateLocalSurfaceId( const gfx::Size& new_size) = 0; - virtual void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info) = 0; // The window was deleted on the server side. DestroyFromServer() should // result in deleting |this|. virtual void DestroyFromServer() = 0; diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc index 9db986531be..2eb6ad5647c 100644 --- a/chromium/ui/aura/mus/window_port_mus.cc +++ b/chromium/ui/aura/mus/window_port_mus.cc @@ -4,13 +4,15 @@ #include "ui/aura/mus/window_port_mus.h" +#include "base/auto_reset.h" #include "cc/mojo_embedder/async_layer_tree_frame_sink.h" +#include "components/viz/client/hit_test_data_provider_draw_quad.h" #include "components/viz/client/local_surface_id_provider.h" #include "components/viz/host/host_frame_sink_manager.h" +#include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/transient_window_client.h" #include "ui/aura/env.h" -#include "ui/aura/hit_test_data_provider_aura.h" #include "ui/aura/mus/client_surface_embedder.h" #include "ui/aura/mus/property_converter.h" #include "ui/aura/mus/window_tree_client.h" @@ -27,6 +29,10 @@ namespace aura { +namespace { +static const char* kMus = "Mus"; +} // namespace + WindowPortMus::WindowMusChangeDataImpl::WindowMusChangeDataImpl() = default; WindowPortMus::WindowMusChangeDataImpl::~WindowMusChangeDataImpl() = default; @@ -38,7 +44,8 @@ WindowMus* WindowMus::Get(Window* window) { WindowPortMus::WindowPortMus(WindowTreeClient* client, WindowMusType window_mus_type) - : WindowMus(window_mus_type), + : WindowPort(WindowPort::Type::kMus), + WindowMus(window_mus_type), window_tree_client_(client), weak_ptr_factory_(this) {} @@ -56,7 +63,10 @@ WindowPortMus::~WindowPortMus() { // static WindowPortMus* WindowPortMus::Get(Window* window) { - return static_cast(WindowPort::Get(window)); + WindowPort* port = WindowPort::Get(window); + return port && port->type() == WindowPort::Type::kMus + ? static_cast(port) + : nullptr; } void WindowPortMus::SetTextInputState(ui::mojom::TextInputStatePtr state) { @@ -85,23 +95,36 @@ void WindowPortMus::SetCanAcceptDrops(bool can_accept_drops) { window_tree_client_->SetCanAcceptDrops(this, can_accept_drops); } -void WindowPortMus::SetHitTestMask(const base::Optional& mask) { - window_tree_client_->SetHitTestMask(this, mask); +void WindowPortMus::SetHitTestInsets(const gfx::Insets& mouse, + const gfx::Insets& touch) { + window_tree_client_->SetHitTestInsets(this, mouse, touch); } void WindowPortMus::Embed(ws::mojom::WindowTreeClientPtr client, uint32_t flags, ws::mojom::WindowTree::EmbedCallback callback) { - window_tree_client_->Embed(window_, std::move(client), flags, - std::move(callback)); + if (!PrepareForEmbed()) { + std::move(callback).Run(false); + return; + } + window_tree_client_->tree_->Embed( + server_id(), std::move(client), flags, + base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); } void WindowPortMus::EmbedUsingToken( const base::UnguessableToken& token, uint32_t flags, ws::mojom::WindowTree::EmbedCallback callback) { - window_tree_client_->EmbedUsingToken(window_, token, flags, - std::move(callback)); + if (!PrepareForEmbed()) { + std::move(callback).Run(false); + return; + } + window_tree_client_->tree_->EmbedUsingToken( + server_id(), token, flags, + base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); } std::unique_ptr @@ -119,11 +142,18 @@ WindowPortMus::RequestLayerTreeFrameSink( params.gpu_memory_buffer_manager = gpu_memory_buffer_manager; params.pipes.compositor_frame_sink_info = std::move(sink_info); params.pipes.client_request = std::move(client_request); + bool root_accepts_events = + (window_->event_targeting_policy() == + ws::mojom::EventTargetingPolicy::TARGET_ONLY) || + (window_->event_targeting_policy() == + ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); params.hit_test_data_provider = - std::make_unique(window_); + std::make_unique( + true /* should_ask_for_child_region */, root_accepts_events); params.local_surface_id_provider = std::make_unique(); params.enable_surface_synchronization = true; + params.client_name = kMus; auto layer_tree_frame_sink = std::make_unique( @@ -213,6 +243,43 @@ WindowPortMus::ServerChanges::iterator WindowPortMus::FindChangeByTypeAndData( return iter; } +bool WindowPortMus::PrepareForEmbed() { + // Window::Init() must be called before Embed() (otherwise the server hasn't + // been told about the window). + DCHECK(window_->layer()); + + // The window server removes all children before embedding. In other words, + // it's generally an error to Embed() with existing children. So, fail early. + if (!window_->children().empty()) + return false; + + // Can only embed in windows created by this client. + if (window_mus_type() != WindowMusType::LOCAL) + return false; + + // Don't allow an embed when one exists. This could be handled, if the + // callback was converted to OnChangeCompleted(). To attempt to handle it + // without routing the callback over the WindowTreeClient pipe would result + // in problemcs because of ordering. The ordering problem is because there is + // the Embed() request, the callback, and OnEmbeddedAppDisconnected() (which + // originates from the server side). + if (has_embedding_) + return false; + + has_embedding_ = true; + return true; +} + +// static +void WindowPortMus::OnEmbedAck( + base::WeakPtr window, + ws::mojom::WindowTree::EmbedCallback real_callback, + bool result) { + if (window && !result) + window->has_embedding_ = false; + std::move(real_callback).Run(window && result); +} + PropertyConverter* WindowPortMus::GetPropertyConverter() { return window_tree_client_->delegate_->GetPropertyConverter(); } @@ -305,9 +372,12 @@ void WindowPortMus::SetPropertyFromServer( void WindowPortMus::SetFrameSinkIdFromServer( const viz::FrameSinkId& frame_sink_id) { - DCHECK(window_mus_type() == WindowMusType::EMBED_IN_OWNER); - window_->SetEmbedFrameSinkId(frame_sink_id); - UpdatePrimarySurfaceId(); + embed_frame_sink_id_ = frame_sink_id; + window_->SetEmbedFrameSinkId(embed_frame_sink_id_); + // We may not have allocated a LocalSurfaceId. Call OnWindowMusBoundsChanged() + // to trigger updating the LocalSurfaceId *and* notifying the server. + window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(), + window_->bounds()); } const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId( @@ -331,25 +401,6 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId( return local_surface_id_; } -void WindowPortMus::SetFallbackSurfaceInfo( - const viz::SurfaceInfo& surface_info) { - if (!window_->IsEmbeddingClient()) { - // |primary_surface_id_| shold not be valid, since we didn't know the - // |window_->frame_sink_id()|. - DCHECK(!primary_surface_id_.is_valid()); - window_->SetEmbedFrameSinkId(surface_info.id().frame_sink_id()); - UpdatePrimarySurfaceId(); - } - - // The frame sink id should never be changed. - DCHECK_EQ(surface_info.id().frame_sink_id(), window_->GetFrameSinkId()); - - fallback_surface_info_ = surface_info; - UpdateClientSurfaceEmbedder(); - if (window_->delegate()) - window_->delegate()->OnFirstSurfaceActivation(fallback_surface_info_); -} - void WindowPortMus::DestroyFromServer() { std::unique_ptr remove_from_parent_change; if (window_->parent()) { @@ -408,6 +459,8 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved( void WindowPortMus::AllocateLocalSurfaceId() { local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); UpdatePrimarySurfaceId(); + if (local_layer_tree_frame_sink_) + local_layer_tree_frame_sink_->SetLocalSurfaceId(local_surface_id_); } bool WindowPortMus::IsLocalSurfaceIdAllocationSuppressed() const { @@ -426,6 +479,12 @@ void WindowPortMus::UpdateLocalSurfaceIdFromEmbeddedClient( embedded_client_local_surface_id); local_surface_id_ = parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(); + UpdatePrimarySurfaceId(); + + // OnWindowMusBoundsChanged() triggers notifying the server of the new + // LocalSurfaceId. + window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(), + window_->bounds()); } const viz::LocalSurfaceId& WindowPortMus::GetLocalSurfaceId() { @@ -459,6 +518,7 @@ void WindowPortMus::PrepareForDestroy() { } void WindowPortMus::NotifyEmbeddedAppDisconnected() { + has_embedding_ = false; for (WindowObserver& observer : *GetObservers(window_)) observer.OnEmbeddedAppDisconnected(window_); } @@ -575,20 +635,18 @@ WindowPortMus::CreateLayerTreeFrameSink() { DCHECK_EQ(window_mus_type(), WindowMusType::LOCAL); DCHECK(!local_layer_tree_frame_sink_); - std::unique_ptr frame_sink; auto client_layer_tree_frame_sink = RequestLayerTreeFrameSink( - nullptr, - aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager()); + nullptr, window_->env()->context_factory()->GetGpuMemoryBufferManager()); local_layer_tree_frame_sink_ = client_layer_tree_frame_sink->GetWeakPtr(); - frame_sink = std::move(client_layer_tree_frame_sink); - window_->SetEmbedFrameSinkId(GenerateFrameSinkIdFromServerId()); + embed_frame_sink_id_ = GenerateFrameSinkIdFromServerId(); + window_->SetEmbedFrameSinkId(embed_frame_sink_id_); gfx::Size size_in_pixel = gfx::ConvertSizeToPixel(GetDeviceScaleFactor(), window_->bounds().size()); // Make sure |local_surface_id_| and |last_surface_size_in_pixels_| are // correct for the new created |local_layer_tree_frame_sink_|. GetOrAllocateLocalSurfaceId(size_in_pixel); - return frame_sink; + return client_layer_tree_frame_sink; } void WindowPortMus::OnEventTargetingPolicyChanged() { @@ -599,25 +657,30 @@ bool WindowPortMus::ShouldRestackTransientChildren() { return should_restack_transient_children_; } +void WindowPortMus::RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) { + if (frame_sink_id == embed_frame_sink_id_) + return; + + window_tree_client_->RegisterFrameSinkId(this, frame_sink_id); +} + +void WindowPortMus::UnregisterFrameSinkId( + const viz::FrameSinkId& frame_sink_id) { + if (frame_sink_id == embed_frame_sink_id_) + return; + + window_tree_client_->UnregisterFrameSinkId(this); +} + void WindowPortMus::UpdatePrimarySurfaceId() { - if (window_mus_type() != WindowMusType::EMBED_IN_OWNER && - window_mus_type() != WindowMusType::LOCAL) { + if (window_mus_type() != WindowMusType::LOCAL) return; - } if (!window_->IsEmbeddingClient() || !local_surface_id_.is_valid()) return; primary_surface_id_ = viz::SurfaceId(window_->GetFrameSinkId(), local_surface_id_); - UpdateClientSurfaceEmbedder(); -} - -void WindowPortMus::UpdateClientSurfaceEmbedder() { - if (window_mus_type() != WindowMusType::EMBED_IN_OWNER && - window_mus_type() != WindowMusType::LOCAL) { - return; - } if (!client_surface_embedder_) { client_surface_embedder_ = std::make_unique( @@ -625,7 +688,7 @@ void WindowPortMus::UpdateClientSurfaceEmbedder() { } client_surface_embedder_->SetPrimarySurfaceId(primary_surface_id_); - client_surface_embedder_->SetFallbackSurfaceInfo(fallback_surface_info_); + client_surface_embedder_->UpdateSizeAndGutters(); } } // namespace aura diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h index e6ec469c098..428b05a2732 100644 --- a/chromium/ui/aura/mus/window_port_mus.h +++ b/chromium/ui/aura/mus/window_port_mus.h @@ -45,7 +45,6 @@ namespace aura { class ClientSurfaceEmbedder; class PropertyConverter; class Window; -class WindowPortMusTest; class WindowTreeClient; class WindowTreeClientPrivate; class WindowTreeHostMus; @@ -87,7 +86,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void SetCanAcceptDrops(bool can_accept_drops); // See description in mojom for details on this. - void SetHitTestMask(const base::Optional& mask); + void SetHitTestInsets(const gfx::Insets& mouse, const gfx::Insets& touch); // Embeds a new client in this Window. See WindowTreeClient::Embed() for // details on arguments. @@ -106,7 +105,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { viz::FrameSinkId GenerateFrameSinkIdFromServerId() const; private: - friend class WindowPortMusTest; + friend class WindowPortMusTestHelper; friend class WindowTreeClient; friend class WindowTreeClientPrivate; friend class WindowTreeHostMus; @@ -116,7 +115,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { // Changes to the underlying Window originating from the server must be done // in such a way that the same change is not applied back to the server. To - // accomplish this every changes from the server is associated with at least + // accomplish this every change from the server is associated with at least // one ServerChange. If the underlying Window ends up calling back to this // class and the change is expected then the change is ignored and not sent to // the server. For example, here's the flow when the server changes the @@ -221,6 +220,16 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { ServerChanges::iterator FindChangeByTypeAndData(const ServerChangeType type, const ServerChangeData& data); + // Called to setup state necessary for an embedding. Returns false if an + // embedding is not allowed in this window. + bool PrepareForEmbed(); + + // Called from OnEmbed() with the result of the embedding. |real_callback| is + // the callback supplied to the embed call. + static void OnEmbedAck(base::WeakPtr window, + ws::mojom::WindowTree::EmbedCallback real_callback, + bool result); + PropertyConverter* GetPropertyConverter(); // WindowMus: @@ -245,7 +254,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { const gfx::Size& surface_size_in_pixels) override; void UpdateLocalSurfaceIdFromEmbeddedClient( const viz::LocalSurfaceId& embedded_client_local_surface_id) override; - void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info) override; void DestroyFromServer() override; void AddTransientChildFromServer(WindowMus* child) override; void RemoveTransientChildFromServer(WindowMus* child) override; @@ -285,9 +293,10 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { const viz::LocalSurfaceId& GetLocalSurfaceId() override; void OnEventTargetingPolicyChanged() override; bool ShouldRestackTransientChildren() override; + void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override; + void UnregisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override; void UpdatePrimarySurfaceId(); - void UpdateClientSurfaceEmbedder(); WindowTreeClient* window_tree_client_; @@ -300,7 +309,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { ServerChanges server_changes_; viz::SurfaceId primary_surface_id_; - viz::SurfaceInfo fallback_surface_info_; viz::LocalSurfaceId local_surface_id_; // TODO(sad, fsamuel): For 'mash' mode, where the embedder is responsible for @@ -311,9 +319,15 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { ui::CursorData cursor_; + // Set if this class calls SetEmbedFrameSinkId() on the associated window. + viz::FrameSinkId embed_frame_sink_id_; + // See description in single place that changes the value for details. bool should_restack_transient_children_ = true; + // True if this window has an embedding. + bool has_embedding_ = false; + // When a frame sink is created // for a local aura::Window, we need keep a weak ptr of it, so we can update // the local surface id when necessary. diff --git a/chromium/ui/aura/mus/window_port_mus_unittest.cc b/chromium/ui/aura/mus/window_port_mus_unittest.cc index 0e05b5886d5..fe616b2dc28 100644 --- a/chromium/ui/aura/mus/window_port_mus_unittest.cc +++ b/chromium/ui/aura/mus/window_port_mus_unittest.cc @@ -7,26 +7,16 @@ #include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/mus/client_surface_embedder.h" +#include "ui/aura/test/aura_mus_test_base.h" #include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/mus/test_window_tree.h" +#include "ui/aura/test/mus/window_port_mus_test_helper.h" #include "ui/aura/window.h" #include "ui/base/ui_base_features.h" namespace aura { -class WindowPortMusTest : public test::AuraTestBase { - public: - WindowPortMusTest() { EnableMusWithTestWindowTree(); } - - ~WindowPortMusTest() override = default; - - base::WeakPtr GetFrameSinkFor(Window* window) { - auto* window_mus = WindowPortMus::Get(window); - return window_mus->local_layer_tree_frame_sink_; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowPortMusTest); -}; +using WindowPortMusTest = test::AuraMusClientTestBase; // TODO(sadrul): https://crbug.com/842361. TEST_F(WindowPortMusTest, @@ -45,7 +35,7 @@ TEST_F(WindowPortMusTest, window.CreateLayerTreeFrameSink()); EXPECT_TRUE(frame_sink.get()); - auto mus_frame_sink = GetFrameSinkFor(&window); + auto mus_frame_sink = WindowPortMusTestHelper(&window).GetFrameSink(); ASSERT_TRUE(mus_frame_sink); auto frame_sink_local_surface_id = static_cast( @@ -71,4 +61,46 @@ TEST_F(WindowPortMusTest, ClientSurfaceEmbedderUpdatesLayer) { EXPECT_EQ(local_surface_id, primary_surface_id.local_surface_id()); } +TEST_F(WindowPortMusTest, + UpdateLocalSurfaceIdFromEmbeddedClientUpdateClientSurfaceEmbedder) { + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.set_owned_by_parent(false); + window.SetBounds(gfx::Rect(300, 300)); + // Simulate an embedding. + window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); + root_window()->AddChild(&window); + + // AckAllChanges() so that can verify a bounds change happens from + // UpdateLocalSurfaceIdFromEmbeddedClient(). + window_tree()->AckAllChanges(); + + // Update the LocalSurfaceId. + viz::LocalSurfaceId current_id = window.GetSurfaceId().local_surface_id(); + ASSERT_TRUE(current_id.is_valid()); + viz::ParentLocalSurfaceIdAllocator* parent_allocator = + WindowPortMusTestHelper(&window).GetParentLocalSurfaceIdAllocator(); + parent_allocator->Reset(current_id); + viz::LocalSurfaceId updated_id = parent_allocator->GenerateId(); + ASSERT_TRUE(updated_id.is_valid()); + EXPECT_NE(updated_id, current_id); + window.UpdateLocalSurfaceIdFromEmbeddedClient(updated_id); + + // Updating the LocalSurfaceId should propagate to the ClientSurfaceEmbedder. + auto* window_mus = WindowPortMus::Get(&window); + ASSERT_TRUE(window_mus); + ASSERT_TRUE(window_mus->client_surface_embedder()); + EXPECT_EQ(updated_id, window_mus->client_surface_embedder() + ->GetPrimarySurfaceIdForTesting() + .local_surface_id()); + + // The server is notified of a bounds change, so that it sees the new + // LocalSurfaceId. + ASSERT_EQ(1u, + window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS)); + ASSERT_TRUE(window_tree()->last_local_surface_id()); + EXPECT_EQ(window_mus->server_id(), window_tree()->window_id()); + EXPECT_EQ(updated_id, *(window_tree()->last_local_surface_id())); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc index 517bd131eaf..f28829be913 100644 --- a/chromium/ui/aura/mus/window_tree_client.cc +++ b/chromium/ui/aura/mus/window_tree_client.cc @@ -38,6 +38,7 @@ #include "ui/aura/mus/embed_root.h" #include "ui/aura/mus/embed_root_delegate.h" #include "ui/aura/mus/focus_synchronizer.h" +#include "ui/aura/mus/gesture_synchronizer.h" #include "ui/aura/mus/in_flight_change.h" #include "ui/aura/mus/input_method_mus.h" #include "ui/aura/mus/mus_context_factory.h" @@ -121,32 +122,7 @@ WindowTreeHostMus* GetWindowTreeHostMus(WindowMus* window) { } bool IsInternalProperty(const void* key) { - return key == client::kModalKey || key == client::kChildModalParentKey; -} - -// Create and return a MouseEvent or TouchEvent from |event| if |event| is a -// PointerEvent, otherwise return the copy of |event|. -std::unique_ptr MapEvent(const ui::Event& event) { - if (event.IsPointerEvent()) { - const ui::PointerEvent& pointer_event = *event.AsPointerEvent(); - // Use a switch statement in case more pointer types are added. - switch (pointer_event.pointer_details().pointer_type) { - case ui::EventPointerType::POINTER_TYPE_MOUSE: - if (event.type() == ui::ET_POINTER_WHEEL_CHANGED) - return std::make_unique(pointer_event); - return std::make_unique(pointer_event); - case ui::EventPointerType::POINTER_TYPE_TOUCH: - case ui::EventPointerType::POINTER_TYPE_PEN: - return std::make_unique(pointer_event); - case ui::EventPointerType::POINTER_TYPE_ERASER: - NOTIMPLEMENTED(); - break; - case ui::EventPointerType::POINTER_TYPE_UNKNOWN: - NOTREACHED(); - break; - } - } - return ui::Event::Clone(event); + return key == client::kModalKey; } } // namespace @@ -273,31 +249,26 @@ void WindowTreeClient::SetImeVisibility(WindowMus* window, tree_->SetImeVisibility(window->server_id(), visible, std::move(state)); } -void WindowTreeClient::SetHitTestMask( - WindowMus* window, - const base::Optional& mask_rect) { +void WindowTreeClient::SetHitTestInsets(WindowMus* window, + const gfx::Insets& mouse, + const gfx::Insets& touch) { DCHECK(tree_); - tree_->SetHitTestMask(window->server_id(), mask_rect); + tree_->SetHitTestInsets(window->server_id(), mouse, touch); } -void WindowTreeClient::Embed(Window* window, - ws::mojom::WindowTreeClientPtr client, - uint32_t flags, - ws::mojom::WindowTree::EmbedCallback callback) { - DCHECK(tree_); - // Window::Init() must be called before Embed() (otherwise the server hasn't - // been told about the window). - DCHECK(window->layer()); - if (!window->children().empty()) { - // The window server removes all children before embedding. In other words, - // it's generally an error to Embed() with existing children. So, fail - // early. - std::move(callback).Run(false); - return; - } +void WindowTreeClient::RegisterFrameSinkId( + WindowMus* window, + const viz::FrameSinkId& frame_sink_id) { + tree_->AttachFrameSinkId(window->server_id(), frame_sink_id); + + // Call OnWindowMusBoundsChanged() to force allocation of a LocalSurfaceId as + // well as notifying the server of the LocalSurfaceId. + const gfx::Rect bounds = window->GetWindow()->bounds(); + OnWindowMusBoundsChanged(window, bounds, bounds); +} - tree_->Embed(WindowMus::Get(window)->server_id(), std::move(client), flags, - std::move(callback)); +void WindowTreeClient::UnregisterFrameSinkId(WindowMus* window) { + tree_->UnattachFrameSinkId(window->server_id()); } void WindowTreeClient::ScheduleEmbed( @@ -306,27 +277,6 @@ void WindowTreeClient::ScheduleEmbed( tree_->ScheduleEmbed(std::move(client), std::move(callback)); } -void WindowTreeClient::EmbedUsingToken( - Window* window, - const base::UnguessableToken& token, - uint32_t flags, - ws::mojom::WindowTree::EmbedCallback callback) { - DCHECK(tree_); - // Window::Init() must be called before Embed() (otherwise the server hasn't - // been told about the window). - DCHECK(window->layer()); - if (!window->children().empty()) { - // The window server removes all children before embedding. In other words, - // it's generally an error to Embed() with existing children. So, fail - // early. - std::move(callback).Run(false); - return; - } - - tree_->EmbedUsingToken(WindowMus::Get(window)->server_id(), token, flags, - std::move(callback)); -} - void WindowTreeClient::AttachCompositorFrameSink( ws::Id window_id, viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, @@ -413,7 +363,9 @@ WindowMus* WindowTreeClient::GetWindowByServerId(ws::Id id) { bool WindowTreeClient::IsWindowKnown(aura::Window* window) { WindowMus* window_mus = WindowMus::Get(window); - return windows_.count(window_mus->server_id()) > 0; + // NOTE: this function explicitly checks for a null WindowMus as it may be + // called from global observers that may see other types. + return window_mus && windows_.count(window_mus->server_id()) > 0; } InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching( @@ -584,6 +536,7 @@ void WindowTreeClient::WindowTreeConnectionEstablished( drag_drop_controller_ = std::make_unique(this, tree_); capture_synchronizer_ = std::make_unique(this, tree_); focus_synchronizer_ = std::make_unique(this, tree_); + gesture_synchronizer_ = std::make_unique(tree_); } void WindowTreeClient::OnConnectionLost() { @@ -601,18 +554,6 @@ bool WindowTreeClient::HandleInternalPropertyChanged(WindowMus* window, window->GetWindow()->GetProperty(client::kModalKey)); return true; } - if (key == client::kChildModalParentKey) { - const uint32_t change_id = - ScheduleInFlightChange(std::make_unique( - window, ChangeType::CHILD_MODAL_PARENT)); - Window* child_modal_parent = - window->GetWindow()->GetProperty(client::kChildModalParentKey); - tree_->SetChildModalParent( - change_id, window->server_id(), - child_modal_parent ? WindowMus::Get(child_modal_parent)->server_id() - : kInvalidServerId); - return true; - } return false; } @@ -736,16 +677,17 @@ void WindowTreeClient::ScheduleInFlightBoundsChange( ScheduleInFlightChange(std::make_unique( this, window, old_bounds, window->GetLocalSurfaceId())); base::Optional local_surface_id; - if (window->window_mus_type() == WindowMusType::EMBED_IN_OWNER || + if (window->GetWindow()->IsEmbeddingClient() || window->HasLocalLayerTreeFrameSink()) { // Do not use ConvertRectToPixel, enclosing rects cause problems. const gfx::Size size = gfx::ScaleToCeiledSize( new_bounds.size(), window->GetDeviceScaleFactor()); local_surface_id = window->GetOrAllocateLocalSurfaceId(size); // |window_tree_host| may be null if this is called during creation of - // the window associated with the WindowTreeHostMus. + // the window associated with the WindowTreeHostMus, or if there is an + // embedding. WindowTreeHost* window_tree_host = window->GetWindow()->GetHost(); - if (window_tree_host) + if (window_tree_host && window_tree_host->window() == window->GetWindow()) window_tree_host->compositor()->OnChildResizing(); } tree_->SetWindowBounds(change_id, window->server_id(), new_bounds, @@ -904,13 +846,24 @@ void WindowTreeClient::OnWindowMusPropertyChanged( WindowPortPropertyDataMus* data_mus = static_cast(data.get()); + PropertyConverter* property_converter = delegate_->GetPropertyConverter(); std::string transport_name; std::unique_ptr> transport_value; - if (!delegate_->GetPropertyConverter()->ConvertPropertyForTransport( + if (!property_converter->ConvertPropertyForTransport( window->GetWindow(), key, &transport_name, &transport_value)) { return; } DCHECK_EQ(transport_name, data_mus->transport_name); + const auto* window_ptr_key = static_cast*>(key); + if (property_converter->IsWindowPtrPropertyRegistered(window_ptr_key)) { + DCHECK(!transport_value); + Window* value = window->GetWindow()->GetProperty(window_ptr_key); + WindowMus* window_mus = WindowMus::Get(value); + if (window_mus) { + transport_value = std::make_unique>( + mojo::ConvertTo>(window_mus->server_id())); + } + } base::Optional> transport_value_mojo; if (transport_value) @@ -1273,6 +1226,14 @@ void WindowTreeClient::OnWindowOpacityChanged(ws::Id window_id, window->SetOpacityFromServer(new_opacity); } +void WindowTreeClient::OnWindowDisplayChanged(ws::Id window_id, + int64_t display_id) { + WindowMus* window = GetWindowByServerId(window_id); + if (!window) + return; + GetWindowTreeHostMus(window->GetWindow())->set_display_id(display_id); +} + void WindowTreeClient::OnWindowParentDrawnStateChanged(ws::Id window_id, bool drawn) { // TODO: route to WindowTreeHost. @@ -1311,10 +1272,22 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, DCHECK(event); WindowMus* window = GetWindowByServerId(window_id); // May be null. + DCHECK(!event->IsPointerEvent()); + if (matches_pointer_watcher && has_pointer_watcher_) { - DCHECK(event->IsPointerEvent()); - std::unique_ptr event_in_dip(ui::Event::Clone(*event)); - NotifyPointerEventObserved(event_in_dip->AsPointerEvent(), display_id, + // TODO(sky): remove this once PointerWatcher doesn't need PointerEvent. + // https://crbug.com/865781 + std::unique_ptr pointer_event; + if (event->IsMouseEvent()) { + pointer_event = + std::make_unique(*event->AsMouseEvent()); + } else if (event->IsTouchEvent()) { + pointer_event = + std::make_unique(*event->AsTouchEvent()); + } else { + NOTREACHED(); + } + NotifyPointerEventObserved(pointer_event->AsPointerEvent(), display_id, window); } @@ -1323,13 +1296,10 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, if (!window || !window->GetWindow()->GetHost()) { EnvInputStateController* env_controller = Env::GetInstance()->env_controller(); - std::unique_ptr mapped_event = MapEvent(*event.get()); - if (mapped_event->IsMouseEvent()) { - env_controller->UpdateStateForMouseEvent(nullptr, - *mapped_event->AsMouseEvent()); - } else if (mapped_event->IsTouchEvent()) { - env_controller->UpdateStateForTouchEvent(*mapped_event->AsTouchEvent()); - } + if (event->IsMouseEvent()) + env_controller->UpdateStateForMouseEvent(nullptr, *event->AsMouseEvent()); + else if (event->IsTouchEvent()) + env_controller->UpdateStateForTouchEvent(*event->AsTouchEvent()); tree_->OnWindowInputEventAck(event_id, ws::mojom::EventResult::UNHANDLED); return; } @@ -1343,10 +1313,6 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, } } - // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or - // ui::TouchEvent once we have proper support for pointer events. - std::unique_ptr mapped_event = MapEvent(*event.get()); - ui::Event* event_to_dispatch = mapped_event.get(); // |ack_handler| may use |event_to_dispatch| from its destructor, so it needs // to be destroyed after |event_to_dispatch| is destroyed. EventAckHandler ack_handler(CreateEventResultCallback(event_id)); @@ -1354,12 +1320,12 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, if (!event->IsKeyEvent()) { // Set |window| as the target, except for key events. Key events go to the // focused window, which may have changed by the time we process the event. - ui::Event::DispatcherApi(event_to_dispatch).set_target(window->GetWindow()); + ui::Event::DispatcherApi(event.get()).set_target(window->GetWindow()); } - GetWindowTreeHostMus(window)->SendEventToSink(event_to_dispatch); + GetWindowTreeHostMus(window)->SendEventToSink(event.get()); - ack_handler.set_handled(event_to_dispatch->handled()); + ack_handler.set_handled(event->handled()); } void WindowTreeClient::OnPointerEventObserved(std::unique_ptr event, @@ -1397,21 +1363,6 @@ void WindowTreeClient::OnWindowCursorChanged(ws::Id window_id, window->SetCursorFromServer(cursor); } -void WindowTreeClient::OnWindowSurfaceChanged( - ws::Id window_id, - const viz::SurfaceInfo& surface_info) { - WindowMus* window = GetWindowByServerId(window_id); - if (!window) - return; - - // If the parent is informed of a child's surface then that surface ID is - // guaranteed to be available in the display compositor so we set it as the - // fallback. If surface synchronization is enabled, the primary SurfaceInfo - // is created by the embedder, and the LocalSurfaceId is allocated by the - // embedder. - window->SetFallbackSurfaceInfo(surface_info); -} - void WindowTreeClient::OnDragDropStart( const base::flat_map>& mime_data) { drag_drop_controller_->OnDragDropStart(mojo::FlatMapToMap(mime_data)); @@ -1605,13 +1556,6 @@ void WindowTreeClient::OnWindowTreeHostStackAtTop( tree_->StackAtTop(change_id, window->server_id()); } -void WindowTreeClient::OnWindowTreeHostPerformWmAction( - WindowTreeHostMus* window_tree_host, - const std::string& action) { - WindowMus* window = WindowMus::Get(window_tree_host->window()); - tree_->PerformWmAction(window->server_id(), action); -} - void WindowTreeClient::OnWindowTreeHostPerformWindowMove( WindowTreeHostMus* window_tree_host, ws::mojom::MoveLoopSource source, diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h index f4d0931ed3e..9183c781309 100644 --- a/chromium/ui/aura/mus/window_tree_client.h +++ b/chromium/ui/aura/mus/window_tree_client.h @@ -61,6 +61,7 @@ class DragDropControllerMus; class EmbedRoot; class EmbedRootDelegate; class FocusSynchronizer; +class GestureSynchronizer; class InFlightBoundsChange; class InFlightChange; class InFlightFocusChange; @@ -136,20 +137,14 @@ class AURA_EXPORT WindowTreeClient void SetImeVisibility(WindowMus* window, bool visible, ui::mojom::TextInputStatePtr state); - void SetHitTestMask(WindowMus* window, const base::Optional& rect); - - // Embeds a new client in |window|. |flags| is a bitmask of the values defined - // by kEmbedFlag*; 0 gives default behavior. |callback| is called to indicate - // whether the embedding succeeded or failed and may be called immediately if - // the embedding is known to fail. - void Embed(Window* window, - ws::mojom::WindowTreeClientPtr client, - uint32_t flags, - ws::mojom::WindowTree::EmbedCallback callback); - void EmbedUsingToken(Window* window, - const base::UnguessableToken& token, - uint32_t flags, - ws::mojom::WindowTree::EmbedCallback callback); + void SetHitTestInsets(WindowMus* window, + const gfx::Insets& mouse, + const gfx::Insets& touch); + + // See WindowPort for details on these. + void RegisterFrameSinkId(WindowMus* window, + const viz::FrameSinkId& child_frame_sink_id); + void UnregisterFrameSinkId(WindowMus* window); // Schedules an embed of a client. See // ws::mojom::WindowTreeClient::ScheduleEmbed() for details. @@ -177,6 +172,17 @@ class AURA_EXPORT WindowTreeClient ws::mojom::MoveLoopSource source, aura::Window* initial_target); + // See mojom for details. + template + mojo::AssociatedInterfacePtr BindWindowManagerInterface() { + ws::mojom::WindowManagerAssociatedPtr interface_ptr; + tree_->BindWindowManagerInterface(Interface::Name_, + mojo::MakeRequest(&interface_ptr)); + return mojo::AssociatedInterfacePtr( + mojo::AssociatedInterfacePtrInfo( + interface_ptr.PassInterface().PassHandle(), Interface::Version_)); + } + // Returns true if the specified window was created by this client. bool WasCreatedByThisClient(const WindowMus* window) const; @@ -403,6 +409,7 @@ class AURA_EXPORT WindowTreeClient void OnWindowOpacityChanged(ws::Id window_id, float old_opacity, float new_opacity) override; + void OnWindowDisplayChanged(ws::Id window_id, int64_t display_id) override; void OnWindowParentDrawnStateChanged(ws::Id window_id, bool drawn) override; void OnWindowSharedPropertyChanged( ws::Id window_id, @@ -418,8 +425,6 @@ class AURA_EXPORT WindowTreeClient int64_t display_id) override; void OnWindowFocused(ws::Id focused_window_id) override; void OnWindowCursorChanged(ws::Id window_id, ui::CursorData cursor) override; - void OnWindowSurfaceChanged(ws::Id window_id, - const viz::SurfaceInfo& surface_info) override; void OnDragDropStart(const base::flat_map>& mime_data) override; void OnDragEnter(ws::Id window_id, @@ -469,8 +474,6 @@ class AURA_EXPORT WindowTreeClient void OnWindowTreeHostStackAbove(WindowTreeHostMus* window_tree_host, Window* window) override; void OnWindowTreeHostStackAtTop(WindowTreeHostMus* window_tree_host) override; - void OnWindowTreeHostPerformWmAction(WindowTreeHostMus* window_tree_host, - const std::string& action) override; void OnWindowTreeHostPerformWindowMove( WindowTreeHostMus* window_tree_host, ws::mojom::MoveLoopSource mus_source, @@ -526,6 +529,8 @@ class AURA_EXPORT WindowTreeClient std::unique_ptr focus_synchronizer_; + std::unique_ptr gesture_synchronizer_; + mojo::Binding binding_; ws::mojom::WindowTreePtr tree_ptr_; // Typically this is the value contained in |tree_ptr_|, but tests may diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc index e8c841cb632..2ca4cce0c21 100644 --- a/chromium/ui/aura/mus/window_tree_client_unittest.cc +++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc @@ -39,6 +39,7 @@ #include "ui/aura/mus/window_tree_host_mus_init_params.h" #include "ui/aura/test/aura_mus_test_base.h" #include "ui/aura/test/mus/test_window_tree.h" +#include "ui/aura/test/mus/window_port_mus_test_helper.h" #include "ui/aura/test/mus/window_tree_client_private.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/test/test_window_delegate.h" @@ -68,10 +69,12 @@ namespace { DEFINE_UI_CLASS_PROPERTY_KEY(uint8_t, kTestPropertyKey1, 0); DEFINE_UI_CLASS_PROPERTY_KEY(uint16_t, kTestPropertyKey2, 0); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kTestPropertyKey3, false); +DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestPropertyKey4, nullptr); const char kTestPropertyServerKey1[] = "test-property-server1"; const char kTestPropertyServerKey2[] = "test-property-server2"; const char kTestPropertyServerKey3[] = "test-property-server3"; +const char kTestPropertyServerKey4[] = "test-property-server4"; ws::Id server_id(Window* window) { return window ? WindowMus::Get(window)->server_id() : 0; @@ -113,6 +116,8 @@ void RegisterTestProperties(PropertyConverter* converter) { converter->RegisterPrimitiveProperty( kTestPropertyKey3, kTestPropertyServerKey3, PropertyConverter::CreateAcceptAnyValueCallback()); + converter->RegisterWindowPtrProperty(kTestPropertyKey4, + kTestPropertyServerKey4); } // Convert a primitive aura property value to a mus transport value. @@ -269,11 +274,8 @@ TEST_F(WindowTreeClientTest, SetBoundsFailed) { // reverted if the server replied that the change failed. TEST_F(WindowTreeClientTest, SetBoundsFailedLocalSurfaceId) { Window window(nullptr); - // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds - // when their sizes change. - window.SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); window.Init(ui::LAYER_NOT_DRAWN); + WindowPortMusTestHelper(&window).SimulateEmbedding(); const gfx::Rect original_bounds(window.bounds()); const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100)); @@ -295,111 +297,29 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowTreeClientTestSurfaceSync, ::testing::Bool()); -namespace { - -class FirstSurfaceActivationWindowDelegate : public test::TestWindowDelegate { - public: - FirstSurfaceActivationWindowDelegate() = default; - ~FirstSurfaceActivationWindowDelegate() override = default; - - const viz::SurfaceInfo& last_surface_info() const { - return last_surface_info_; - } - - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override { - last_surface_info_ = surface_info; - } - - private: - viz::SurfaceInfo last_surface_info_; - - DISALLOW_COPY_AND_ASSIGN(FirstSurfaceActivationWindowDelegate); -}; - -} // namespace - -// Verifies that a ClientSurfaceEmbedder is created for a window once it has -// a bounds, and a valid FrameSinkId. -TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderOnValidEmbedding) { - FirstSurfaceActivationWindowDelegate delegate; - Window window(&delegate); - // EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds when their sizes - // change. - window.SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); +// Verifies that windows with an embedding create a ClientSurfaceEmbedder. +TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderCreated) { + Window window(nullptr); window.Init(ui::LAYER_NOT_DRAWN); + WindowPortMusTestHelper(&window).SimulateEmbedding(); // The window will allocate a viz::LocalSurfaceId once it has a bounds. - WindowMus* window_mus = WindowMus::Get(&window); - ASSERT_NE(nullptr, window_mus); - EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid()); - gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100)); - ASSERT_NE(new_bounds, window.bounds()); - window.SetBounds(new_bounds); - EXPECT_EQ(new_bounds, window.bounds()); - EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid()); - - // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and - // a valid FrameSinkId. WindowPortMus* window_port_mus = WindowPortMus::Get(&window); ASSERT_NE(nullptr, window_port_mus); + EXPECT_FALSE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid()); + // A ClientSurfaceEmbedder is only created once there is bounds and a + // FrameSinkId. EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder()); - - // Now that the window has a valid FrameSinkId, it can embed the client in a - // CompositorFrame. - window_tree_client()->OnFrameSinkIdAllocated(server_id(&window), - viz::FrameSinkId(1, 1)); - ClientSurfaceEmbedder* client_surface_embedder = - window_port_mus->client_surface_embedder(); - ASSERT_NE(nullptr, client_surface_embedder); - EXPECT_FALSE(delegate.last_surface_info().is_valid()); - - // When a SurfaceInfo arrives from the window server, we use it as the - // fallback SurfaceInfo. Here we issue the primary SurfaceId back to the - // client lib. This should cause the gutter to go away, eliminating overdraw. - window_tree_client()->OnWindowSurfaceChanged( - server_id(&window), - viz::SurfaceInfo(window_port_mus->PrimarySurfaceIdForTesting(), 1.0f, - gfx::Size(100, 100))); - EXPECT_TRUE(delegate.last_surface_info().is_valid()); - EXPECT_EQ(delegate.last_surface_info().id(), - window_port_mus->PrimarySurfaceIdForTesting()); -} - -// Verifies that EMBED_IN_OWNER windows do not gutter. -TEST_P(WindowTreeClientTestSurfaceSync, NoEmbedInOwnerGutter) { - FirstSurfaceActivationWindowDelegate delegate; - Window window(&delegate); - // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds - // when their sizes change. - window.SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); - window.Init(ui::LAYER_NOT_DRAWN); - - // The window will allocate a viz::LocalSurfaceId once it has a bounds. - WindowMus* window_mus = WindowMus::Get(&window); - ASSERT_NE(nullptr, window_mus); - EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid()); gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100)); ASSERT_NE(new_bounds, window.bounds()); window.SetBounds(new_bounds); EXPECT_EQ(new_bounds, window.bounds()); - EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid()); + EXPECT_TRUE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid()); - // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and - // a valid FrameSinkId. - WindowPortMus* window_port_mus = WindowPortMus::Get(&window); - ASSERT_NE(nullptr, window_port_mus); - EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder()); - - // Now that the window has a valid FrameSinkId, it can embed the client in a - // CompositorFrame. - window_tree_client()->OnFrameSinkIdAllocated(server_id(&window), - viz::FrameSinkId(1, 1)); + // Once the bounds have been set, the ClientSurfaceEmbedder should be created. ClientSurfaceEmbedder* client_surface_embedder = window_port_mus->client_surface_embedder(); ASSERT_NE(nullptr, client_surface_embedder); - EXPECT_FALSE(delegate.last_surface_info().is_valid()); EXPECT_EQ(nullptr, client_surface_embedder->BottomGutterForTesting()); EXPECT_EQ(nullptr, client_surface_embedder->RightGutterForTesting()); @@ -410,11 +330,8 @@ TEST_P(WindowTreeClientTestSurfaceSync, NoEmbedInOwnerGutter) { TEST_P(WindowTreeClientTestSurfaceSync, SetBoundsLocalSurfaceIdChanges) { ASSERT_EQ(base::nullopt, window_tree()->last_local_surface_id()); Window window(nullptr); - // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds - // when their sizes change. - window.SetProperty(aura::client::kEmbedType, - aura::client::WindowEmbedType::EMBED_IN_OWNER); window.Init(ui::LAYER_NOT_DRAWN); + WindowPortMusTestHelper(&window).SimulateEmbedding(); // Resize the window and verify that we've allocated a viz::LocalSurfaceId. const gfx::Rect new_bounds(0, 0, 100, 100); @@ -800,6 +717,26 @@ TEST_F(WindowTreeClientTest, SetStringProperty) { EXPECT_EQ(example, *root_window()->GetProperty(client::kNameKey)); } +TEST_F(WindowTreeClientTest, SetWindowPointerProperty) { + PropertyConverter* property_converter = GetPropertyConverter(); + RegisterTestProperties(property_converter); + + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.Show(); + root_window()->SetProperty(kTestPropertyKey4, &window); + base::Optional> value = + window_tree()->GetLastPropertyValue(); + ASSERT_TRUE(value.has_value()); + EXPECT_EQ(WindowMus::Get(&window)->server_id(), + mojo::ConvertTo(*value)); + window_tree()->AckAllChanges(); + + root_window()->ClearProperty(kTestPropertyKey4); + value = window_tree()->GetLastPropertyValue(); + EXPECT_FALSE(value.has_value()); +} + // Verifies visible is reverted if the server replied that the change failed. TEST_F(WindowTreeClientTest, SetVisibleFailed) { const bool original_visible = root_window()->TargetVisibility(); @@ -1010,13 +947,13 @@ TEST_F(WindowTreeClientTest, InputEventPointerEvent) { const gfx::Point event_location(2, 3); const uint32_t event_id = 1; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event( - ui::ET_POINTER_MOVED, event_location, gfx::Point(), ui::EF_NONE, 0, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); + ui::MouseEvent mouse_event( + ui::ET_MOUSE_MOVED, event_location, event_location, ui::EventTimeForNow(), + ui::EF_NONE, ui::EF_NONE, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0)); window_tree_client()->OnWindowInputEvent(event_id, server_id(&child), window_tree_host.display_id(), - ui::Event::Clone(pointer_event), 0); + ui::Event::Clone(mouse_event), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ws::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); @@ -1046,13 +983,13 @@ TEST_F(WindowTreeClientTest, InputEventPen) { const gfx::Point event_location(2, 3); const uint32_t event_id = 1; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event( - ui::ET_POINTER_DOWN, event_location, gfx::Point(), ui::EF_NONE, 0, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_PEN, 0), - ui::EventTimeForNow()); + ui::MouseEvent mouse_event( + ui::ET_MOUSE_PRESSED, event_location, event_location, + ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_PEN, 0)); window_tree_client()->OnWindowInputEvent(event_id, server_id(&child), window_tree_host.display_id(), - ui::Event::Clone(pointer_event), 0); + ui::Event::Clone(mouse_event), 0); // Pen event was handled. EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); @@ -1346,14 +1283,13 @@ TEST_F(WindowTreeClientTest, InputMouseEventNoWindow) { const gfx::Point event_location(2, 3); uint32_t event_id = 1; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event_down( - ui::ET_POINTER_DOWN, event_location, event_location, - ui::EF_LEFT_MOUSE_BUTTON, 0, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), - ui::EventTimeForNow()); + ui::MouseEvent mouse_event_down( + ui::ET_MOUSE_PRESSED, event_location, event_location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0)); window_tree_client()->OnWindowInputEvent( event_id, server_id(&child), window_tree_host.display_id(), - ui::Event::Clone(pointer_event_down), 0); + ui::Event::Clone(mouse_event_down), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ws::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); @@ -1366,14 +1302,13 @@ TEST_F(WindowTreeClientTest, InputMouseEventNoWindow) { const gfx::Point event_location1(4, 5); event_id = 2; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event_up( - ui::ET_POINTER_UP, event_location1, event_location, - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), - ui::EventTimeForNow()); - window_tree_client()->OnWindowInputEvent( - event_id, kInvalidServerId, window_tree_host.display_id(), - ui::Event::Clone(pointer_event_up), 0); + ui::MouseEvent mouse_event_up( + ui::ET_MOUSE_RELEASED, event_location1, event_location, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0)); + window_tree_client()->OnWindowInputEvent(event_id, kInvalidServerId, + window_tree_host.display_id(), + ui::Event::Clone(mouse_event_up), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); // WindowTreeClient::OnWindowInputEvent cannot find a target window with // kInvalidServerId but should use the event to update event states kept in @@ -1410,13 +1345,12 @@ TEST_F(WindowTreeClientTest, InputTouchEventNoWindow) { const gfx::Point event_location(2, 3); uint32_t event_id = 1; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event_down( - ui::ET_POINTER_DOWN, event_location, gfx::Point(), 0, 0, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0), - ui::EventTimeForNow()); + ui::TouchEvent touch_event_down( + ui::ET_TOUCH_PRESSED, event_location, ui::EventTimeForNow(), + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); window_tree_client()->OnWindowInputEvent( event_id, server_id(&child), window_tree_host.display_id(), - ui::Event::Clone(pointer_event_down), 0); + ui::Event::Clone(touch_event_down), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ws::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); @@ -1426,13 +1360,12 @@ TEST_F(WindowTreeClientTest, InputTouchEventNoWindow) { event_id = 2; window_delegate.set_event_id(event_id); - ui::PointerEvent pointer_event_up( - ui::ET_POINTER_UP, event_location, gfx::Point(), 0, 0, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0), - ui::EventTimeForNow()); - window_tree_client()->OnWindowInputEvent( - event_id, kInvalidServerId, window_tree_host.display_id(), - ui::Event::Clone(pointer_event_up), 0); + ui::TouchEvent touch_event_up( + ui::ET_TOUCH_RELEASED, event_location, ui::EventTimeForNow(), + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); + window_tree_client()->OnWindowInputEvent(event_id, kInvalidServerId, + window_tree_host.display_id(), + ui::Event::Clone(touch_event_up), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); // WindowTreeClient::OnWindowInputEvent cannot find a target window with // kInvalidServerId but should use the event to update event states kept in @@ -1543,12 +1476,12 @@ TEST_F(WindowTreeClientPointerObserverTest, window_tree_client_impl()->StartPointerWatcher(false /* want_moves */); // Simulate the server dispatching an event that also matched the observer. - std::unique_ptr pointer_event_down(new ui::PointerEvent( - ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 0, + ui::TouchEvent touch_event_down( + ui::ET_TOUCH_PRESSED, gfx::Point(), ui::EventTimeForNow(), ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1), - base::TimeTicks::Now())); - window_tree_client()->OnWindowInputEvent(1, server_id(top_level), 0, - std::move(pointer_event_down), true); + ui::EF_CONTROL_DOWN); + window_tree_client()->OnWindowInputEvent( + 1, server_id(top_level), 0, ui::Event::Clone(touch_event_down), true); // Delegate sensed the event. const ui::Event* last_event = last_event_observed(); diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc index 4714427d756..47ff9645626 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.cc +++ b/chromium/ui/aura/mus/window_tree_host_mus.cc @@ -146,10 +146,6 @@ void WindowTreeHostMus::StackAtTop() { delegate_->OnWindowTreeHostStackAtTop(this); } -void WindowTreeHostMus::PerformWmAction(const std::string& action) { - delegate_->OnWindowTreeHostPerformWmAction(this, action); -} - void WindowTreeHostMus::PerformWindowMove( ws::mojom::MoveLoopSource mus_source, const gfx::Point& cursor_location, diff --git a/chromium/ui/aura/mus/window_tree_host_mus.h b/chromium/ui/aura/mus/window_tree_host_mus.h index c023265a716..eaafd008187 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.h +++ b/chromium/ui/aura/mus/window_tree_host_mus.h @@ -68,9 +68,6 @@ class AURA_EXPORT WindowTreeHostMus : public WindowTreeHostPlatform, // windows which we might not own. void StackAtTop(); - // Requests that the window manager perform |action| on the window. - void PerformWmAction(const std::string& action); - // Tells the window manager to take control of moving the window. Returns // true if the move wasn't canceled. void PerformWindowMove(ws::mojom::MoveLoopSource mus_source, diff --git a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h index 636d7018f35..0c17643cca5 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h +++ b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h @@ -54,11 +54,6 @@ class AURA_EXPORT WindowTreeHostMusDelegate { virtual void OnWindowTreeHostStackAtTop( WindowTreeHostMus* window_tree_host) = 0; - // Called to signal to the window manager to take an action. - virtual void OnWindowTreeHostPerformWmAction( - WindowTreeHostMus* window_tree_host, - const std::string& action) = 0; - // Called to start a move loop, where the window manager will take over // moving a window during a drag. virtual void OnWindowTreeHostPerformWindowMove( diff --git a/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc b/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc index 39a7302ed1d..90c5bc823a2 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc +++ b/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc @@ -23,30 +23,4 @@ TEST_F(WindowTreeHostMusTest, UpdateClientArea) { EXPECT_EQ(new_insets, window_tree()->last_client_area()); } -TEST_F(WindowTreeHostMusTest, SetHitTestMask) { - std::unique_ptr window_tree_host_mus = - std::make_unique( - CreateInitParamsForTopLevel(window_tree_client_impl())); - - EXPECT_FALSE(window_tree()->last_hit_test_mask().has_value()); - gfx::Rect mask(10, 10, 10, 10); - WindowPortMus::Get(window_tree_host_mus->window())->SetHitTestMask(mask); - ASSERT_TRUE(window_tree()->last_hit_test_mask().has_value()); - EXPECT_EQ(mask, window_tree()->last_hit_test_mask()); - - WindowPortMus::Get(window_tree_host_mus->window()) - ->SetHitTestMask(base::nullopt); - ASSERT_FALSE(window_tree()->last_hit_test_mask().has_value()); -} - -TEST_F(WindowTreeHostMusTest, PerformWmAction) { - std::unique_ptr window_tree_host_mus = - std::make_unique( - CreateInitParamsForTopLevel(window_tree_client_impl())); - - const std::string test_action("test-action"); - window_tree_host_mus->PerformWmAction(test_action); - EXPECT_EQ(test_action, window_tree()->last_wm_action()); -} - } // namespace aura diff --git a/chromium/ui/aura/screen_ozone.h b/chromium/ui/aura/screen_ozone.h index 132ea591702..7c26999f515 100644 --- a/chromium/ui/aura/screen_ozone.h +++ b/chromium/ui/aura/screen_ozone.h @@ -5,6 +5,8 @@ #ifndef UI_AURA_SCREEN_OZONE_H_ #define UI_AURA_SCREEN_OZONE_H_ +#include + #include "base/macros.h" #include "ui/aura/aura_export.h" #include "ui/display/screen.h" diff --git a/chromium/ui/aura/test/ui_controls_factory_ozone.cc b/chromium/ui/aura/test/ui_controls_factory_ozone.cc index 8538cfb0893..24ef109d467 100644 --- a/chromium/ui/aura/test/ui_controls_factory_ozone.cc +++ b/chromium/ui/aura/test/ui_controls_factory_ozone.cc @@ -6,12 +6,12 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" +#include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/event_injector.mojom.h" -#include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/test/aura_test_utils.h" @@ -19,6 +19,8 @@ #include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/events_test_utils.h" @@ -122,16 +124,19 @@ class UIControlsOzone : public ui_controls::UIControlsAura { bool SendMouseMoveNotifyWhenDone(long screen_x, long screen_y, base::OnceClosure closure) override { - gfx::Point root_location(screen_x, screen_y); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(host_->window()); - if (screen_position_client) { - screen_position_client->ConvertPointFromScreen(host_->window(), - &root_location); + // The location needs to be in display's coordinate. + gfx::Point display_location(screen_x, screen_y); + display::Display display; + if (!display::Screen::GetScreen()->GetDisplayWithDisplayId( + host_->GetDisplayId(), &display)) { + LOG(ERROR) << "Failed to see the display for " << host_->GetDisplayId(); + return false; } + display_location -= display.bounds().OffsetFromOrigin(); - gfx::Point host_location = root_location; + gfx::Point host_location = display_location; host_->ConvertDIPToPixels(&host_location); + last_mouse_location_ = host_location; ui::EventType event_type; @@ -155,16 +160,24 @@ class UIControlsOzone : public ui_controls::UIControlsAura { int button_state, base::OnceClosure closure, int accelerator_state) override { - gfx::Point root_location = host_->window()->env()->last_mouse_location(); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(host_->window()); - if (screen_position_client) { - screen_position_client->ConvertPointFromScreen(host_->window(), - &root_location); - } + gfx::Point host_location; + if (last_mouse_location_.has_value()) { + host_location = last_mouse_location_.value(); + } else { + // The location needs to be in display's coordinate. + gfx::Point display_location = + host_->window()->env()->last_mouse_location(); + display::Display display; + if (!display::Screen::GetScreen()->GetDisplayWithDisplayId( + host_->GetDisplayId(), &display)) { + LOG(ERROR) << "Failed to see the display for " << host_->GetDisplayId(); + return false; + } + display_location -= display.bounds().OffsetFromOrigin(); - gfx::Point host_location = root_location; - host_->ConvertDIPToPixels(&host_location); + host_location = display_location; + host_->ConvertDIPToPixels(&host_location); + } int changed_button_flag = 0; @@ -219,18 +232,8 @@ class UIControlsOzone : public ui_controls::UIControlsAura { private: void SendEventToSink(ui::Event* event, base::OnceClosure closure) { if (host_->window()->env()->mode() == aura::Env::Mode::MUS) { - std::unique_ptr event_to_send; - if (event->IsMouseEvent()) { - // WindowService expects MouseEvents as PointerEvents. - // See http://crbug.com/617222. - event_to_send = - std::make_unique(*event->AsMouseEvent()); - } else { - event_to_send = ui::Event::Clone(*event); - } - GetEventInjector()->InjectEvent( - host_->GetDisplayId(), std::move(event_to_send), + host_->GetDisplayId(), ui::Event::Clone(*event), base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure))); return; } @@ -311,6 +314,11 @@ class UIControlsOzone : public ui_controls::UIControlsAura { WindowTreeHost* host_; ws::mojom::EventInjectorPtr event_injector_; + // The mouse location for the last SendMouseEventsNotifyWhenDone call. This is + // used rather than Env::last_mouse_location() as Env::last_mouse_location() + // is updated asynchronously with mus. + base::Optional last_mouse_location_; + // Mask of the mouse buttons currently down. This is static as it needs to // track the state globally for all displays. A UIControlsOzone instance is // created for each display host. diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index 3ebec72c8db..18829840094 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -92,7 +92,7 @@ Window::Window(WindowDelegate* delegate, } Window::~Window() { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); if (layer()->owner() == this) layer()->CompleteAllAnimations(); @@ -160,7 +160,7 @@ Window::~Window() { } void Window::Init(ui::LayerType layer_type) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); if (!port_owner_) { port_owner_ = env_->CreateWindowPort(this); @@ -285,7 +285,7 @@ gfx::Rect Window::GetBoundsInScreen() const { } void Window::SetTransform(const gfx::Transform& transform) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); for (WindowObserver& observer : observers_) observer.OnWindowTargetTransformChanging(this, transform); layer()->SetTransform(transform); @@ -308,7 +308,11 @@ void Window::SetLayoutManager(LayoutManager* layout_manager) { std::unique_ptr Window::SetEventTargeter( std::unique_ptr targeter) { std::unique_ptr old_targeter = std::move(targeter_); + if (old_targeter) + old_targeter->OnInstalled(nullptr); targeter_ = std::move(targeter); + if (targeter_) + targeter_->OnInstalled(this); return old_targeter; } @@ -369,7 +373,7 @@ void Window::StackChildBelow(Window* child, Window* target) { } void Window::AddChild(Window* child) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); DCHECK(layer()) << "Parent has not been Init()ed yet."; DCHECK(child->layer()) << "Child has not been Init()ed yt."; @@ -411,7 +415,7 @@ void Window::AddChild(Window* child) { } void Window::RemoveChild(Window* child) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); WindowObserver::HierarchyChangeParams params; params.target = child; @@ -547,6 +551,20 @@ bool Window::HasObserver(const WindowObserver* observer) const { } void Window::SetEventTargetingPolicy(ws::mojom::EventTargetingPolicy policy) { +#if DCHECK_IS_ON() + const bool old_window_accepts_events = + (event_targeting_policy_ == + ws::mojom::EventTargetingPolicy::TARGET_ONLY) || + (event_targeting_policy_ == + ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + const bool new_window_accepts_events = + (policy == ws::mojom::EventTargetingPolicy::TARGET_ONLY) || + (policy == ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + if (new_window_accepts_events != old_window_accepts_events) { + DCHECK(!created_layer_tree_frame_sink_); + } +#endif + if (event_targeting_policy_ == policy) return; @@ -833,7 +851,7 @@ void Window::SetVisible(bool visible) { if (visible == layer()->GetTargetVisibility()) return; // No change. - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); for (WindowObserver& observer : observers_) observer.OnWindowVisibilityChanging(this, visible); @@ -886,7 +904,7 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) { if (child->OwnsLayer()) layer()->Remove(child->layer()); child->parent_ = NULL; - Windows::iterator i = std::find(children_.begin(), children_.end(), child); + auto i = std::find(children_.begin(), children_.end(), child); DCHECK(i != children_.end()); children_.erase(i); child->OnParentChanged(); @@ -908,7 +926,7 @@ void Window::StackChildRelativeTo(Window* child, DCHECK_EQ(this, child->parent()); DCHECK_EQ(this, target->parent()); - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); client::WindowStackingClient* stacking_client = client::GetWindowStackingClient(); @@ -1074,9 +1092,7 @@ bool Window::CleanupGestureState() { bool state_modified = false; state_modified |= env_->gesture_recognizer()->CancelActiveTouches(this); state_modified |= env_->gesture_recognizer()->CleanupStateForConsumer(this); - for (Window::Windows::iterator iter = children_.begin(); - iter != children_.end(); - ++iter) { + for (auto iter = children_.begin(); iter != children_.end(); ++iter) { state_modified |= (*iter)->CleanupGestureState(); } return state_modified; @@ -1087,6 +1103,7 @@ std::unique_ptr Window::CreateLayerTreeFrameSink() { DCHECK(frame_sink_id_.is_valid()); DCHECK(embeds_external_client_); DCHECK(GetLocalSurfaceId().is_valid()); + created_layer_tree_frame_sink_ = true; return sink; } @@ -1133,6 +1150,8 @@ const viz::FrameSinkId& Window::GetFrameSinkId() const { } void Window::SetEmbedFrameSinkId(const viz::FrameSinkId& frame_sink_id) { + UnregisterFrameSinkId(); + DCHECK(frame_sink_id.is_valid()); frame_sink_id_ = frame_sink_id; embeds_external_client_ = true; @@ -1143,6 +1162,10 @@ bool Window::IsEmbeddingClient() const { return embeds_external_client_; } +void Window::TrackOcclusionState() { + env_->GetWindowOcclusionTracker()->Track(this); +} + bool Window::RequiresDoubleTapGestureEvents() const { return delegate_ && delegate_->RequiresDoubleTapGestureEvents(); } @@ -1160,7 +1183,7 @@ void Window::OnPaintLayer(const ui::PaintContext& context) { void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds, ui::PropertyChangeReason reason) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); bounds_ = layer()->bounds(); @@ -1177,13 +1200,13 @@ void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds, } void Window::OnLayerOpacityChanged(ui::PropertyChangeReason reason) { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); for (WindowObserver& observer : observers_) observer.OnWindowOpacitySet(this, reason); } void Window::OnLayerAlphaShapeChanged() { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); for (WindowObserver& observer : observers_) observer.OnWindowAlphaShapeSet(this); } @@ -1191,7 +1214,7 @@ void Window::OnLayerAlphaShapeChanged() { void Window::OnLayerTransformed(const gfx::Transform& old_transform, ui::PropertyChangeReason reason) { port_->OnDidChangeTransform(old_transform, layer()->transform()); - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); for (WindowObserver& observer : observers_) observer.OnWindowTransformed(this, reason); } @@ -1246,8 +1269,18 @@ void Window::ConvertEventToTarget(ui::EventTarget* target, static_cast(target)); } +gfx::PointF Window::GetScreenLocationF(const ui::LocatedEvent& event) const { + DCHECK_EQ(this, event.target()); + gfx::PointF screen_location(event.root_location_f()); + const Window* root = GetRootWindow(); + auto* screen_position_client = aura::client::GetScreenPositionClient(root); + if (screen_position_client) + screen_position_client->ConvertPointToScreen(root, &screen_location); + return screen_location; +} + std::unique_ptr Window::RecreateLayer() { - WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_); ui::LayerAnimator* const animator = layer()->GetAnimator(); const bool was_animating_opacity = @@ -1307,6 +1340,7 @@ void Window::RegisterFrameSinkId() { if (auto* compositor = layer()->GetCompositor()) { compositor->AddChildFrameSink(frame_sink_id_); registered_frame_sink_id_ = true; + port_->RegisterFrameSinkId(frame_sink_id_); } } @@ -1314,6 +1348,7 @@ void Window::UnregisterFrameSinkId() { if (!registered_frame_sink_id_) return; registered_frame_sink_id_ = false; + port_->UnregisterFrameSinkId(frame_sink_id_); if (auto* compositor = layer()->GetCompositor()) compositor->RemoveChildFrameSink(frame_sink_id_); } diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index 18a6a3601e6..6175dcd10ba 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -95,8 +95,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate, STACK_BELOW }; enum class OcclusionState { - // The window's occlusion state isn't tracked - // (WindowOcclusionTracker::Track) or hasn't been computed yet. + // The window's occlusion state isn't tracked (Window::TrackOcclusionState) + // or hasn't been computed yet. UNKNOWN, // The window or one of its descendants IsVisible() [1] and: // - Its bounds aren't completely covered by fully opaque windows [2], or, @@ -194,9 +194,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // whether Show() without a Hide() has been invoked. bool TargetVisibility() const { return visible_; } // Returns the occlusion state of this window. Is UNKNOWN if the occlusion - // state of this window isn't tracked (WindowOcclusionTracker::Track) or + // state of this window isn't tracked (Window::TrackOcclusionState) or // hasn't been computed yet. Is stale if called within the scope of a - // WindowOcclusionTracker::ScopedPauseOcclusionTracking. + // WindowOcclusionTracker::ScopedPause. OcclusionState occlusion_state() const { return occlusion_state_; } // Returns the window's bounds in root window's coordinates. @@ -221,6 +221,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, std::unique_ptr SetEventTargeter( std::unique_ptr targeter); WindowTargeter* targeter() { return targeter_.get(); } + const WindowTargeter* targeter() const { return targeter_.get(); } // Changes the bounds of the window. If present, the window's parent's // LayoutManager may adjust the bounds. @@ -430,6 +431,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Returns whether this window is embedding another client. bool IsEmbeddingClient() const; + // Starts occlusion state tracking. + void TrackOcclusionState(); + Env* env() { return env_; } const Env* env() const { return env_; } @@ -558,6 +562,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, ui::EventTargeter* GetEventTargeter() override; void ConvertEventToTarget(ui::EventTarget* target, ui::LocatedEvent* event) override; + gfx::PointF GetScreenLocationF(const ui::LocatedEvent& event) const override; // Updates the layer name based on the window's name and id. void UpdateLayerName(); @@ -572,6 +577,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate, bool registered_frame_sink_id_ = false; bool disable_frame_sink_id_registration_ = false; + bool created_layer_tree_frame_sink_ = false; + // Window owns its corresponding WindowPort, but the ref is held as a raw // pointer in |port_| so that it can still be accessed during destruction. // This is important as deleting the WindowPort may result in trying to lookup diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h index fae8ea9c7ee..7911cb92df7 100644 --- a/chromium/ui/aura/window_delegate.h +++ b/chromium/ui/aura/window_delegate.h @@ -24,10 +24,6 @@ namespace ui { class PaintContext; } -namespace viz { -class SurfaceInfo; -} - namespace aura { // Delegate interface for aura::Window. @@ -106,10 +102,6 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler { // above returns true. virtual void GetHitTestMask(gfx::Path* mask) const = 0; - // Called when a child submits a CompositorFrame to a surface with the given - // |surface_info| for the first time. - virtual void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {} - // Returns whether the window wants to receive and handle double tap gesture // events. Defaults to false. virtual bool RequiresDoubleTapGestureEvents() const; diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc index b5ce6203d1a..f6ea825d7e2 100644 --- a/chromium/ui/aura/window_event_dispatcher.cc +++ b/chromium/ui/aura/window_event_dispatcher.cc @@ -836,15 +836,19 @@ ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() { } if (held_move_event_) { + // |held_move_event_| should be cleared here. Some event handler can + // create its own run loop on an event (e.g. WindowMove loop for + // tab-dragging), which means the other move events need to be processed + // before this OnEventFromSource() finishes. See also b/119260190. + std::unique_ptr event = std::move(held_move_event_); + // If a mouse move has been synthesized, the target location is suspect, // so drop the held mouse event. - if (held_move_event_->IsTouchEvent() || - (held_move_event_->IsMouseEvent() && !synthesize_mouse_move_)) { - dispatching_held_event_ = held_move_event_.get(); - dispatch_details = OnEventFromSource(held_move_event_.get()); + if (event->IsTouchEvent() || + (event->IsMouseEvent() && !synthesize_mouse_move_)) { + dispatching_held_event_ = event.get(); + dispatch_details = OnEventFromSource(event.get()); } - if (!dispatch_details.dispatcher_destroyed) - held_move_event_.reset(); } if (!dispatch_details.dispatcher_destroyed) { diff --git a/chromium/ui/aura/window_event_dispatcher.h b/chromium/ui/aura/window_event_dispatcher.h index 5a9e099cf7a..c66b2a1d2a7 100644 --- a/chromium/ui/aura/window_event_dispatcher.h +++ b/chromium/ui/aura/window_event_dispatcher.h @@ -64,6 +64,8 @@ class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor, WindowEventDispatcher(WindowTreeHost* host, bool are_events_in_pixels); ~WindowEventDispatcher() override; + bool are_events_in_pixels() const { return are_events_in_pixels_; } + // Stops dispatching/synthesizing mouse events. void Shutdown(); diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc index 27deae028d1..fc0967392b9 100644 --- a/chromium/ui/aura/window_event_dispatcher_unittest.cc +++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc @@ -14,6 +14,7 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -1010,9 +1011,6 @@ class HoldPointerOnScrollHandler : public ui::test::TestEventHandler { // Tests that touch-move events don't contribute to an in-progress scroll // gesture if touch-move events are being held by the dispatcher. TEST_P(WindowEventDispatcherTest, TouchMovesHeldOnScroll) { - // TODO(sky): fails with mus. https://crbug.com/866502 - if (GetParam() == Env::Mode::MUS) - return; EventFilterRecorder recorder; root_window()->AddPreTargetHandler(&recorder); test::TestWindowDelegate delegate; @@ -2179,6 +2177,77 @@ TEST_P(WindowEventDispatcherTest, CaptureWindowDestroyed) { EXPECT_EQ(NULL, capture_window_tracker.capture_window()); } +namespace { + +class RunLoopHandler : public ui::EventHandler { + public: + explicit RunLoopHandler(aura::Window* target) + : run_loop_(base::RunLoop::Type::kNestableTasksAllowed), target_(target) { + target_->AddPreTargetHandler(this); + } + ~RunLoopHandler() override { target_->RemovePreTargetHandler(this); } + int num_scroll_updates() const { return num_scroll_updates_; } + + private: + // ui::EventHandler: + void OnGestureEvent(ui::GestureEvent* event) override { + if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE) + return; + num_scroll_updates_++; + if (running_) { + run_loop_.QuitWhenIdle(); + } else { + running_ = true; + run_loop_.Run(); + } + } + + base::RunLoop run_loop_; + bool running_ = false; + int num_scroll_updates_ = 0; + + aura::Window* target_; + + DISALLOW_COPY_AND_ASSIGN(RunLoopHandler); +}; + +} // namespace + +TEST_P(WindowEventDispatcherTest, HeldTouchMoveWithRunLoop) { + RunLoopHandler handler(root_window()); + + host()->dispatcher()->HoldPointerMoves(); + + gfx::Point point = root_window()->GetBoundsInScreen().CenterPoint(); + ui::TouchEvent ev0(ui::ET_TOUCH_PRESSED, point, ui::EventTimeForNow(), + ui::PointerDetails()); + DispatchEventUsingWindowDispatcher(&ev0); + + point.Offset(10, 10); + ui::TouchEvent ev1(ui::ET_TOUCH_MOVED, point, ui::EventTimeForNow(), + ui::PointerDetails()); + DispatchEventUsingWindowDispatcher(&ev1); + // The move event is held, so SCROLL_UPDATE does not happen yet. + EXPECT_EQ(0, handler.num_scroll_updates()); + + // ReleasePointerMoves() will post DispatchHeldEvent() asynchronously. + host()->dispatcher()->ReleasePointerMoves(); + point.Offset(10, 10); + // Schedule another move event which should cause another SCROLL_UPDATE and + // quit the run_loop within the handler. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindLambdaForTesting([&]() { + ui::TouchEvent ev2(ui::ET_TOUCH_MOVED, point, base::TimeTicks::Now(), + ui::PointerDetails()); + DispatchEventUsingWindowDispatcher(&ev2); + })); + // Wait for both DispatchHeldEvent() and dispatch of |ev2|. + base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle(); + + // Makes sure that the run_loop ran and then ended. + EXPECT_EQ(2, handler.num_scroll_updates()); +} + class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler { public: ExitMessageLoopOnMousePress() {} @@ -2282,7 +2351,9 @@ class WindowEventDispatcherTestInHighDPI : public WindowEventDispatcherTest { }; TEST_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) { - // TODO(sky): fails with mus. https://crbug.com/866502 + // This test is only applicable to LOCAL mode as it's setting a device scale + // factor and expecting events to be transformed while routing the event + // directly through host(). In MUS mode the window-service does the scaling. if (GetParam() == Env::Mode::MUS) return; @@ -2322,9 +2393,12 @@ TEST_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) { } TEST_P(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) { - // TODO(sky): fails with mus. https://crbug.com/866502 + // This test is only applicable to LOCAL mode as it's setting a device scale + // factor and expecting events to be transformed while routing the event + // directly through host(). In MUS mode the window-service does the scaling. if (GetParam() == Env::Mode::MUS) return; + EventFilterRecorder recorder; root_window()->AddPreTargetHandler(&recorder); test::TestWindowDelegate delegate; @@ -2394,9 +2468,12 @@ class TriggerNestedLoopOnRightMousePress : public ui::test::TestEventHandler { // correctly. TEST_P(WindowEventDispatcherTestInHighDPI, EventsTransformedInRepostedEventTriggeredNestedLoop) { - // TODO(sky): fails with mus. https://crbug.com/866502 + // This test is only applicable to LOCAL mode as it's setting a device scale + // factor and expecting events to be transformed while routing the event + // directly through host(). In MUS mode the window-service does the scaling. if (GetParam() == Env::Mode::MUS) return; + std::unique_ptr window(CreateNormalWindow(1, root_window(), NULL)); // Make sure the window is visible. RunAllPendingInMessageLoop(); @@ -2851,7 +2928,9 @@ TEST_P(WindowEventDispatcherTest, TouchMovesMarkedWhenCausingScroll) { // cursor's position in root coordinates has changed (e.g. when the displays's // scale factor changed). Test that hover effects are properly updated. TEST_P(WindowEventDispatcherTest, OnCursorMovedToRootLocationUpdatesHover) { - // TODO(sky): fails with mus. https://crbug.com/866502 + // This test is only applicable to LOCAL mode as it's setting a device scale + // factor and expecting events to be transformed while routing the event + // directly through host(). In MUS mode the window-service does the scaling. if (GetParam() == Env::Mode::MUS) return; diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc index 89f7a5b412f..16a1d228990 100644 --- a/chromium/ui/aura/window_occlusion_tracker.cc +++ b/chromium/ui/aura/window_occlusion_tracker.cc @@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRegion.h" +#include "ui/aura/env.h" #include "ui/aura/window_tracker.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/transform.h" @@ -32,10 +33,6 @@ constexpr ui::LayerAnimationElement::AnimatableProperties // RenderWidgetHostViewAura. https://crbug.com/827268 constexpr int kMaxRecomputeOcclusion = 3; -WindowOcclusionTracker* g_tracker = nullptr; - -int g_num_pause_occlusion_tracking = 0; - bool WindowOrParentHasShape(Window* window) { if (window->layer()->alpha_shape()) return true; @@ -112,46 +109,36 @@ bool OcclusionStatesMatch( } // namespace -WindowOcclusionTracker::ScopedPauseOcclusionTracking:: - ScopedPauseOcclusionTracking() { - ++g_num_pause_occlusion_tracking; +WindowOcclusionTracker::ScopedPause::ScopedPause(Env* env) + : tracker_(env->GetWindowOcclusionTracker()) { + ++tracker_->num_pause_occlusion_tracking_; } -WindowOcclusionTracker::ScopedPauseOcclusionTracking:: - ~ScopedPauseOcclusionTracking() { - --g_num_pause_occlusion_tracking; - DCHECK_GE(g_num_pause_occlusion_tracking, 0); - if (g_tracker) - g_tracker->MaybeComputeOcclusion(); +WindowOcclusionTracker::ScopedPause::~ScopedPause() { + --tracker_->num_pause_occlusion_tracking_; + DCHECK_GE(tracker_->num_pause_occlusion_tracking_, 0); + tracker_->MaybeComputeOcclusion(); } void WindowOcclusionTracker::Track(Window* window) { DCHECK(window); DCHECK(window != window->GetRootWindow()); - if (!g_tracker) - g_tracker = new WindowOcclusionTracker(); - - auto insert_result = g_tracker->tracked_windows_.insert( - {window, Window::OcclusionState::UNKNOWN}); + auto insert_result = + tracked_windows_.insert({window, Window::OcclusionState::UNKNOWN}); DCHECK(insert_result.second); - if (!window->HasObserver(g_tracker)) - window->AddObserver(g_tracker); + if (!window_observer_.IsObserving(window)) + window_observer_.Add(window); if (window->GetRootWindow()) - g_tracker->TrackedWindowAddedToRoot(window); + TrackedWindowAddedToRoot(window); } WindowOcclusionTracker::WindowOcclusionTracker() = default; WindowOcclusionTracker::~WindowOcclusionTracker() = default; -WindowOcclusionTracker* WindowOcclusionTracker::GetInstance() { - DCHECK(g_tracker); - return g_tracker; -} - void WindowOcclusionTracker::MaybeComputeOcclusion() { - if (g_num_pause_occlusion_tracking || + if (num_pause_occlusion_tracking_ || num_times_occlusion_recomputed_in_current_step_ != 0) { return; } @@ -459,9 +446,10 @@ void WindowOcclusionTracker::TrackedWindowRemovedFromRoot(Window* window) { void WindowOcclusionTracker::RemoveObserverFromWindowAndDescendants( Window* window) { if (WindowIsTracked(window)) { - DCHECK(window->HasObserver(this)); + DCHECK(window_observer_.IsObserving(window)); } else { - window->RemoveObserver(this); + if (window_observer_.IsObserving(window)) + window_observer_.Remove(window); window->layer()->GetAnimator()->RemoveObserver(this); animated_windows_.erase(window); } @@ -470,10 +458,12 @@ void WindowOcclusionTracker::RemoveObserverFromWindowAndDescendants( } void WindowOcclusionTracker::AddObserverToWindowAndDescendants(Window* window) { - if (WindowIsTracked(window)) - DCHECK(window->HasObserver(this)); - else - window->AddObserver(this); + if (WindowIsTracked(window)) { + DCHECK(window_observer_.IsObserving(window)); + } else { + DCHECK(!window_observer_.IsObserving(window)); + window_observer_.Add(window); + } for (Window* child_window : window->children()) AddObserverToWindowAndDescendants(child_window); } @@ -498,7 +488,7 @@ void WindowOcclusionTracker::OnWindowHierarchyChanged( Window* const window = params.target; Window* const root_window = window->GetRootWindow(); if (root_window && base::ContainsKey(root_windows_, root_window) && - !window->HasObserver(this)) { + !window_observer_.IsObserving(window)) { AddObserverToWindowAndDescendants(window); } } @@ -582,6 +572,7 @@ void WindowOcclusionTracker::OnWindowStackingChanged(Window* window) { void WindowOcclusionTracker::OnWindowDestroyed(Window* window) { DCHECK(!window->GetRootWindow() || (window == window->GetRootWindow())); tracked_windows_.erase(window); + window_observer_.Remove(window); // Animations should be completed or aborted before a window is destroyed. DCHECK(!window->layer()->GetAnimator()->IsAnimatingOnePropertyOf( kSkipWindowWhenPropertiesAnimated)); diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h index 2e6d557b31b..2b546a5a8b6 100644 --- a/chromium/ui/aura/window_occlusion_tracker.h +++ b/chromium/ui/aura/window_occlusion_tracker.h @@ -5,9 +5,12 @@ #ifndef UI_AURA_WINDOW_OCCLUSION_TRACKER_H_ #define UI_AURA_WINDOW_OCCLUSION_TRACKER_H_ +#include + #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/macros.h" +#include "base/scoped_observer.h" #include "ui/aura/aura_export.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" @@ -26,10 +29,12 @@ namespace test { class WindowOcclusionTrackerTestApi; } +class Env; + // Notifies tracked Windows when their occlusion state change. // // To start tracking the occlusion state of a Window, call -// WindowOcclusionTracker::Track(). +// aura::Window::TrackOcclusionState() // // A Window is occluded if its bounds and transform are not animated and one of // these conditions is true: @@ -43,22 +48,25 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, public: // Prevents window occlusion state computations within its scope. If an event // that could cause window occlusion states to change occurs within the scope - // of a ScopedPauseOcclusionTracking, window occlusion state computations are - // delayed until all ScopedPauseOcclusionTracking objects have been destroyed. - class AURA_EXPORT ScopedPauseOcclusionTracking { + // of a ScopedPause, window occlusion state computations are delayed until all + // ScopedPause objects have been destroyed. + class AURA_EXPORT ScopedPause { public: - ScopedPauseOcclusionTracking(); - ~ScopedPauseOcclusionTracking(); + explicit ScopedPause(Env* env); + ~ScopedPause(); private: - DISALLOW_COPY_AND_ASSIGN(ScopedPauseOcclusionTracking); + WindowOcclusionTracker* const tracker_; + DISALLOW_COPY_AND_ASSIGN(ScopedPause); }; // Start tracking the occlusion state of |window|. - static void Track(Window* window); + void Track(Window* window); private: friend class test::WindowOcclusionTrackerTestApi; + friend class Env; + friend std::unique_ptr::deleter_type; struct RootWindowState { // Number of Windows whose occlusion state is tracked under this root @@ -72,11 +80,8 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, WindowOcclusionTracker(); ~WindowOcclusionTracker() override; - static WindowOcclusionTracker* GetInstance(); - // Recomputes the occlusion state of tracked windows under roots marked as - // dirty in |root_windows_| if there are no active - // ScopedPauseOcclusionTracking instance. + // dirty in |root_windows_| if there are no active ScopedPause instance. void MaybeComputeOcclusion(); // Recomputes the occlusion state of |window| and its descendants. @@ -211,6 +216,12 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, // recomputed occlusion states. Always 0 when not in MaybeComputeOcclusion(). int num_times_occlusion_recomputed_in_current_step_ = 0; + // Counter of the current occlusion tracking pause. + int num_pause_occlusion_tracking_ = 0; + + // Tracks the observed windows. + ScopedObserver window_observer_{this}; + DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTracker); }; diff --git a/chromium/ui/aura/window_occlusion_tracker_unittest.cc b/chromium/ui/aura/window_occlusion_tracker_unittest.cc index 27caa0959a2..ee9247f9d99 100644 --- a/chromium/ui/aura/window_occlusion_tracker_unittest.cc +++ b/chromium/ui/aura/window_occlusion_tracker_unittest.cc @@ -76,7 +76,7 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase { window->Show(); parent = parent ? parent : root_window(); parent->AddChild(window); - WindowOcclusionTracker::Track(window); + window->TrackOcclusionState(); return window; } @@ -958,9 +958,8 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { } // Verify that the bounds of windows are changed multiple times within the scope -// of a ScopedPauseOcclusionTracking, occlusion states are updated once at the -// end of the scope. -TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { +// of a ScopedPause, occlusion states are updated once at the end of the scope. +TEST_F(WindowOcclusionTrackerTest, ScopedPause) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); delegate_a->set_expectation(Window::OcclusionState::VISIBLE); @@ -977,8 +976,8 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { // Change bounds multiple times. At the end of the scope, expect window a to // be occluded. { - WindowOcclusionTracker::ScopedPauseOcclusionTracking - pause_occlusion_tracking; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking( + root_window()->env()); window_b->SetBounds(window_a->bounds()); window_a->SetBounds(gfx::Rect(0, 10, 5, 5)); window_b->SetBounds(window_a->bounds()); @@ -988,8 +987,8 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { EXPECT_FALSE(delegate_a->is_expecting_call()); } -// Same as the previous test, but with nested ScopedPauseOcclusionTracking. -TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) { +// Same as the previous test, but with nested ScopedPause. +TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); delegate_a->set_expectation(Window::OcclusionState::VISIBLE); @@ -1006,22 +1005,22 @@ TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) { // Change bounds multiple times. At the end of the scope, expect window a to // be occluded. { - WindowOcclusionTracker::ScopedPauseOcclusionTracking - pause_occlusion_tracking_a; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_a( + root_window()->env()); { - WindowOcclusionTracker::ScopedPauseOcclusionTracking - pause_occlusion_tracking_b; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_b( + root_window()->env()); window_b->SetBounds(window_a->bounds()); } { - WindowOcclusionTracker::ScopedPauseOcclusionTracking - pause_occlusion_tracking_c; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_c( + root_window()->env()); window_a->SetBounds(gfx::Rect(0, 10, 5, 5)); } { - WindowOcclusionTracker::ScopedPauseOcclusionTracking - pause_occlusion_tracking_d; + WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_d( + root_window()->env()); window_b->SetBounds(window_a->bounds()); } @@ -1451,7 +1450,7 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate { // Verify that if a window changes its visibility every time it is notified that // its occlusion state changed, a DCHECK occurs. TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) { - test::WindowOcclusionTrackerTestApi test_api; + test::WindowOcclusionTrackerTestApi test_api(root_window()->env()); // Create 2 superposed tracked windows. MockWindowDelegate* delegate_a = new MockWindowDelegate(); @@ -1651,7 +1650,7 @@ class WindowDelegateAddingAndHidingChild : public MockWindowDelegate { // to be recomputed. TEST_F(WindowOcclusionTrackerTest, HideWindowWithHiddenParentOnOcclusionChange) { - test::WindowOcclusionTrackerTestApi test_api; + test::WindowOcclusionTrackerTestApi test_api(root_window()->env()); auto* delegate_a = new WindowDelegateAddingAndHidingChild(this); delegate_a->set_expectation(Window::OcclusionState::VISIBLE); diff --git a/chromium/ui/aura/window_port.cc b/chromium/ui/aura/window_port.cc index a710f70587b..2c3b71651ba 100644 --- a/chromium/ui/aura/window_port.cc +++ b/chromium/ui/aura/window_port.cc @@ -8,6 +8,8 @@ namespace aura { +WindowPort::WindowPort(Type type) : type_(type) {} + // static WindowPort* WindowPort::Get(Window* window) { return window ? window->port_ : nullptr; diff --git a/chromium/ui/aura/window_port.h b/chromium/ui/aura/window_port.h index 99f07292d6f..8e058542b48 100644 --- a/chromium/ui/aura/window_port.h +++ b/chromium/ui/aura/window_port.h @@ -40,8 +40,22 @@ class WindowObserver; // Env::CreateWindowPort() is used to create the WindowPort. class AURA_EXPORT WindowPort { public: + // Corresponds to the concrete implementation of this interface. + enum class Type { + // WindowPortLocal. + kLocal, + + // WindowPortMus. + kMus, + + // WindowPortForShutdown. + kShutdown, + }; + virtual ~WindowPort() {} + Type type() const { return type_; } + // Called from Window::Init(). virtual void OnPreInit(Window* window) = 0; @@ -116,13 +130,23 @@ class AURA_EXPORT WindowPort { // See description of function with same name in transient_window_client. virtual bool ShouldRestackTransientChildren() = 0; + // Called to register/unregister an embedded FramesSinkId. This is only called + // if SetEmbedFrameSinkId() is called on the associated Window. + virtual void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) {} + virtual void UnregisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) {} + protected: + explicit WindowPort(Type type); + // Returns the WindowPort associated with a Window. static WindowPort* Get(Window* window); // Returns the ObserverList of a Window. static base::ObserverList::Unchecked* GetObservers( Window* window); + + private: + const Type type_; }; } // namespace aura diff --git a/chromium/ui/aura/window_port_for_shutdown.cc b/chromium/ui/aura/window_port_for_shutdown.cc index 998764cceed..a30583c51cd 100644 --- a/chromium/ui/aura/window_port_for_shutdown.cc +++ b/chromium/ui/aura/window_port_for_shutdown.cc @@ -9,7 +9,8 @@ namespace aura { -WindowPortForShutdown::WindowPortForShutdown() {} +WindowPortForShutdown::WindowPortForShutdown() + : WindowPort(WindowPort::Type::kShutdown) {} WindowPortForShutdown::~WindowPortForShutdown() {} diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc index 9555a1d7373..19a77c27a51 100644 --- a/chromium/ui/aura/window_targeter.cc +++ b/chromium/ui/aura/window_targeter.cc @@ -10,6 +10,8 @@ #include "ui/aura/client/focus_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" +#include "ui/aura/mus/window_port_mus.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" @@ -20,6 +22,14 @@ #include "ui/events/event_target_iterator.h" namespace aura { +namespace { + +bool AreInsetsEmptyOrPositive(const gfx::Insets& insets) { + return insets.left() >= 0 && insets.right() >= 0 && insets.top() >= 0 && + insets.bottom() >= 0; +} + +} // namespace WindowTargeter::WindowTargeter() {} WindowTargeter::~WindowTargeter() {} @@ -60,11 +70,9 @@ void WindowTargeter::SetInsets(const gfx::Insets& mouse_extend, if (mouse_extend_ == mouse_extend && touch_extend_ == touch_extend) return; - const gfx::Insets last_mouse_extend_ = mouse_extend_; - const gfx::Insets last_touch_extend_ = touch_extend_; mouse_extend_ = mouse_extend; touch_extend_ = touch_extend; - OnSetInsets(last_mouse_extend_, last_touch_extend_); + UpdateMusIfNecessary(); } Window* WindowTargeter::GetPriorityTargetInRootWindow( @@ -125,10 +133,12 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window, if (consumer) return static_cast(consumer); +#if defined(OS_CHROMEOS) // If the initial touch is outside the window's display, target the root. // This is used for bezel gesture events (eg. swiping in from screen edge). display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(root_window); + // The window target may be null, so use the root's ScreenPositionClient. gfx::Point screen_location = event.root_location(); if (client::GetScreenPositionClient(root_window)) { client::GetScreenPositionClient(root_window) @@ -136,6 +146,12 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window, } if (!display.bounds().Contains(screen_location)) return root_window; +#else + // If the initial touch is outside the root window, target the root. + // TODO: this code is likely not necessarily and will be removed. + if (!root_window->bounds().Contains(event.location())) + return root_window; +#endif } return nullptr; @@ -189,6 +205,11 @@ ui::EventTarget* WindowTargeter::FindNextBestTarget( return nullptr; } +void WindowTargeter::OnInstalled(Window* window) { + window_ = window; + UpdateMusIfNecessary(); +} + Window* WindowTargeter::FindTargetForLocatedEvent(Window* window, ui::LocatedEvent* event) { if (!window->parent()) { @@ -278,12 +299,34 @@ bool WindowTargeter::EventLocationInsideBounds( return false; } -bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* window) const { - return true; +bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* w) const { + // window() is null when this is used as the default targeter (by + // WindowEventDispatcher). Insets should never be set in this case, so the + // return should not matter. + if (!window()) { + DCHECK(mouse_extend_.IsEmpty()); + DCHECK(touch_extend_.IsEmpty()); + return false; + } + + // Insets should only apply to the window. Subclasses may enforce other + // policies. + return window() == w; } -void WindowTargeter::OnSetInsets(const gfx::Insets& last_mouse_extend, - const gfx::Insets& last_touch_extend) {} +// TODO: this function should go away once https://crbug.com/879308 is fixed. +void WindowTargeter::UpdateMusIfNecessary() { + if (!window_ || window_->env()->mode() != Env::Mode::MUS) + return; + + // Negative insets are used solely to extend the hit-test region of child + // windows, which is not needed by code using MUS (negative insets are only + // used in the server). + if (AreInsetsEmptyOrPositive(mouse_extend_) && + AreInsetsEmptyOrPositive(touch_extend_)) { + WindowPortMus::Get(window_)->SetHitTestInsets(mouse_extend_, touch_extend_); + } +} Window* WindowTargeter::FindTargetForKeyEvent(Window* window, const ui::KeyEvent& key) { diff --git a/chromium/ui/aura/window_targeter.h b/chromium/ui/aura/window_targeter.h index 5f38c4828f8..3d251b8a37e 100644 --- a/chromium/ui/aura/window_targeter.h +++ b/chromium/ui/aura/window_targeter.h @@ -88,6 +88,12 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter { ui::Event* event) override; protected: + aura::Window* window() { return window_; } + const aura::Window* window() const { return window_; } + + // This is called by Window when the targeter is set on a window. + virtual void OnInstalled(Window* window); + // Same as FindTargetForEvent(), but used for positional events. The location // etc. of |event| are in |window|'s coordinate system. When finding the // target for the event, the targeter can mutate the |event| (e.g. change the @@ -114,22 +120,26 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter { // Returns true if the hit testing (GetHitTestRects()) should use the // extended bounds. - virtual bool ShouldUseExtendedBounds(const aura::Window* window) const; - - // Called after the hit-test area has been extended with SetInsets(). The - // supplied insets are the values before the call to SetInsets(). - virtual void OnSetInsets(const gfx::Insets& last_mouse_extend, - const gfx::Insets& last_touch_extend); + virtual bool ShouldUseExtendedBounds(const aura::Window* w) const; const gfx::Insets& mouse_extend() const { return mouse_extend_; } const gfx::Insets& touch_extend() const { return touch_extend_; } private: + // To call OnInstalled(). + friend class Window; + + void UpdateMusIfNecessary(); + Window* FindTargetForKeyEvent(Window* root_window, const ui::KeyEvent& event); Window* FindTargetForNonKeyEvent(Window* root_window, ui::Event* event); Window* FindTargetForLocatedEventRecursively(Window* root_window, ui::LocatedEvent* event); + // The Window this WindowTargeter is installed on. Null if not attached to a + // Window. + aura::Window* window_ = nullptr; + gfx::Insets mouse_extend_; gfx::Insets touch_extend_; diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc index daeb8529d05..1085c08c32c 100644 --- a/chromium/ui/aura/window_targeter_unittest.cc +++ b/chromium/ui/aura/window_targeter_unittest.cc @@ -8,7 +8,9 @@ #include "base/macros.h" #include "ui/aura/scoped_window_targeter.h" +#include "ui/aura/test/aura_mus_test_base.h" #include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/mus/test_window_tree.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" #include "ui/display/display.h" @@ -332,4 +334,33 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowTargeterTest, ::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS)); +using WindowTargeterMus = aura::test::AuraMusClientTestBase; + +TEST_F(WindowTargeterMus, SetInsets) { + aura::Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + std::unique_ptr window_targeter_ptr = + std::make_unique(); + WindowTargeter* window_targeter = window_targeter_ptr.get(); + window.SetEventTargeter(std::move(window_targeter_ptr)); + const gfx::Insets insets1(1, 2, 3, 4); + const gfx::Insets insets2(11, 12, 13, 14); + window_targeter->SetInsets(insets1, insets2); + EXPECT_EQ(insets1, window_tree()->last_mouse_hit_test_insets()); + EXPECT_EQ(insets2, window_tree()->last_touch_hit_test_insets()); +} + +TEST_F(WindowTargeterMus, SetInsetsBeforeInstall) { + aura::Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + std::unique_ptr window_targeter = + std::make_unique(); + const gfx::Insets insets1(1, 2, 3, 4); + const gfx::Insets insets2(11, 12, 13, 14); + window_targeter->SetInsets(insets1, insets2); + window.SetEventTargeter(std::move(window_targeter)); + EXPECT_EQ(insets1, window_tree()->last_mouse_hit_test_insets()); + EXPECT_EQ(insets2, window_tree()->last_touch_hit_test_insets()); +} + } // namespace aura diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc index 4c3ea6cb9d1..eb205785534 100644 --- a/chromium/ui/aura/window_tree_host.cc +++ b/chromium/ui/aura/window_tree_host.cc @@ -243,7 +243,8 @@ void WindowTreeHost::SetSharedInputMethod(ui::InputMethod* input_method) { } ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME( - ui::KeyEvent* event) { + ui::KeyEvent* event, + base::OnceCallback ack_callback) { // If dispatch to IME is already disabled we shouldn't reach here. DCHECK(!dispatcher_->should_skip_ime()); dispatcher_->set_skip_ime(true); @@ -252,6 +253,7 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME( event_sink()->OnEventFromSource(event); if (!dispatch_details.dispatcher_destroyed) dispatcher_->set_skip_ime(false); + CallDispatchKeyEventPostIMEAck(event, std::move(ack_callback)); return dispatch_details; } @@ -300,6 +302,11 @@ WindowTreeHost::WindowTreeHost(std::unique_ptr window) display::Screen::GetScreen()->AddObserver(this); } +void WindowTreeHost::IntializeDeviceScaleFactor(float device_scale_factor) { + DCHECK(!compositor_->root_layer()) << "Only call this before InitHost()"; + device_scale_factor_ = device_scale_factor; +} + void WindowTreeHost::DestroyCompositor() { if (compositor_) { compositor_->RemoveObserver(this); @@ -442,10 +449,6 @@ ui::EventSink* WindowTreeHost::GetEventSink() { return dispatcher_.get(); } -void WindowTreeHost::OnDisplayAdded(const display::Display& new_display) {} - -void WindowTreeHost::OnDisplayRemoved(const display::Display& old_display) {} - void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) { if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE) { diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h index d600ca4869e..8eec7d205ea 100644 --- a/chromium/ui/aura/window_tree_host.h +++ b/chromium/ui/aura/window_tree_host.h @@ -45,12 +45,13 @@ struct PlatformWindowInitProperties; } namespace aura { -class ScopedKeyboardHook; namespace test { class WindowTreeHostTestApi; } +class Env; +class ScopedKeyboardHook; class WindowEventDispatcher; class WindowTreeHostObserver; @@ -64,9 +65,11 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, public: ~WindowTreeHost() override; - // Creates a new WindowTreeHost with the specified |properties|. + // Creates a new WindowTreeHost with the specified |properties| and an + // optional |env|. If |env| is null, the default Env::GetInstance() is used. static std::unique_ptr Create( - ui::PlatformWindowInitProperties properties); + ui::PlatformWindowInitProperties properties, + Env* env = nullptr); // Returns the WindowTreeHost for the specified accelerated widget, or NULL // if there is none associated. @@ -168,7 +171,9 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, void SetSharedInputMethod(ui::InputMethod* input_method); // Overridden from ui::internal::InputMethodDelegate: - ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* event) final; + ui::EventDispatchDetails DispatchKeyEventPostIME( + ui::KeyEvent* event, + base::OnceCallback ack_callback) final; // Returns the id of the display. Default implementation queries Screen. virtual int64_t GetDisplayId(); @@ -224,6 +229,10 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, explicit WindowTreeHost(std::unique_ptr window = nullptr); + // Set the cached display device scale factor. This should only be called + // during subclass initialization, when the value is needed before InitHost(). + void IntializeDeviceScaleFactor(float device_scale_factor); + void DestroyCompositor(); void DestroyDispatcher(); @@ -273,8 +282,6 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, ui::EventSink* GetEventSink() override; // display::DisplayObserver implementation. - void OnDisplayAdded(const display::Display& new_display) override; - void OnDisplayRemoved(const display::Display& old_display) override; void OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) override; diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc index 76865a51750..c16bbb1477a 100644 --- a/chromium/ui/aura/window_tree_host_platform.cc +++ b/chromium/ui/aura/window_tree_host_platform.cc @@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" @@ -42,11 +43,12 @@ namespace aura { // static std::unique_ptr WindowTreeHost::Create( - ui::PlatformWindowInitProperties properties) { + ui::PlatformWindowInitProperties properties, + Env* env) { return std::make_unique( std::move(properties), std::make_unique(nullptr, client::WINDOW_TYPE_UNKNOWN, - Env::GetInstance())); + env ? env : Env::GetInstance())); } WindowTreeHostPlatform::WindowTreeHostPlatform( @@ -215,8 +217,23 @@ void WindowTreeHostPlatform::OnDamageRect(const gfx::Rect& damage_rect) { void WindowTreeHostPlatform::DispatchEvent(ui::Event* event) { TRACE_EVENT0("input", "WindowTreeHostPlatform::DispatchEvent"); ui::EventDispatchDetails details = SendEventToSink(event); - if (details.dispatcher_destroyed) + if (details.dispatcher_destroyed) { event->SetHandled(); + return; + } + + // Reset the cursor on ET_MOUSE_EXITED, so that when the mouse re-enters the + // window, the cursor is updated correctly. + if (event->type() == ui::ET_MOUSE_EXITED) { + client::CursorClient* cursor_client = client::GetCursorClient(window()); + if (cursor_client) { + // The cursor-change needs to happen through the CursorClient so that + // other external states are updated correctly, instead of just changing + // |current_cursor_| here. + cursor_client->SetCursor(ui::CursorType::kNone); + DCHECK_EQ(ui::CursorType::kNone, current_cursor_.native_type()); + } + } } void WindowTreeHostPlatform::OnCloseRequest() { diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h index 5ea1727398f..91fde9bcf2a 100644 --- a/chromium/ui/aura/window_tree_host_platform.h +++ b/chromium/ui/aura/window_tree_host_platform.h @@ -84,6 +84,9 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost, bool IsKeyLocked(ui::DomCode dom_code) override; base::flat_map GetKeyboardLayoutMap() override; + // This function is only for test purpose. + gfx::NativeCursor* GetCursorNative() { return ¤t_cursor_; } + private: gfx::AcceleratedWidget widget_; std::unique_ptr platform_window_; diff --git a/chromium/ui/aura/window_tree_host_unittest.cc b/chromium/ui/aura/window_tree_host_unittest.cc index 8207d3ba42d..6d40482c6d6 100644 --- a/chromium/ui/aura/window_tree_host_unittest.cc +++ b/chromium/ui/aura/window_tree_host_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_cursor_client.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/test/window_event_dispatcher_test_api.h" #include "ui/aura/window.h" @@ -10,6 +11,7 @@ #include "ui/base/ime/input_method.h" #include "ui/compositor/layer.h" #include "ui/compositor/test/draw_waiter_for_test.h" +#include "ui/events/base_event_utils.h" #include "ui/events/event_rewriter.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/platform_window/stub/stub_window.h" @@ -141,12 +143,51 @@ class TestWindowTreeHost : public WindowTreeHostPlatform { CreateCompositor(); } + ui::CursorType GetCursorType() { return GetCursorNative()->native_type(); } + void DispatchEventForTest(ui::Event* event) { DispatchEvent(event); } + private: DISALLOW_COPY_AND_ASSIGN(TestWindowTreeHost); }; +class TestCursorClient : public test::TestCursorClient { + public: + explicit TestCursorClient(aura::Window* root_window) + : test::TestCursorClient(root_window) { + window_ = root_window; + } + ~TestCursorClient() override {} + + // Overridden from test::TestCursorClient: + void SetCursor(gfx::NativeCursor cursor) override { + WindowTreeHost* host = window_->GetHost(); + if (host) + host->SetCursor(cursor); + } + + private: + aura::Window* window_; + DISALLOW_COPY_AND_ASSIGN(TestCursorClient); +}; + TEST_F(WindowTreeHostTest, LostCaptureDuringTearDown) { TestWindowTreeHost host; } +// Tests if the cursor type is reset after ET_MOUSE_EXITED event. +TEST_F(WindowTreeHostTest, ResetCursorOnExit) { + TestWindowTreeHost host; + aura::TestCursorClient cursor_client(host.window()); + + // Set the cursor with the specific type to check if it's reset after + // ET_MOUSE_EXITED event. + host.SetCursorNative(ui::CursorType::kCross); + + ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + + host.DispatchEventForTest(&exit_event); + EXPECT_EQ(host.GetCursorType(), ui::CursorType::kNone); +} + } // namespace aura diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc index a61fc13a4de..7edb1e5aced 100644 --- a/chromium/ui/aura/window_unittest.cc +++ b/chromium/ui/aura/window_unittest.cc @@ -1638,9 +1638,13 @@ TEST_P(WindowTest, Transform) { } TEST_P(WindowTest, TransformGesture) { - // TODO(sky): fails with mus. https://crbug.com/866502 + // This test is only applicable to LOCAL mode as it's setting a transform on + // host() and expecting events to be transformed while routing the event + // directly through host(). In MUS mode the window-service does the + // transformation. if (GetParam() == Env::Mode::MUS) return; + gfx::Size size = host()->GetBoundsInPixels().size(); std::unique_ptr delegate( -- cgit v1.2.1