diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-20 10:33:36 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-11-22 11:45:12 +0000 |
commit | be59a35641616a4cf23c4a13fa0632624b021c1b (patch) | |
tree | 9da183258bdf9cc413f7562079d25ace6955467f /chromium/ui/aura/mus | |
parent | d702e4b6a64574e97fc7df8fe3238cde70242080 (diff) | |
download | qtwebengine-chromium-be59a35641616a4cf23c4a13fa0632624b021c1b.tar.gz |
BASELINE: Update Chromium to 62.0.3202.101
Change-Id: I2d5eca8117600df6d331f6166ab24d943d9814ac
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/ui/aura/mus')
26 files changed, 1248 insertions, 222 deletions
diff --git a/chromium/ui/aura/mus/DEPS b/chromium/ui/aura/mus/DEPS index 2f08e4b543d..1f379237e61 100644 --- a/chromium/ui/aura/mus/DEPS +++ b/chromium/ui/aura/mus/DEPS @@ -4,23 +4,15 @@ include_rules = [ "+cc/output/layer_tree_frame_sink_client.h", "+cc/output/layer_tree_frame_sink.h", "+cc/scheduler/begin_frame_source.h", - "+cc/surfaces/local_surface_id.h", - "+cc/surfaces/local_surface_id_allocator.h", - "+cc/surfaces/surface_info.h", - "+cc/surfaces/surface_manager.h", - "+cc/surfaces/surface_reference_factory.h", "+components/discardable_memory/client/client_discardable_shared_memory_manager.h", "+components/viz/client", - "+components/viz/common/gpu", + "+components/viz/common", "+gpu/command_buffer/client/gpu_memory_buffer_manager.h", "+gpu/ipc/client/gpu_channel_host.h", "+mojo/public/cpp/system/buffer.h", "+mojo/public/cpp/system/platform_handle.h", "+services/ui/common/accelerator_util.h", "+services/ui/common/task_runner_test_base.h", - "+services/ui/public/cpp/gpu", - "+services/ui/public/cpp/property_type_converters.h", - "+services/ui/public/cpp/raster_thread_helper.h", - "+services/ui/public/cpp/client_layer_tree_frame_sink.h", + "+services/ui/public", "+ui/gl/gl_bindings.h", ] diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc index cf439ce2375..e14dcd5254d 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.cc +++ b/chromium/ui/aura/mus/client_surface_embedder.cc @@ -5,7 +5,7 @@ #include "ui/aura/mus/client_surface_embedder.h" #include "base/memory/ptr_util.h" -#include "cc/surfaces/stub_surface_reference_factory.h" +#include "components/viz/common/surfaces/stub_surface_reference_factory.h" #include "ui/aura/window.h" #include "ui/gfx/geometry/dip_util.h" @@ -27,7 +27,7 @@ ClientSurfaceEmbedder::ClientSurfaceEmbedder( // this is the case with window decorations provided by Window Manager. // This content should appear underneath the content of the embedded client. window_->layer()->StackAtTop(surface_layer_.get()); - ref_factory_ = new cc::StubSurfaceReferenceFactory(); + ref_factory_ = new viz::StubSurfaceReferenceFactory(); } ClientSurfaceEmbedder::~ClientSurfaceEmbedder() = default; diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.cc b/chromium/ui/aura/mus/drag_drop_controller_mus.cc index 0d64f7b0258..fea4fc0554f 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus.cc +++ b/chromium/ui/aura/mus/drag_drop_controller_mus.cc @@ -15,7 +15,9 @@ #include "mojo/public/cpp/bindings/map.h" #include "services/ui/public/interfaces/window_tree.mojom.h" #include "services/ui/public/interfaces/window_tree_constants.mojom.h" +#include "ui/aura/client/drag_drop_client_observer.h" #include "ui/aura/client/drag_drop_delegate.h" +#include "ui/aura/env.h" #include "ui/aura/mus/drag_drop_controller_host.h" #include "ui/aura/mus/mus_types.h" #include "ui/aura/mus/os_exchange_data_provider_mus.h" @@ -116,8 +118,11 @@ uint32_t DragDropControllerMus::OnCompleteDrop( void DragDropControllerMus::OnPerformDragDropCompleted(uint32_t action_taken) { DCHECK(current_drag_state_); + for (client::DragDropClientObserver& observer : observers_) + observer.OnDragEnded(); current_drag_state_->completed_action = action_taken; current_drag_state_->runloop_quit_closure.Run(); + current_drag_state_ = nullptr; } void DragDropControllerMus::OnDragDropDone() { @@ -140,8 +145,10 @@ int DragDropControllerMus::StartDragAndDrop( CurrentDragState current_drag_state = {root_window_mus->server_id(), change_id, ui::mojom::kDropEffectNone, data, run_loop.QuitClosure()}; - base::AutoReset<CurrentDragState*> resetter(¤t_drag_state_, - ¤t_drag_state); + + // current_drag_state_ will be reset in |OnPerformDragDropCompleted| before + // run_loop.Run() quits. + current_drag_state_ = ¤t_drag_state; base::MessageLoop* loop = base::MessageLoop::current(); base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); @@ -155,6 +162,10 @@ int DragDropControllerMus::StartDragAndDrop( std::map<std::string, std::vector<uint8_t>> drag_data = static_cast<const aura::OSExchangeDataProviderMus&>(data.provider()) .GetData(); + + for (client::DragDropClientObserver& observer : observers_) + observer.OnDragStarted(); + window_tree_->PerformDragDrop( change_id, root_window_mus->server_id(), screen_location, mojo::MapToUnorderedMap(drag_data), @@ -162,7 +173,6 @@ int DragDropControllerMus::StartDragAndDrop( data.provider().GetDragImageOffset(), drag_operations, mojo_source); run_loop.Run(); - return current_drag_state.completed_action; } @@ -176,6 +186,16 @@ bool DragDropControllerMus::IsDragDropInProgress() { return current_drag_state_ != nullptr; } +void DragDropControllerMus::AddObserver( + client::DragDropClientObserver* observer) { + observers_.AddObserver(observer); +} + +void DragDropControllerMus::RemoveObserver( + client::DragDropClientObserver* observer) { + observers_.RemoveObserver(observer); +} + uint32_t DragDropControllerMus::HandleDragEnterOrOver( WindowMus* window, uint32_t event_flags, diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.h b/chromium/ui/aura/mus/drag_drop_controller_mus.h index 92700dcb992..e161339ded1 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus.h +++ b/chromium/ui/aura/mus/drag_drop_controller_mus.h @@ -11,6 +11,8 @@ #include <memory> #include <vector> +#include "base/observer_list.h" +#include "ui/aura/aura_export.h" #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/window_tracker.h" #include "ui/base/dragdrop/drag_drop_types.h" @@ -32,7 +34,7 @@ class WindowMus; // DragDropControllerMus acts as the DragDropClient for aura as well as // handling all drag operations from the server. Drag operations are forwarded // to the client::DragDropDelegate set on the target Window. -class DragDropControllerMus : public client::DragDropClient { +class AURA_EXPORT DragDropControllerMus : public client::DragDropClient { public: DragDropControllerMus(DragDropControllerHost* drag_drop_controller_host, ui::mojom::WindowTree* window_tree); @@ -70,6 +72,8 @@ class DragDropControllerMus : public client::DragDropClient { ui::DragDropTypes::DragEventSource source) override; void DragCancel() override; bool IsDragDropInProgress() override; + void AddObserver(client::DragDropClientObserver* observer) override; + void RemoveObserver(client::DragDropClientObserver* observer) override; private: struct CurrentDragState; @@ -105,6 +109,8 @@ class DragDropControllerMus : public client::DragDropClient { // Used to track the current drop target. WindowTracker drop_target_window_tracker_; + base::ObserverList<client::DragDropClientObserver> observers_; + DISALLOW_COPY_AND_ASSIGN(DragDropControllerMus); }; diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc new file mode 100644 index 00000000000..55964c70bd8 --- /dev/null +++ b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc @@ -0,0 +1,170 @@ +// Copyright 2017 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/drag_drop_controller_mus.h" + +#include <memory> + +#include "base/callback_forward.h" +#include "base/memory/ptr_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/thread_task_runner_handle.h" +#include "ui/aura/client/drag_drop_client_observer.h" +#include "ui/aura/client/drag_drop_delegate.h" +#include "ui/aura/mus/drag_drop_controller_host.h" +#include "ui/aura/mus/window_mus.h" +#include "ui/aura/test/aura_mus_test_base.h" +#include "ui/aura/test/mus/test_window_tree.h" +#include "ui/base/dragdrop/drop_target_event.h" +#include "ui/events/event_utils.h" + +namespace aura { +namespace { + +class DragDropControllerMusTest : public test::AuraMusWmTestBase { + public: + DragDropControllerMusTest() = default; + + // test::AuraMusWmTestBase + void SetUp() override { + AuraMusWmTestBase::SetUp(); + controller_ = base::MakeUnique<DragDropControllerMus>(&controller_host_, + window_tree()); + window_ = std::unique_ptr<aura::Window>( + CreateNormalWindow(0, root_window(), nullptr)); + } + + void TearDown() override { + window_.reset(); + controller_.reset(); + AuraMusWmTestBase::TearDown(); + } + + protected: + void PostDragMoveAndDrop() { + // Posted task will be run when the inner loop runs in StartDragAndDrop. + ASSERT_TRUE(base::ThreadTaskRunnerHandle::IsSet()); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&DragDropControllerMusTest::DragMoveAndDrop, + base::Unretained(this))); + } + + void StartDragAndDrop() { + controller_->StartDragAndDrop( + ui::OSExchangeData(), window_->GetRootWindow(), window_.get(), + gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE, + ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); + } + + std::unique_ptr<DragDropControllerMus> controller_; + std::unique_ptr<aura::Window> window_; + + private: + void DragMoveAndDrop() { + WindowMus* const window_mus = WindowMus::Get(window_.get()); + controller_->OnDragEnter(window_mus, 0, gfx::Point(5, 20), 0); + controller_->OnDragOver(window_mus, 0, gfx::Point(5, 20), 0); + controller_->OnCompleteDrop(window_mus, 0, gfx::Point(5, 20), 0); + controller_->OnPerformDragDropCompleted(0); + } + + class TestDragDropControllerHost : public DragDropControllerHost { + public: + TestDragDropControllerHost() : serial_(0u) {} + + // DragDropControllerHost + uint32_t CreateChangeIdForDrag(WindowMus* window) override { + return serial_++; + } + + private: + uint32_t serial_; + + } controller_host_; + + DISALLOW_COPY_AND_ASSIGN(DragDropControllerMusTest); +}; + +TEST_F(DragDropControllerMusTest, DragStartedAndEndedEvents) { + enum class State { kNotInvoked, kDragStartInvoked, kDragEndInvoked }; + + class TestObserver : public client::DragDropClientObserver { + public: + TestObserver() = default; + State state() const { return state_; } + + // Overrides from client::DragDropClientObserver: + void OnDragStarted() override { + EXPECT_EQ(State::kNotInvoked, state_); + state_ = State::kDragStartInvoked; + } + void OnDragEnded() override { + EXPECT_EQ(State::kDragStartInvoked, state_); + state_ = State::kDragEndInvoked; + } + + private: + State state_{State::kNotInvoked}; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); + } observer; + + controller_->AddObserver(&observer); + PostDragMoveAndDrop(); + StartDragAndDrop(); + EXPECT_EQ(State::kDragEndInvoked, observer.state()); + controller_->RemoveObserver(&observer); +} + +TEST_F(DragDropControllerMusTest, EventTarget) { + enum class State { + kNotInvoked, + kDragEnteredInvoked, + kDragUpdateInvoked, + kPerformDropInvoked + }; + + class TestDelegate : public client::DragDropDelegate { + public: + TestDelegate(aura::Window* window) : window_(window) {} + State state() const { return state_; } + + // Overrides from client::DragDropClientObserver: + void OnDragEntered(const ui::DropTargetEvent& event) override { + EXPECT_EQ(State::kNotInvoked, state_); + EXPECT_EQ(window_, event.target()); + state_ = State::kDragEnteredInvoked; + } + int OnDragUpdated(const ui::DropTargetEvent& event) override { + EXPECT_TRUE(State::kDragEnteredInvoked == state_ || + State::kDragUpdateInvoked == state_); + EXPECT_EQ(window_, event.target()); + state_ = State::kDragUpdateInvoked; + return ui::DragDropTypes::DRAG_MOVE; + } + void OnDragExited() override { ADD_FAILURE(); } + int OnPerformDrop(const ui::DropTargetEvent& event) override { + EXPECT_EQ(State::kDragUpdateInvoked, state_); + EXPECT_EQ(window_, event.target()); + state_ = State::kPerformDropInvoked; + return ui::DragDropTypes::DRAG_MOVE; + } + + private: + aura::Window* const window_; + State state_{State::kNotInvoked}; + + DISALLOW_COPY_AND_ASSIGN(TestDelegate); + } delegate(window_.get()); + + client::SetDragDropDelegate(window_.get(), &delegate); + PostDragMoveAndDrop(); + StartDragAndDrop(); + EXPECT_EQ(State::kPerformDropInvoked, delegate.state()); + client::SetDragDropDelegate(window_.get(), nullptr); +} + +} // namespace +} // namespace aura diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura.cc b/chromium/ui/aura/mus/hit_test_data_provider_aura.cc new file mode 100644 index 00000000000..db915077e08 --- /dev/null +++ b/chromium/ui/aura/mus/hit_test_data_provider_aura.cc @@ -0,0 +1,133 @@ +// Copyright 2017 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/hit_test_data_provider_aura.h" + +#include "base/containers/adapters.h" +#include "services/ui/public/interfaces/window_tree_constants.mojom.h" +#include "ui/aura/window.h" +#include "ui/aura/window_targeter.h" + +namespace { + +viz::mojom::HitTestRegionPtr CreateHitTestRegion(const aura::Window* window, + uint32_t flags, + const gfx::Rect& rect) { + const ui::Layer* layer = window->layer(); + DCHECK(layer); + + auto hit_test_region = viz::mojom::HitTestRegion::New(); + DCHECK(window->GetFrameSinkId().is_valid()); + hit_test_region->frame_sink_id = window->GetFrameSinkId(); + if (layer->GetPrimarySurfaceInfo()) { + DCHECK(window->GetFrameSinkId() == + layer->GetPrimarySurfaceInfo()->id().frame_sink_id()); + hit_test_region->local_surface_id = + layer->GetPrimarySurfaceInfo()->id().local_surface_id(); + } + hit_test_region->flags = flags; + hit_test_region->rect = rect; + hit_test_region->transform = layer->transform(); + + return hit_test_region; +} + +} // namespace + +namespace aura { + +HitTestDataProviderAura::HitTestDataProviderAura(aura::Window* window) + : window_(window) {} + +HitTestDataProviderAura::~HitTestDataProviderAura() {} + +viz::mojom::HitTestRegionListPtr HitTestDataProviderAura::GetHitTestData() + const { + const ui::mojom::EventTargetingPolicy event_targeting_policy = + window_->event_targeting_policy(); + if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE) + return nullptr; + + auto hit_test_region_list = viz::mojom::HitTestRegionList::New(); + hit_test_region_list->flags = + event_targeting_policy == + ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY + ? viz::mojom::kHitTestIgnore + : viz::mojom::kHitTestMine; + hit_test_region_list->bounds = window_->bounds(); + + GetHitTestDataRecursively(window_, hit_test_region_list.get()); + return hit_test_region_list; +} + +void HitTestDataProviderAura::GetHitTestDataRecursively( + aura::Window* window, + viz::mojom::HitTestRegionList* hit_test_region_list) const { + WindowTargeter* targeter = + static_cast<WindowTargeter*>(window->GetEventTargeter()); + + // TODO(varkha): Figure out if we need to add hit-test regions for |window|. + // Walk the children in Z-order (reversed order of children()) to produce + // the hit-test data. Each child's hit test data is added before the hit-test + // data from the child's descendants because the child could clip its + // descendants for the purpose of event handling. + for (aura::Window* child : base::Reversed(window->children())) { + const ui::mojom::EventTargetingPolicy event_targeting_policy = + child->event_targeting_policy(); + if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE) + continue; + if (event_targeting_policy != + ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY) { + gfx::Rect rect_mouse(child->bounds()); + gfx::Rect rect_touch; + bool touch_and_mouse_are_same = true; + uint32_t flags = child->layer()->GetPrimarySurfaceInfo() + ? viz::mojom::kHitTestChildSurface + : viz::mojom::kHitTestMine; + // Use the |targeter| to query for possibly expanded hit-test area. + // Use the |child| bounds with mouse and touch flags when there is no + // |targeter|. + if (targeter && + targeter->GetHitTestRects(child, &rect_mouse, &rect_touch)) { + touch_and_mouse_are_same = rect_mouse == rect_touch; + } + + auto shape_rects = + targeter ? targeter->GetExtraHitTestShapeRects(child) : nullptr; + if (shape_rects) { + // The |child| has a complex shape. Clip it to |rect_mouse|. + const gfx::Vector2d offset = child->bounds().OffsetFromOrigin(); + for (const gfx::Rect& shape_rect : *shape_rects) { + gfx::Rect rect = shape_rect; + rect.Offset(offset); + rect.Intersect(rect_mouse); + if (rect.IsEmpty()) + continue; + hit_test_region_list->regions.push_back(CreateHitTestRegion( + child, + flags | viz::mojom::kHitTestMouse | viz::mojom::kHitTestTouch, + rect)); + } + } else { + // The |child| has possibly same mouse and touch hit-test areas. + if (!rect_mouse.IsEmpty()) { + hit_test_region_list->regions.push_back(CreateHitTestRegion( + child, + flags | (touch_and_mouse_are_same ? (viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch) + : viz::mojom::kHitTestMouse), + rect_mouse)); + } + if (!touch_and_mouse_are_same && !rect_touch.IsEmpty()) { + hit_test_region_list->regions.push_back(CreateHitTestRegion( + child, flags | viz::mojom::kHitTestTouch, rect_touch)); + } + } + } + if (event_targeting_policy != ui::mojom::EventTargetingPolicy::TARGET_ONLY) + GetHitTestDataRecursively(child, hit_test_region_list); + } +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura.h b/chromium/ui/aura/mus/hit_test_data_provider_aura.h new file mode 100644 index 00000000000..04b7748b494 --- /dev/null +++ b/chromium/ui/aura/mus/hit_test_data_provider_aura.h @@ -0,0 +1,41 @@ +// Copyright 2017 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_HIT_TEST_DATA_PROVIDER_AURA_H_ +#define UI_AURA_MUS_HIT_TEST_DATA_PROVIDER_AURA_H_ + +#include "base/macros.h" +#include "components/viz/client/hit_test_data_provider.h" + +namespace aura { + +class Window; + +// A HitTestDataProvider that captures hit-test areas from a aura::Window tree +// and packages it to be submitted to compositor frame sink. The |window| used +// when creating the HitTestDataProviderAura should outlive the data provider. +class HitTestDataProviderAura : public viz::HitTestDataProvider { + public: + explicit HitTestDataProviderAura(Window* window); + ~HitTestDataProviderAura() override; + + // HitTestDataProvider: + viz::mojom::HitTestRegionListPtr GetHitTestData() const override; + + private: + // Recursively walks the children of |window| and uses |window|'s + // EventTargeter to generate hit-test data for the |window|'s descendants. + // Populates |hit_test_region_list|. + void GetHitTestDataRecursively( + aura::Window* window, + viz::mojom::HitTestRegionList* hit_test_region_list) const; + + aura::Window* const window_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderAura); +}; + +} // namespace aura + +#endif // UI_AURA_MUS_HIT_TEST_DATA_PROVIDER_AURA_H_
\ No newline at end of file diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc b/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc new file mode 100644 index 00000000000..5f8611fe1b2 --- /dev/null +++ b/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc @@ -0,0 +1,290 @@ +// Copyright 2017 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/window_tree_client.h" + +#include "components/viz/client/hit_test_data_provider.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/mus/window_port_mus.h" +#include "ui/aura/test/aura_mus_test_base.h" +#include "ui/aura/window.h" +#include "ui/aura/window_targeter.h" +#include "ui/gfx/geometry/rect.h" + +namespace aura { + +namespace { + +const int kMouseInset = -5; +const int kTouchInset = -10; + +// Custom WindowTargeter that expands hit-test regions of child windows. +class TestWindowTargeter : public WindowTargeter { + public: + TestWindowTargeter() { + SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset)); + } + ~TestWindowTargeter() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestWindowTargeter); +}; + +// Custom WindowTargeter that replaces hit-test area on a window with a frame +// rectangle and a hole in the middle 1/3. +// ---------------------- +// | hit hit | +// | ---------- | +// | | | | +// | | No hit | hit | +// | | | | +// | hit | | | +// | ---------- | +// | hit hit | +// ---------------------- +class TestHoleWindowTargeter : public aura::WindowTargeter { + public: + TestHoleWindowTargeter() = default; + ~TestHoleWindowTargeter() override {} + + private: + // aura::WindowTargeter: + std::unique_ptr<aura::WindowTargeter::HitTestRects> GetExtraHitTestShapeRects( + aura::Window* target) const override { + gfx::Rect bounds = target->bounds(); + int x0 = 0; + int x1 = bounds.width() / 3; + int x2 = bounds.width() - bounds.width() / 3; + int x3 = bounds.width(); + int y0 = 0; + int y1 = bounds.height() / 3; + int y2 = bounds.height() - bounds.height() / 3; + int y3 = bounds.height(); + auto shape_rects = base::MakeUnique<aura::WindowTargeter::HitTestRects>(); + 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); + shape_rects->emplace_back(x0, y2, bounds.width(), y3 - y2); + return shape_rects; + } + + DISALLOW_COPY_AND_ASSIGN(TestHoleWindowTargeter); +}; + +} // namespace + +// Creates a root window and child windows. Maintains a cc:LayerTreeFrameSink +// to help exercise its viz::HitTestDataProvider. +class HitTestDataProviderAuraTest : public test::AuraTestBaseMus { + public: + HitTestDataProviderAuraTest() {} + ~HitTestDataProviderAuraTest() override {} + + void SetUp() override { + test::AuraTestBaseMus::SetUp(); + + root_ = base::MakeUnique<Window>(nullptr); + root_->Init(ui::LAYER_NOT_DRAWN); + root_->SetEventTargeter(base::MakeUnique<WindowTargeter>()); + root_->SetBounds(gfx::Rect(0, 0, 300, 200)); + + window2_ = new Window(nullptr); + window2_->Init(ui::LAYER_TEXTURED); + window2_->SetBounds(gfx::Rect(20, 30, 40, 60)); + + window3_ = new Window(nullptr); + window3_->Init(ui::LAYER_TEXTURED); + window3_->SetEventTargeter(base::MakeUnique<WindowTargeter>()); + window3_->SetBounds(gfx::Rect(50, 60, 100, 40)); + + window4_ = new Window(nullptr); + window4_->Init(ui::LAYER_TEXTURED); + window4_->SetBounds(gfx::Rect(20, 10, 60, 30)); + + window3_->AddChild(window4_); + root_->AddChild(window2_); + root_->AddChild(window3_); + + WindowPort* port = WindowPortMus::Get(root_.get()); + sink_ = port->CreateLayerTreeFrameSink(); + } + + protected: + const viz::HitTestDataProvider* hit_test_data_provider() const { + // TODO(varkha): Find a way to get the HitTestDataProvider without depending + // on WindowPortMus + WindowPortMus* port = WindowPortMus::Get(root_.get()); + return port->local_layer_tree_frame_sink_->hit_test_data_provider(); + } + + Window* root() { return root_.get(); } + Window* window2() { return window2_; } + Window* window3() { return window3_; } + Window* window4() { return window4_; } + + private: + std::unique_ptr<cc::LayerTreeFrameSink> sink_; + std::unique_ptr<Window> root_; + Window* window2_; + Window* window3_; + Window* window4_; + + DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderAuraTest); +}; + +// TODO(riajiang): Add test cases for kHitTestChildSurface to ensure +// that local_surface_id is set and used correctly. + +// Tests that the order of reported hit-test regions matches windows Z-order. +TEST_F(HitTestDataProviderAuraTest, Stacking) { + const auto hit_test_data_1 = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data_1); + EXPECT_EQ(hit_test_data_1->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data_1->bounds, root()->bounds()); + Window* expected_order_1[] = {window3(), window4(), window2()}; + EXPECT_EQ(hit_test_data_1->regions.size(), arraysize(expected_order_1)); + int i = 0; + for (const auto& region : hit_test_data_1->regions) { + EXPECT_EQ(region->flags, viz::mojom::kHitTestMine | + viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch); + EXPECT_EQ(region->frame_sink_id, expected_order_1[i]->GetFrameSinkId()); + EXPECT_EQ(region->rect.ToString(), + expected_order_1[i]->bounds().ToString()); + i++; + } + + root()->StackChildAbove(window2(), window3()); + const auto hit_test_data_2 = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data_2); + EXPECT_EQ(hit_test_data_2->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data_2->bounds, root()->bounds()); + + Window* expected_order_2[] = {window2(), window3(), window4()}; + EXPECT_EQ(hit_test_data_2->regions.size(), arraysize(expected_order_2)); + i = 0; + for (const auto& region : hit_test_data_2->regions) { + EXPECT_EQ(region->flags, viz::mojom::kHitTestMine | + viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch); + EXPECT_EQ(region->frame_sink_id, expected_order_2[i]->GetFrameSinkId()); + EXPECT_EQ(region->rect.ToString(), + expected_order_2[i]->bounds().ToString()); + i++; + } +} + +// Tests that the hit-test regions get expanded with a custom event targeter. +TEST_F(HitTestDataProviderAuraTest, CustomTargeter) { + window3()->SetEventTargeter(base::MakeUnique<TestWindowTargeter>()); + const auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data->bounds, root()->bounds()); + + // Children of a container that has the custom targeter installed will get + // reported twice, once with hit-test bounds optimized for mouse events and + // another time with bounds expanded more for touch input. + Window* expected_windows[] = {window3(), window4(), window4(), window2()}; + uint32_t expected_flags[] = { + viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch, + viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse, + viz::mojom::kHitTestMine | viz::mojom::kHitTestTouch, + viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch}; + int expected_insets[] = {0, kMouseInset, kTouchInset, 0}; + ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_windows)); + ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_flags)); + ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_insets)); + int i = 0; + for (const auto& region : hit_test_data->regions) { + EXPECT_EQ(region->frame_sink_id, expected_windows[i]->GetFrameSinkId()); + EXPECT_EQ(region->flags, expected_flags[i]); + gfx::Rect expected_bounds = expected_windows[i]->bounds(); + expected_bounds.Inset(gfx::Insets(expected_insets[i])); + EXPECT_EQ(region->rect.ToString(), expected_bounds.ToString()); + i++; + } +} + +// Tests that the complex hit-test shape can be set with a custom targeter. +TEST_F(HitTestDataProviderAuraTest, HoleTargeter) { + window3()->SetEventTargeter(base::MakeUnique<TestHoleWindowTargeter>()); + const auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data->bounds, root()->bounds()); + + // Children of a container that has the custom targeter installed will get + // reported 4 times for each of the hit test regions defined by the custom + // targeter. + Window* expected_windows[] = {window3(), window4(), window4(), + window4(), window4(), window2()}; + uint32_t expected_flags = viz::mojom::kHitTestMine | + viz::mojom::kHitTestMouse | + viz::mojom::kHitTestTouch; + std::vector<gfx::Rect> expected_bounds; + expected_bounds.push_back(window3()->bounds()); + + // original window4 is at gfx::Rect(20, 10, 60, 30). + expected_bounds.emplace_back(20, 10, 60, 10); + expected_bounds.emplace_back(20, 20, 20, 10); + expected_bounds.emplace_back(60, 20, 20, 10); + expected_bounds.emplace_back(20, 30, 60, 10); + + expected_bounds.push_back(window2()->bounds()); + + ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_windows)); + ASSERT_EQ(hit_test_data->regions.size(), expected_bounds.size()); + int i = 0; + for (const auto& region : hit_test_data->regions) { + EXPECT_EQ(region->frame_sink_id, expected_windows[i]->GetFrameSinkId()); + EXPECT_EQ(region->flags, expected_flags); + EXPECT_EQ(region->rect.ToString(), expected_bounds[i].ToString()); + i++; + } +} + +TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { + root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE); + auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_FALSE(hit_test_data); + + root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY); + window3()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data->regions.size(), 3U); + + root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY); + window3()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::TARGET_ONLY); + hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data->regions.size(), 2U); + + root()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY); + window3()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY); + hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestIgnore); + EXPECT_EQ(hit_test_data->regions.size(), 2U); + + root()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + window3()->SetEventTargetingPolicy( + ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); + hit_test_data = hit_test_data_provider()->GetHitTestData(); + ASSERT_TRUE(hit_test_data); + EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); + EXPECT_EQ(hit_test_data->regions.size(), 3U); +} + +} // namespace aura diff --git a/chromium/ui/aura/mus/in_flight_change.h b/chromium/ui/aura/mus/in_flight_change.h index 40b3dcbcc6c..0422d2f20be 100644 --- a/chromium/ui/aura/mus/in_flight_change.h +++ b/chromium/ui/aura/mus/in_flight_change.h @@ -41,6 +41,7 @@ enum class ChangeType { ADD_TRANSIENT_WINDOW, BOUNDS, CAPTURE, + CHILD_MODAL_PARENT, DELETE_WINDOW, DRAG_LOOP, FOCUS, diff --git a/chromium/ui/aura/mus/mus_context_factory.cc b/chromium/ui/aura/mus/mus_context_factory.cc index ed99ef60c9f..6cab93e4813 100644 --- a/chromium/ui/aura/mus/mus_context_factory.cc +++ b/chromium/ui/aura/mus/mus_context_factory.cc @@ -8,11 +8,11 @@ #include "base/memory/ptr_util.h" #include "cc/base/switches.h" #include "components/viz/common/gpu/context_provider.h" +#include "components/viz/host/renderer_settings_creation.h" #include "services/ui/public/cpp/gpu/gpu.h" #include "ui/aura/mus/window_port_mus.h" #include "ui/aura/window_tree_host.h" #include "ui/compositor/compositor_switches.h" -#include "ui/compositor/compositor_util.h" #include "ui/display/display_switches.h" #include "ui/gfx/switches.h" #include "ui/gl/gl_bindings.h" @@ -39,8 +39,8 @@ viz::BufferToTextureTargetMap CreateBufferToTextureTargetMap() { MusContextFactory::MusContextFactory(ui::Gpu* gpu) : gpu_(gpu), - renderer_settings_( - ui::CreateRendererSettings(CreateBufferToTextureTargetMap())), + resource_settings_( + viz::CreateResourceSettings(CreateBufferToTextureTargetMap())), weak_ptr_factory_(this) {} MusContextFactory::~MusContextFactory() {} @@ -104,7 +104,7 @@ cc::TaskGraphRunner* MusContextFactory::GetTaskGraphRunner() { } const viz::ResourceSettings& MusContextFactory::GetResourceSettings() const { - return renderer_settings_.resource_settings; + return resource_settings_; } } // namespace aura diff --git a/chromium/ui/aura/mus/mus_context_factory.h b/chromium/ui/aura/mus/mus_context_factory.h index 3634f7b4c0c..ab1b1950f62 100644 --- a/chromium/ui/aura/mus/mus_context_factory.h +++ b/chromium/ui/aura/mus/mus_context_factory.h @@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "cc/surfaces/surface_manager.h" #include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/gpu/context_provider.h" #include "services/ui/public/cpp/raster_thread_helper.h" @@ -58,7 +57,7 @@ class AURA_EXPORT MusContextFactory : public ui::ContextFactory { ui::RasterThreadHelper raster_thread_helper_; ui::Gpu* gpu_; - const viz::RendererSettings renderer_settings_; + const viz::ResourceSettings resource_settings_; scoped_refptr<viz::ContextProvider> shared_main_thread_context_provider_; base::WeakPtrFactory<MusContextFactory> weak_ptr_factory_; 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 04e7539f04a..cfdf82b7ef0 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc @@ -251,7 +251,7 @@ bool OSExchangeDataProviderMus::HasCustomFormat( // These methods were added in an ad-hoc way to different operating // systems. We need to support them until they get cleaned up. -#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN) +#if defined(USE_X11) || defined(OS_WIN) void OSExchangeDataProviderMus::SetFileContents( const base::FilePath& filename, const std::string& file_contents) {} diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h index 777da5ac293..27a541950dd 100644 --- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h +++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h @@ -68,7 +68,7 @@ class AURA_EXPORT OSExchangeDataProviderMus // per operating system. Now we have to have at least two providers per OS, // leading to the following warts, which will remain until we clean all the // callsites up. -#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN) +#if defined(USE_X11) || defined(OS_WIN) void SetFileContents(const base::FilePath& filename, const std::string& file_contents) override; #endif diff --git a/chromium/ui/aura/mus/user_activity_forwarder.h b/chromium/ui/aura/mus/user_activity_forwarder.h index d1890424b88..58d28529ed1 100644 --- a/chromium/ui/aura/mus/user_activity_forwarder.h +++ b/chromium/ui/aura/mus/user_activity_forwarder.h @@ -24,7 +24,7 @@ namespace aura { // downstream of ui::UserActivityDetector) instead observe UserActivityMonitor // directly: http://crbug.com/626899 class AURA_EXPORT UserActivityForwarder - : NON_EXPORTED_BASE(public ui::mojom::UserActivityObserver) { + : public ui::mojom::UserActivityObserver { public: UserActivityForwarder(ui::mojom::UserActivityMonitorPtr monitor, ui::UserActivityDetector* detector); diff --git a/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc b/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc index dc2fd59f428..9d011c0e723 100644 --- a/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc +++ b/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc @@ -71,7 +71,8 @@ TEST_F(UserActivityForwarderTest, ForwardActivityToDetector) { // Run pending tasks so |monitor| receives |forwarder|'s registration. RunUntilIdle(); - base::TimeTicks now = base::TimeTicks::FromInternalValue(1000); + base::TimeTicks now = + base::TimeTicks() + base::TimeDelta::FromMicroseconds(1000); detector.set_now_for_test(now); monitor.NotifyUserActivityObservers(); RunUntilIdle(); diff --git a/chromium/ui/aura/mus/window_manager_delegate.cc b/chromium/ui/aura/mus/window_manager_delegate.cc index e2f42eb1fab..0bf4087a847 100644 --- a/chromium/ui/aura/mus/window_manager_delegate.cc +++ b/chromium/ui/aura/mus/window_manager_delegate.cc @@ -15,4 +15,6 @@ ui::mojom::EventResult WindowManagerDelegate::OnAccelerator( return ui::mojom::EventResult::UNHANDLED; } +void WindowManagerDelegate::OnEventBlockedByModalWindow(Window* window) {} + } // namespace aura diff --git a/chromium/ui/aura/mus/window_manager_delegate.h b/chromium/ui/aura/mus/window_manager_delegate.h index d3df4610aa2..bd3332ef53e 100644 --- a/chromium/ui/aura/mus/window_manager_delegate.h +++ b/chromium/ui/aura/mus/window_manager_delegate.h @@ -41,6 +41,12 @@ class WindowTreeHostMus; struct WindowTreeHostMusInitParams; +// This mirrors ui::mojom::BlockingContainers. See it for details. +struct BlockingContainers { + aura::Window* system_modal_container = nullptr; + aura::Window* min_container = nullptr; +}; + // See the mojom with the same name for details on the functions in this // interface. class AURA_EXPORT WindowManagerClient { @@ -56,7 +62,6 @@ class AURA_EXPORT WindowManagerClient { virtual void RemoveAccelerator(uint32_t id) = 0; virtual void AddActivationParent(Window* window) = 0; virtual void RemoveActivationParent(Window* window) = 0; - virtual void ActivateNextWindow() = 0; virtual void SetExtendedHitRegionForChildren( Window* window, const gfx::Insets& mouse_area, @@ -80,6 +85,12 @@ class AURA_EXPORT WindowManagerClient { virtual void SetGlobalOverrideCursor( base::Optional<ui::CursorData> cursor) = 0; + // Sets whether the cursor is visible because the user touched the + // screen. This bit is separate from SetCursorVisible(), as it implicitly is + // set in the window server when a touch event occurs, and is implicitly + // cleared when the mouse moves. + virtual void SetCursorTouchVisible(bool enabled) = 0; + // Sets the list of keys which don't hide the cursor. virtual void SetKeyEventsThatDontHideCursor( std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) = 0; @@ -89,6 +100,11 @@ class AURA_EXPORT WindowManagerClient { // this does nothing. virtual void RequestClose(Window* window) = 0; + // See mojom::WindowManager::SetBlockingContainers() and + // mojom::BlockingContainers for details on what this does. + virtual void SetBlockingContainers( + const std::vector<BlockingContainers>& all_blocking_containers) = 0; + // Blocks until the initial displays have been received, or if displays are // not automatically created until the connection to mus has been // established. @@ -217,6 +233,10 @@ class AURA_EXPORT WindowManagerDelegate { const ui::Event& event, std::unordered_map<std::string, std::vector<uint8_t>>* properties); + // Called when the mouse cursor is shown or hidden in response to a touch + // event or window manager call. + virtual void OnCursorTouchVisibleChanged(bool enabled) = 0; + virtual void OnWmPerformMoveLoop( Window* window, ui::mojom::MoveLoopSource source, @@ -238,6 +258,10 @@ class AURA_EXPORT WindowManagerDelegate { // window. virtual void OnWmDeactivateWindow(Window* window) = 0; + // Called when an event is blocked by a modal window. |window| is the modal + // window that blocked the event. + virtual void OnEventBlockedByModalWindow(Window* window); + protected: virtual ~WindowManagerDelegate() {} }; diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h index acf13fd17aa..4b734983e1e 100644 --- a/chromium/ui/aura/mus/window_mus.h +++ b/chromium/ui/aura/mus/window_mus.h @@ -14,10 +14,6 @@ #include "ui/aura/aura_export.h" #include "ui/aura/mus/mus_types.h" -namespace cc { -class SurfaceInfo; -} - namespace gfx { class Rect; class Transform; @@ -29,6 +25,12 @@ enum class OrderDirection; } } +namespace viz { +class FrameSinkId; +class LocalSurfaceId; +class SurfaceInfo; +} + namespace aura { class Window; @@ -60,6 +62,9 @@ class AURA_EXPORT WindowMus { virtual ~WindowMus() {} // Returns the WindowMus associated with |window|. + static const WindowMus* Get(const Window* window) { + return const_cast<const WindowMus*>(Get(const_cast<Window*>(window))); + } static WindowMus* Get(Window* window); Id server_id() const { return server_id_; } diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc index 4915a5e13db..3b937f13e8b 100644 --- a/chromium/ui/aura/mus/window_port_mus.cc +++ b/chromium/ui/aura/mus/window_port_mus.cc @@ -10,6 +10,7 @@ #include "ui/aura/client/transient_window_client.h" #include "ui/aura/env.h" #include "ui/aura/mus/client_surface_embedder.h" +#include "ui/aura/mus/hit_test_data_provider_aura.h" #include "ui/aura/mus/property_converter.h" #include "ui/aura/mus/window_tree_client.h" #include "ui/aura/mus/window_tree_client_delegate.h" @@ -107,11 +108,11 @@ std::unique_ptr<viz::ClientLayerTreeFrameSink> WindowPortMus::RequestLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) { - cc::mojom::CompositorFrameSinkPtrInfo sink_info; - cc::mojom::CompositorFrameSinkRequest sink_request = + viz::mojom::CompositorFrameSinkPtrInfo sink_info; + viz::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink_info); - cc::mojom::CompositorFrameSinkClientPtr client; - cc::mojom::CompositorFrameSinkClientRequest client_request = + viz::mojom::CompositorFrameSinkClientPtr client; + viz::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&client); constexpr bool enable_surface_synchronization = true; auto layer_tree_frame_sink = base::MakeUnique<viz::ClientLayerTreeFrameSink>( @@ -119,6 +120,7 @@ WindowPortMus::RequestLayerTreeFrameSink( gpu_memory_buffer_manager, nullptr /* shared_bitmap_manager */, nullptr /* synthetic_begin_frame_source */, std::move(sink_info), std::move(client_request), + base::MakeUnique<HitTestDataProviderAura>(window_), base::MakeUnique<viz::DefaultLocalSurfaceIdProvider>(), enable_surface_synchronization); window_tree_client_->AttachCompositorFrameSink( @@ -126,6 +128,12 @@ WindowPortMus::RequestLayerTreeFrameSink( return layer_tree_frame_sink; } +viz::FrameSinkId WindowPortMus::GetFrameSinkId() const { + if (embed_frame_sink_id_.is_valid()) + return embed_frame_sink_id_; + return viz::FrameSinkId(0, server_id()); +} + WindowPortMus::ServerChangeIdType WindowPortMus::ScheduleChange( const ServerChangeType type, const ServerChangeData& data) { @@ -293,7 +301,7 @@ void WindowPortMus::SetFrameSinkIdFromServer( const viz::FrameSinkId& frame_sink_id) { DCHECK(window_mus_type() == WindowMusType::TOP_LEVEL_IN_WM || window_mus_type() == WindowMusType::EMBED_IN_OWNER); - frame_sink_id_ = frame_sink_id; + embed_frame_sink_id_ = frame_sink_id; UpdatePrimarySurfaceInfo(); } @@ -311,7 +319,7 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId( // The newly generated frame by the embedder will block in the display // compositor until the child submits a corresponding CompositorFrame or a // deadline hits. - if (frame_sink_id_.is_valid()) + if (embed_frame_sink_id_.is_valid()) UpdatePrimarySurfaceInfo(); if (local_layer_tree_frame_sink_) @@ -322,19 +330,21 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId( void WindowPortMus::SetFallbackSurfaceInfo( const viz::SurfaceInfo& surface_info) { - if (!frame_sink_id_.is_valid()) { + if (!embed_frame_sink_id_.is_valid()) { // |primary_surface_info_| shold not be valid, since we didn't know the - // |frame_sink_id_|. + // |embed_frame_sink_id_|. DCHECK(!primary_surface_info_.is_valid()); - frame_sink_id_ = surface_info.id().frame_sink_id(); + embed_frame_sink_id_ = surface_info.id().frame_sink_id(); UpdatePrimarySurfaceInfo(); } // The frame sink id should never be changed. - DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_); + DCHECK_EQ(surface_info.id().frame_sink_id(), embed_frame_sink_id_); fallback_surface_info_ = surface_info; UpdateClientSurfaceEmbedder(); + if (window_->delegate()) + window_->delegate()->OnFirstSurfaceActivation(fallback_surface_info_); } void WindowPortMus::DestroyFromServer() { @@ -392,6 +402,10 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved( : ChangeSource::LOCAL; } +void WindowPortMus::AllocateLocalSurfaceId() { + local_surface_id_ = local_surface_id_allocator_.GenerateId(); +} + const viz::LocalSurfaceId& WindowPortMus::GetLocalSurfaceId() { return local_surface_id_; } @@ -451,6 +465,16 @@ void WindowPortMus::OnPreInit(Window* window) { } void WindowPortMus::OnDeviceScaleFactorChanged(float device_scale_factor) { + // TODO(fsamuel): If we don't have a LayerTreeFrameSinkLocal then we should + // let the window server know about the device scale factor change and + // the new LocalSurfaceId allocated. + if (last_device_scale_factor_ != device_scale_factor && + local_surface_id_.is_valid() && local_layer_tree_frame_sink_) { + last_device_scale_factor_ = device_scale_factor; + local_surface_id_ = local_surface_id_allocator_.GenerateId(); + local_layer_tree_frame_sink_->SetLocalSurfaceId(local_surface_id_); + } + if (window_->delegate()) window_->delegate()->OnDeviceScaleFactorChanged(device_scale_factor); } @@ -546,12 +570,20 @@ WindowPortMus::CreateLayerTreeFrameSink() { nullptr, aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager()); local_layer_tree_frame_sink_ = frame_sink->GetWeakPtr(); + local_surface_id_ = local_surface_id_allocator_.GenerateId(); return std::move(frame_sink); } viz::SurfaceId WindowPortMus::GetSurfaceId() const { - // This is only used by WindowPortLocal in unit tests. - return viz::SurfaceId(); + return viz::SurfaceId(embed_frame_sink_id_, local_surface_id_); +} + +void WindowPortMus::OnWindowAddedToRootWindow() {} + +void WindowPortMus::OnWillRemoveWindowFromRootWindow() {} + +void WindowPortMus::OnEventTargetingPolicyChanged() { + SetEventTargetingPolicy(window_->event_targeting_policy()); } void WindowPortMus::UpdatePrimarySurfaceInfo() { @@ -562,15 +594,13 @@ void WindowPortMus::UpdatePrimarySurfaceInfo() { return; } - if (!frame_sink_id_.is_valid() || !local_surface_id_.is_valid()) + if (!embed_frame_sink_id_.is_valid() || !local_surface_id_.is_valid()) return; primary_surface_info_ = viz::SurfaceInfo( - viz::SurfaceId(frame_sink_id_, local_surface_id_), + viz::SurfaceId(embed_frame_sink_id_, local_surface_id_), ScaleFactorForDisplay(window_), last_surface_size_in_pixels_); UpdateClientSurfaceEmbedder(); - if (window_->delegate()) - window_->delegate()->OnWindowSurfaceChanged(primary_surface_info_); } void WindowPortMus::UpdateClientSurfaceEmbedder() { diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h index 68936714fd1..b0d5d62cd92 100644 --- a/chromium/ui/aura/mus/window_port_mus.h +++ b/chromium/ui/aura/mus/window_port_mus.h @@ -93,11 +93,17 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager); + // WindowPort: + // Returns either the FrameSinkId set by window server or its server_id with + // the client id part 0. + viz::FrameSinkId GetFrameSinkId() const override; + private: friend class WindowPortMusTestApi; friend class WindowTreeClient; friend class WindowTreeClientPrivate; friend class WindowTreeHostMus; + friend class HitTestDataProviderAuraTest; using ServerChangeIdType = uint8_t; @@ -242,7 +248,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { void RemoveTransientChildFromServer(WindowMus* child) override; ChangeSource OnTransientChildAdded(WindowMus* child) override; ChangeSource OnTransientChildRemoved(WindowMus* child) override; - const viz::LocalSurfaceId& GetLocalSurfaceId() override; std::unique_ptr<WindowMusChangeData> PrepareForServerBoundsChange( const gfx::Rect& bounds) override; std::unique_ptr<WindowMusChangeData> PrepareForServerVisibilityChange( @@ -271,8 +276,11 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { std::unique_ptr<ui::PropertyData> data) override; std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override; viz::SurfaceId GetSurfaceId() const override; - void OnWindowAddedToRootWindow() override {} - void OnWillRemoveWindowFromRootWindow() override {} + void AllocateLocalSurfaceId() override; + const viz::LocalSurfaceId& GetLocalSurfaceId() override; + void OnWindowAddedToRootWindow() override; + void OnWillRemoveWindowFromRootWindow() override; + void OnEventTargetingPolicyChanged() override; void UpdatePrimarySurfaceInfo(); void UpdateClientSurfaceEmbedder(); @@ -287,13 +295,15 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { ServerChangeIdType next_server_change_id_ = 0; ServerChanges server_changes_; - viz::FrameSinkId frame_sink_id_; + // Only set when it is embedding another client inside. + viz::FrameSinkId embed_frame_sink_id_; viz::SurfaceInfo primary_surface_info_; viz::SurfaceInfo fallback_surface_info_; viz::LocalSurfaceId local_surface_id_; viz::LocalSurfaceIdAllocator local_surface_id_allocator_; + float last_device_scale_factor_ = 1.0f; gfx::Size last_surface_size_in_pixels_; ui::CursorData cursor_; diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc index 8d64f8deada..a06044dba27 100644 --- a/chromium/ui/aura/mus/window_tree_client.cc +++ b/chromium/ui/aura/mus/window_tree_client.cc @@ -72,14 +72,6 @@ namespace aura { namespace { -// This serves to document the places that rely on bounds changes to the -// root window being ignored. -constexpr bool kRootWindowBoundsChangesAreIgnored = true; - -Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) { - return (client_id << 16) | local_id; -} - inline uint16_t HiWord(uint32_t id) { return static_cast<uint16_t>((id >> 16) & 0xFFFF); } @@ -135,7 +127,7 @@ WindowTreeHostMus* GetWindowTreeHostMus(WindowMus* window) { } bool IsInternalProperty(const void* key) { - return key == client::kModalKey; + return key == client::kModalKey || key == client::kChildModalParentKey; } void SetWindowTypeFromProperties( @@ -158,21 +150,6 @@ float ScaleFactorForDisplay(Window* window) { return ui::GetScaleFactorForNativeView(window); } -void ConvertEventLocationToDip(int64_t display_id, ui::LocatedEvent* event) { - display::Screen* screen = display::Screen::GetScreen(); - display::Display display; - if (!screen->GetDisplayWithDisplayId(display_id, &display) || - display.device_scale_factor() == 1.f) { - return; - } - const gfx::Point host_location = - gfx::ConvertPointToDIP(display.device_scale_factor(), event->location()); - event->set_location(host_location); - const gfx::Point root_location = gfx::ConvertPointToDIP( - display.device_scale_factor(), event->root_location()); - event->set_root_location(root_location); -} - // Create and return a MouseEvent or TouchEvent from |event| if |event| is a // PointerEvent, otherwise return the copy of |event|. std::unique_ptr<ui::Event> MapEvent(const ui::Event& event) { @@ -200,6 +177,10 @@ void OnAckMustSucceed(bool success) { CHECK(success); } +Id GetServerIdForWindow(Window* window) { + return window ? WindowMus::Get(window)->server_id() : kInvalidServerId; +} + } // namespace WindowTreeClient::WindowTreeClient( @@ -210,7 +191,6 @@ WindowTreeClient::WindowTreeClient( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, bool create_discardable_memory) : connector_(connector), - client_id_(0), next_window_id_(1), next_change_id_(1), delegate_(delegate), @@ -290,9 +270,6 @@ WindowTreeClient::~WindowTreeClient() { } void WindowTreeClient::ConnectViaWindowTreeFactory() { - // The client id doesn't really matter, we use 101 purely for debugging. - client_id_ = 101; - ui::mojom::WindowTreeFactoryPtr factory; connector_->BindInterface(ui::mojom::kServiceName, &factory); ui::mojom::WindowTreePtr window_tree; @@ -368,8 +345,8 @@ void WindowTreeClient::Embed( void WindowTreeClient::AttachCompositorFrameSink( Id window_id, - cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::CompositorFrameSinkClientPtr client) { + viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, + viz::mojom::CompositorFrameSinkClientPtr client) { DCHECK(tree_); tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink), std::move(client)); @@ -390,6 +367,63 @@ bool WindowTreeClient::IsWindowKnown(aura::Window* window) { return windows_.count(window_mus->server_id()) > 0; } +void WindowTreeClient::ConvertPointerEventLocationToDip( + int64_t display_id, + WindowMus* window, + ui::LocatedEvent* event) const { + // PointerEvents shouldn't have the target set. + DCHECK(!event->target()); + if (window_manager_delegate_) { + ConvertPointerEventLocationToDipInWindowManager(display_id, window, event); + return; + } + display::Screen* screen = display::Screen::GetScreen(); + display::Display display; + // TODO(sky): this needs to take into account the ui display scale. + // http://crbug.com/758399. + if (!screen->GetDisplayWithDisplayId(display_id, &display) || + display.device_scale_factor() == 1.f) { + return; + } + const gfx::Point root_location = gfx::ConvertPointToDIP( + display.device_scale_factor(), event->root_location()); + event->set_root_location(root_location); + if (window) { + const gfx::Point host_location = gfx::ConvertPointToDIP( + display.device_scale_factor(), event->location()); + event->set_location(host_location); + } else { + // When there is no window force the root and location to be the same. They + // may differ it |window| was valid at the time of the event, but was since + // deleted. + event->set_location(root_location); + } +} + +void WindowTreeClient::ConvertPointerEventLocationToDipInWindowManager( + int64_t display_id, + WindowMus* window, + ui::LocatedEvent* event) const { + const WindowTreeHostMus* window_tree_host = + GetWindowTreeHostForDisplayId(display_id); + if (!window_tree_host) + return; + + ui::Event::DispatcherApi dispatcher_api(event); + if (window) { + dispatcher_api.set_target(window->GetWindow()); + } else { + // UpdateForRootTransform() in the case of no target uses |location_|. + // |location_| may be relative to a window that wasn't found. To ensure we + // convert from the root, reset |location_| to |root_location_|. + event->set_location_f(event->root_location_f()); + } + event->UpdateForRootTransform( + window_tree_host->GetInverseRootTransform(), + window_tree_host->GetInverseRootTransformForLocalEventCoordinates()); + dispatcher_api.set_target(nullptr); +} + InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching( const InFlightChange& change) { for (const auto& pair : in_flight_map_) { @@ -481,6 +515,20 @@ void WindowTreeClient::SetLocalPropertiesFromServerProperties( window->SetPropertyFromServer(pair.first, &pair.second); } +const WindowTreeHostMus* WindowTreeClient::GetWindowTreeHostForDisplayId( + int64_t display_id) const { + if (!window_manager_delegate_) + return nullptr; + + for (WindowMus* window : roots_) { + WindowTreeHostMus* window_tree_host = + static_cast<WindowTreeHostMus*>(window->GetWindow()->GetHost()); + if (window_tree_host->display_id() == display_id) + return window_tree_host; + } + return nullptr; +} + std::unique_ptr<WindowTreeHostMus> WindowTreeClient::CreateWindowTreeHost( WindowMusType window_mus_type, const ui::mojom::WindowData& window_data, @@ -567,28 +615,36 @@ void WindowTreeClient::OnConnectionLost() { bool WindowTreeClient::HandleInternalPropertyChanged(WindowMus* window, const void* key, int64_t old_value) { - if (key != client::kModalKey) - return false; - - const uint32_t change_id = - ScheduleInFlightChange(base::MakeUnique<InFlightSetModalTypeChange>( - window, static_cast<ui::ModalType>(old_value))); - tree_->SetModalType(change_id, window->server_id(), - window->GetWindow()->GetProperty(client::kModalKey)); - return true; + if (key == client::kModalKey) { + const uint32_t change_id = + ScheduleInFlightChange(base::MakeUnique<InFlightSetModalTypeChange>( + window, static_cast<ui::ModalType>(old_value))); + tree_->SetModalType(change_id, window->server_id(), + window->GetWindow()->GetProperty(client::kModalKey)); + return true; + } + if (key == client::kChildModalParentKey) { + const uint32_t change_id = + ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>( + 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; } void WindowTreeClient::OnEmbedImpl( ui::mojom::WindowTree* window_tree, - ClientSpecificId client_id, ui::mojom::WindowDataPtr root_data, int64_t display_id, Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - // WARNING: this is only called if WindowTreeClient was created as the - // result of an embedding. - client_id_ = client_id; WindowTreeConnectionEstablished(window_tree); DCHECK(roots_.empty()); @@ -601,19 +657,6 @@ void WindowTreeClient::OnEmbedImpl( delegate_->OnEmbed(std::move(window_tree_host)); } -void WindowTreeClient::OnSetDisplayRootDone( - Id window_id, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - // The only way SetDisplayRoot() should fail is if we've done something wrong. - CHECK(local_surface_id.has_value()); - WindowMus* window = GetWindowByServerId(window_id); - if (!window) - return; // Display was already deleted. - - ui::Compositor* compositor = window->GetWindow()->GetHost()->compositor(); - compositor->SetLocalSurfaceId(*local_surface_id); -} - WindowTreeHostMus* WindowTreeClient::WmNewDisplayAddedImpl( const display::Display& display, ui::mojom::WindowDataPtr root_data, @@ -713,7 +756,7 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) { if (window->server_id() != kInvalidServerId) return; - window->set_server_id(MakeTransportId(client_id_, next_window_id_++)); + window->set_server_id(next_window_id_++); RegisterWindowMus(window); DCHECK(window_manager_delegate_ || !IsRoot(window)); @@ -737,6 +780,11 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) { base::MakeUnique<CrashInFlightChange>(window, ChangeType::NEW_WINDOW)); tree_->NewWindow(change_id, window->server_id(), std::move(transport_properties)); + if (window->GetWindow()->event_targeting_policy() != + ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS) { + SetEventTargetingPolicy(window, + window->GetWindow()->event_targeting_policy()); + } if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) { WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window); std::unique_ptr<DisplayInitParams> display_init_params = @@ -755,7 +803,6 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) { // bounds changes are routed through OnWindowTreeHostBoundsWillChange()). // But the display is created with an initial bounds, and we need to push // that to the server. - DCHECK(kRootWindowBoundsChangesAreIgnored); ScheduleInFlightBoundsChange( window, gfx::Rect(), gfx::Rect( @@ -765,8 +812,7 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) { window_manager_client_->SetDisplayRoot( display, display_init_params->viewport_metrics.Clone(), display_init_params->is_primary_display, window->server_id(), - base::Bind(&WindowTreeClient::OnSetDisplayRootDone, - base::Unretained(this), window->server_id())); + base::Bind(&OnAckMustSucceed)); } } } @@ -816,7 +862,21 @@ void WindowTreeClient::OnWindowMusBoundsChanged(WindowMus* window, // OnWindowTreeHostBoundsWillChange(). Any bounds that happen here are a side // effect of those and can be ignored. if (IsRoot(window)) { - DCHECK(kRootWindowBoundsChangesAreIgnored); + // NOTE: this has to happen to here as during the call to + // OnWindowTreeHostBoundsWillChange() the compositor hasn't been updated + // yet. + if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) { + WindowTreeHost* window_tree_host = window->GetWindow()->GetHost(); + // |window_tree_host| may be null if this is called during creation of + // the window associated with the WindowTreeHostMus. + if (window_tree_host) { + viz::LocalSurfaceId local_surface_id = + window->GetOrAllocateLocalSurfaceId( + window_tree_host->GetBoundsInPixels().size()); + DCHECK(local_surface_id.is_valid()); + window_tree_host->compositor()->SetLocalSurfaceId(local_surface_id); + } + } return; } @@ -947,9 +1007,9 @@ std::set<Window*> WindowTreeClient::GetRoots() { } bool WindowTreeClient::WasCreatedByThisClient(const WindowMus* window) const { - // Windows created via CreateTopLevelWindow() are not owned by us, but have - // our client id. const_cast is required by set. - return HiWord(window->server_id()) == client_id_ && + // Windows created via CreateTopLevelWindow() are not owned by us, but don't + // have high-word set. const_cast is required by set. + return !HiWord(window->server_id()) && roots_.count(const_cast<WindowMus*>(window)) == 0; } @@ -1008,7 +1068,6 @@ void WindowTreeClient::SetEventTargetingPolicy( } void WindowTreeClient::OnEmbed( - ClientSpecificId client_id, ui::mojom::WindowDataPtr root_data, ui::mojom::WindowTreePtr tree, int64_t display_id, @@ -1025,8 +1084,7 @@ void WindowTreeClient::OnEmbed( MakeRequest(&window_manager_internal_client_)); window_manager_client_ = window_manager_internal_client_.get(); } - - OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data), display_id, + OnEmbedImpl(tree_ptr_.get(), std::move(root_data), display_id, focused_window_id, drawn, local_surface_id); } @@ -1334,7 +1392,8 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id, if (matches_pointer_watcher && has_pointer_watcher_) { DCHECK(event->IsPointerEvent()); std::unique_ptr<ui::Event> event_in_dip(ui::Event::Clone(*event)); - ConvertEventLocationToDip(display_id, event_in_dip->AsLocatedEvent()); + ConvertPointerEventLocationToDip(display_id, window, + event_in_dip->AsLocatedEvent()); delegate_->OnPointerEventObserved(*event_in_dip->AsPointerEvent(), window ? window->GetWindow() : nullptr); } @@ -1368,8 +1427,31 @@ 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<ui::Event> mapped_event = MapEvent(*event.get()); - DispatchEventToTarget(mapped_event.get(), window); - ack_handler.set_handled(mapped_event->handled()); + ui::Event* event_to_dispatch = mapped_event.get(); +// Ash wants the native events in one place (see ExtendedMouseWarpController). +// By using the constructor that takes a MouseEvent we ensure the MouseEvent +// has a NativeEvent that can be used to extract the pixel coordinates. +// +// TODO: this should really be covered by |root_location|. See 608547 for +// details. +#if defined(USE_OZONE) + std::unique_ptr<ui::MouseEvent> mapped_event_with_native; + if (mapped_event->type() == ui::ET_MOUSE_MOVED || + mapped_event->type() == ui::ET_MOUSE_DRAGGED) { + mapped_event_with_native = base::MakeUnique<ui::MouseEvent>( + static_cast<const base::NativeEvent&>(mapped_event.get())); + // MouseEvent(NativeEvent) sets the root_location to location. + mapped_event_with_native->set_root_location_f( + mapped_event->AsMouseEvent()->root_location_f()); + // |mapped_event| is now the NativeEvent. It's expected the location of the + // NativeEvent is the same as root_location. + mapped_event->AsMouseEvent()->set_location_f( + mapped_event->AsMouseEvent()->root_location_f()); + event_to_dispatch = mapped_event_with_native.get(); + } +#endif + DispatchEventToTarget(event_to_dispatch, window); + ack_handler.set_handled(event_to_dispatch->handled()); } void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event, @@ -1380,8 +1462,9 @@ void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event, if (!has_pointer_watcher_) return; - ConvertEventLocationToDip(display_id, event->AsLocatedEvent()); WindowMus* target_window = GetWindowByServerId(window_id); + ConvertPointerEventLocationToDip(display_id, target_window, + event->AsLocatedEvent()); delegate_->OnPointerEventObserved( *event->AsPointerEvent(), target_window ? target_window->GetWindow() : nullptr); @@ -1500,6 +1583,29 @@ void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) { } } +void WindowTreeClient::SetBlockingContainers( + const std::vector<BlockingContainers>& all_blocking_containers) { + std::vector<ui::mojom::BlockingContainersPtr> + transport_all_blocking_containers; + for (const BlockingContainers& blocking_containers : + all_blocking_containers) { + ui::mojom::BlockingContainersPtr transport_blocking_containers = + ui::mojom::BlockingContainers::New(); + // The |system_modal_container| must be specified, |min_container| may be + // null. + DCHECK(blocking_containers.system_modal_container); + transport_blocking_containers->system_modal_container_id = + GetServerIdForWindow(blocking_containers.system_modal_container); + transport_blocking_containers->min_container_id = + GetServerIdForWindow(blocking_containers.min_container); + transport_all_blocking_containers.push_back( + std::move(transport_blocking_containers)); + } + window_manager_client_->SetBlockingContainers( + std::move(transport_all_blocking_containers), + base::Bind(&OnAckMustSucceed)); +} + void WindowTreeClient::GetWindowManager( mojo::AssociatedInterfaceRequest<WindowManager> internal) { window_manager_internal_.reset( @@ -1537,8 +1643,7 @@ WindowTreeHostMusInitParams WindowTreeClient::CreateInitParamsForNewDisplay() { return init_params; } -void WindowTreeClient::OnConnect(ClientSpecificId client_id) { - client_id_ = client_id; +void WindowTreeClient::OnConnect() { got_initial_displays_ = true; if (window_manager_delegate_) window_manager_delegate_->OnWmConnected(); @@ -1811,6 +1916,20 @@ void WindowTreeClient::OnAccelerator(uint32_t ack_id, window_manager_client_->OnAcceleratorAck(ack_id, result, properties); } +void WindowTreeClient::OnCursorTouchVisibleChanged(bool enabled) { + if (window_manager_client_) + window_manager_delegate_->OnCursorTouchVisibleChanged(enabled); +} + +void WindowTreeClient::OnEventBlockedByModalWindow(Id window_id) { + if (!window_manager_delegate_) + return; + + WindowMus* window = GetWindowByServerId(window_id); + if (window) + window_manager_delegate_->OnEventBlockedByModalWindow(window->GetWindow()); +} + void WindowTreeClient::SetFrameDecorationValues( ui::mojom::FrameDecorationValuesPtr values) { if (window_manager_client_) { @@ -1855,11 +1974,6 @@ void WindowTreeClient::RemoveActivationParent(Window* window) { } } -void WindowTreeClient::ActivateNextWindow() { - if (window_manager_client_) - window_manager_client_->ActivateNextWindow(); -} - void WindowTreeClient::SetExtendedHitRegionForChildren( Window* window, const gfx::Insets& mouse_insets, @@ -1900,6 +2014,11 @@ void WindowTreeClient::SetGlobalOverrideCursor( window_manager_client_->WmSetGlobalOverrideCursor(std::move(cursor)); } +void WindowTreeClient::SetCursorTouchVisible(bool enabled) { + if (window_manager_client_) + window_manager_client_->WmSetCursorTouchVisible(enabled); +} + void WindowTreeClient::SetKeyEventsThatDontHideCursor( std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) { if (window_manager_client_) { @@ -1943,9 +2062,10 @@ void WindowTreeClient::AddDisplayReusingWindowTreeHost( WindowMus* display_root_window = WindowMus::Get(window_tree_host->window()); window_manager_client_->SetDisplayRoot( display, std::move(viewport_metrics), is_primary_display, - display_root_window->server_id(), - base::Bind(&WindowTreeClient::OnSetDisplayRootDone, - base::Unretained(this), display_root_window->server_id())); + display_root_window->server_id(), base::Bind(&OnAckMustSucceed)); + window_tree_host->compositor()->SetLocalSurfaceId( + display_root_window->GetOrAllocateLocalSurfaceId( + window_tree_host->GetBoundsInPixels().size())); } } @@ -2076,13 +2196,23 @@ void WindowTreeClient::OnWindowTreeHostMoveCursorToDisplayLocation( } } +void WindowTreeClient::OnWindowTreeHostConfineCursorToBounds( + const gfx::Rect& bounds_in_pixels, + int64_t display_id) { + DCHECK(window_manager_client_); + if (window_manager_client_) { + window_manager_client_->WmConfineCursorToBounds(bounds_in_pixels, + display_id); + } +} + std::unique_ptr<WindowPortMus> WindowTreeClient::CreateWindowPortForTopLevel( const std::map<std::string, std::vector<uint8_t>>* properties) { std::unique_ptr<WindowPortMus> window_port = base::MakeUnique<WindowPortMus>(this, WindowMusType::TOP_LEVEL); roots_.insert(window_port.get()); - window_port->set_server_id(MakeTransportId(client_id_, next_window_id_++)); + window_port->set_server_id(next_window_id_++); RegisterWindowMus(window_port.get()); std::unordered_map<std::string, std::vector<uint8_t>> transport_properties; diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h index fb4c741b568..4490bdcde2e 100644 --- a/chromium/ui/aura/mus/window_tree_client.h +++ b/chromium/ui/aura/mus/window_tree_client.h @@ -89,8 +89,8 @@ using EventResultCallback = base::Callback<void(ui::mojom::EventResult)>; // When WindowTreeClient is deleted all windows are deleted (and observers // notified). class AURA_EXPORT WindowTreeClient - : NON_EXPORTED_BASE(public ui::mojom::WindowTreeClient), - NON_EXPORTED_BASE(public ui::mojom::WindowManager), + : public ui::mojom::WindowTreeClient, + public ui::mojom::WindowManager, public CaptureSynchronizerDelegate, public FocusSynchronizerDelegate, public DragDropControllerHost, @@ -129,7 +129,6 @@ class AURA_EXPORT WindowTreeClient FocusSynchronizer* focus_synchronizer() { return focus_synchronizer_.get(); } bool connected() const { return tree_ != nullptr; } - ClientSpecificId client_id() const { return client_id_; } void SetCanFocus(Window* window, bool can_focus); void SetCanAcceptDrops(WindowMus* window, bool can_accept_drops); @@ -155,8 +154,8 @@ class AURA_EXPORT WindowTreeClient void AttachCompositorFrameSink( Id window_id, - cc::mojom::CompositorFrameSinkRequest compositor_frame_sink, - cc::mojom::CompositorFrameSinkClientPtr client); + viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, + viz::mojom::CompositorFrameSinkClientPtr client); bool IsRoot(WindowMus* window) const { return roots_.count(window) > 0; } @@ -207,6 +206,22 @@ class AURA_EXPORT WindowTreeClient bool IsWindowKnown(aura::Window* window); + // Updates the coordinates of |event| to be in DIPs. |window| is the source + // of the event, and may be null. A null |window| means either there is no + // local window the event is targeted at *or* |window| was valid at the time + // the event was generated at the server but was deleted locally before the + // event was received. + void ConvertPointerEventLocationToDip(int64_t display_id, + WindowMus* window, + ui::LocatedEvent* event) const; + + // Variant of ConvertPointerEventLocationToDip() that is used when in + // the window-manager. + void ConvertPointerEventLocationToDipInWindowManager( + int64_t display_id, + WindowMus* window, + ui::LocatedEvent* event) const; + // Returns the oldest InFlightChange that matches |change|. InFlightChange* GetOldestInFlightChangeMatching(const InFlightChange& change); @@ -236,6 +251,9 @@ class AURA_EXPORT WindowTreeClient WindowMus* window, const ui::mojom::WindowData& window_data); + const WindowTreeHostMus* GetWindowTreeHostForDisplayId( + int64_t display_id) const; + // Creates a new WindowTreeHostMus. std::unique_ptr<WindowTreeHostMus> CreateWindowTreeHost( WindowMusType window_mus_type, @@ -264,18 +282,12 @@ class AURA_EXPORT WindowTreeClient // OnEmbed() calls into this. Exposed as a separate function for testing. void OnEmbedImpl(ui::mojom::WindowTree* window_tree, - ClientSpecificId client_id, ui::mojom::WindowDataPtr root_data, int64_t display_id, Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id); - // Called once mus acks the call to SetDisplayRoot(). - void OnSetDisplayRootDone( - Id window_id, - const base::Optional<viz::LocalSurfaceId>& local_surface_id); - // Called by WmNewDisplayAdded(). WindowTreeHostMus* WmNewDisplayAddedImpl( const display::Display& display, @@ -331,7 +343,6 @@ class AURA_EXPORT WindowTreeClient // Overridden from WindowTreeClient: void OnEmbed( - ClientSpecificId client_id, ui::mojom::WindowDataPtr root, ui::mojom::WindowTreePtr tree, int64_t display_id, @@ -421,11 +432,13 @@ class AURA_EXPORT WindowTreeClient void OnDragDropDone() override; void OnChangeCompleted(uint32_t change_id, bool success) override; void RequestClose(uint32_t window_id) override; + void SetBlockingContainers( + const std::vector<BlockingContainers>& all_blocking_containers) override; void GetWindowManager( mojo::AssociatedInterfaceRequest<WindowManager> internal) override; // Overridden from WindowManager: - void OnConnect(ClientSpecificId client_id) override; + void OnConnect() override; void WmNewDisplayAdded( const display::Display& display, ui::mojom::WindowDataPtr root_data, @@ -468,6 +481,8 @@ class AURA_EXPORT WindowTreeClient void OnAccelerator(uint32_t ack_id, uint32_t accelerator_id, std::unique_ptr<ui::Event> event) override; + void OnCursorTouchVisibleChanged(bool enabled) override; + void OnEventBlockedByModalWindow(Id window_id) override; // Overridden from WindowManagerClient: void SetFrameDecorationValues( @@ -479,7 +494,6 @@ class AURA_EXPORT WindowTreeClient void RemoveAccelerator(uint32_t id) override; void AddActivationParent(Window* window) override; void RemoveActivationParent(Window* window) override; - void ActivateNextWindow() override; void SetExtendedHitRegionForChildren( Window* window, const gfx::Insets& mouse_insets, @@ -489,6 +503,7 @@ class AURA_EXPORT WindowTreeClient void SetCursorVisible(bool visible) override; void SetCursorSize(ui::CursorSize cursor_size) override; void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override; + void SetCursorTouchVisible(bool enabled) override; void SetKeyEventsThatDontHideCursor( std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) override; void RequestClose(Window* window) override; @@ -532,6 +547,8 @@ class AURA_EXPORT WindowTreeClient void OnWindowTreeHostMoveCursorToDisplayLocation( const gfx::Point& location_in_pixels, int64_t display_id) override; + void OnWindowTreeHostConfineCursorToBounds(const gfx::Rect& bounds_in_pixels, + int64_t display_id) override; std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel( const std::map<std::string, std::vector<uint8_t>>* properties) override; void OnWindowTreeHostCreated(WindowTreeHostMus* window_tree_host) override; @@ -573,10 +590,6 @@ class AURA_EXPORT WindowTreeClient // This may be null in tests. service_manager::Connector* connector_; - // This is set once and only once when we get OnEmbed(). It gives the unique - // id for this client. - ClientSpecificId client_id_; - // Id assigned to the next window created. ClientSpecificId next_window_id_; diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc index f6ba1a71dfc..9fb47c75742 100644 --- a/chromium/ui/aura/mus/window_tree_client_unittest.cc +++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc @@ -52,6 +52,7 @@ #include "ui/events/test/test_event_handler.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/transform.h" namespace aura { @@ -211,11 +212,35 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowTreeClientWmTestSurfaceSync, ::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(WindowTreeClientWmTestSurfaceSync, ClientSurfaceEmbedderOnValidEmbedding) { - Window window(nullptr); + 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, @@ -245,6 +270,7 @@ TEST_P(WindowTreeClientWmTestSurfaceSync, ClientSurfaceEmbedder* client_surface_embedder = window_port_mus->client_surface_embedder(); ASSERT_NE(nullptr, client_surface_embedder); + EXPECT_FALSE(delegate.last_surface_info().is_valid()); // Until the fallback surface fills the window, we will have gutter. { @@ -261,6 +287,9 @@ TEST_P(WindowTreeClientWmTestSurfaceSync, // client lib. This should cause the gutter to go away, eliminating overdraw. window_tree_client()->OnWindowSurfaceChanged( server_id(&window), window_port_mus->PrimarySurfaceInfoForTesting()); + EXPECT_TRUE(delegate.last_surface_info().is_valid()); + EXPECT_EQ(delegate.last_surface_info(), + window_port_mus->PrimarySurfaceInfoForTesting()); // The gutter is gone. ASSERT_EQ(nullptr, client_surface_embedder->BottomGutterForTesting()); @@ -718,41 +747,52 @@ class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate { : test_window_tree_(test_window_tree) {} ~InputEventBasicTestWindowDelegate() override {} - bool got_move() const { return got_move_; } - bool got_press() const { return got_press_; } - bool got_release() const { return got_release_; } + int move_count() const { return move_count_; } + int press_count() const { return press_count_; } + int release_count() const { return release_count_; } bool was_acked() const { return was_acked_; } const gfx::Point& last_event_location() const { return last_event_location_; } void set_event_id(uint32_t event_id) { event_id_ = event_id; } + bool last_mouse_event_had_native_event() const { + return last_mouse_event_had_native_event_; + } + const gfx::Point& last_native_event_location() const { + return last_native_event_location_; + } // TestWindowDelegate:: void OnMouseEvent(ui::MouseEvent* event) override { was_acked_ = test_window_tree_->WasEventAcked(event_id_); if (event->type() == ui::ET_MOUSE_MOVED) - got_move_ = true; + ++move_count_; else if (event->type() == ui::ET_MOUSE_PRESSED) - got_press_ = true; + ++press_count_; else if (event->type() == ui::ET_MOUSE_RELEASED) - got_release_ = true; + ++release_count_; last_event_location_ = event->location(); + last_mouse_event_had_native_event_ = event->HasNativeEvent(); + if (event->HasNativeEvent()) { + last_native_event_location_ = + ui::EventSystemLocationFromNative(event->native_event()); + } event->SetHandled(); } void OnTouchEvent(ui::TouchEvent* event) override { was_acked_ = test_window_tree_->WasEventAcked(event_id_); if (event->type() == ui::ET_TOUCH_PRESSED) - got_press_ = true; + ++press_count_; else if (event->type() == ui::ET_TOUCH_RELEASED) - got_release_ = true; + ++release_count_; last_event_location_ = event->location(); event->SetHandled(); } void reset() { was_acked_ = false; - got_move_ = false; - got_press_ = false; - got_release_ = false; + move_count_ = 0; + press_count_ = 0; + release_count_ = 0; last_event_location_ = gfx::Point(); event_id_ = 0; } @@ -760,11 +800,13 @@ class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate { private: TestWindowTree* test_window_tree_; bool was_acked_ = false; - bool got_move_ = false; - bool got_press_ = false; - bool got_release_ = false; + int move_count_ = 0; + int press_count_ = 0; + int release_count_ = false; gfx::Point last_event_location_; uint32_t event_id_ = 0; + bool last_mouse_event_had_native_event_ = false; + gfx::Point last_native_event_location_; DISALLOW_COPY_AND_ASSIGN(InputEventBasicTestWindowDelegate); }; @@ -775,7 +817,7 @@ class InputEventBasicTestEventHandler : public ui::test::TestEventHandler { : target_window_(target_window) {} ~InputEventBasicTestEventHandler() override {} - bool got_move() const { return got_move_; } + int move_count() const { return move_count_; } const gfx::Point& last_event_location() const { return last_event_location_; } void set_event_id(uint32_t event_id) { event_id_ = event_id; } @@ -783,21 +825,21 @@ class InputEventBasicTestEventHandler : public ui::test::TestEventHandler { void OnMouseEvent(ui::MouseEvent* event) override { if (event->target() == target_window_) { if (event->type() == ui::ET_MOUSE_MOVED) - got_move_ = true; + ++move_count_; last_event_location_ = event->location(); event->SetHandled(); } } void reset() { - got_move_ = false; + move_count_ = 0; last_event_location_ = gfx::Point(); event_id_ = 0; } private: Window* target_window_ = nullptr; - bool got_move_ = false; + int move_count_ = 0; gfx::Point last_event_location_; uint32_t event_id_ = 0; @@ -822,7 +864,7 @@ TEST_F(WindowTreeClientClientTest, InputEventBasic) { top_level->AddChild(&child); child.SetBounds(gfx::Rect(10, 10, 100, 100)); child.Show(); - EXPECT_FALSE(window_delegate.got_move()); + EXPECT_EQ(0, window_delegate.move_count()); EXPECT_FALSE(window_delegate.was_acked()); const gfx::Point event_location_in_child(2, 3); const uint32_t event_id = 1; @@ -836,7 +878,7 @@ TEST_F(WindowTreeClientClientTest, InputEventBasic) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate.got_move()); + EXPECT_EQ(1, window_delegate.move_count()); EXPECT_FALSE(window_delegate.was_acked()); EXPECT_EQ(event_location_in_child, window_delegate.last_event_location()); } @@ -857,7 +899,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPointerEvent) { top_level->AddChild(&child); child.SetBounds(gfx::Rect(10, 10, 100, 100)); child.Show(); - EXPECT_FALSE(window_delegate.got_move()); + EXPECT_EQ(0, window_delegate.move_count()); const gfx::Point event_location(2, 3); const uint32_t event_id = 1; window_delegate.set_event_id(event_id); @@ -871,7 +913,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPointerEvent) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate.got_move()); + EXPECT_EQ(1, window_delegate.move_count()); EXPECT_EQ(event_location, window_delegate.last_event_location()); } @@ -899,8 +941,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) { child2.SetBounds(gfx::Rect(20, 30, 100, 100)); child2.Show(); - EXPECT_FALSE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(0, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); // child1 has a targeter set and event_location is (50, 60), child2 // should get the event even though mus-ws wants to send to child1. @@ -917,8 +959,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_FALSE(window_delegate1.got_move()); - EXPECT_TRUE(window_delegate2.got_move()); + EXPECT_EQ(0, window_delegate1.move_count()); + EXPECT_EQ(1, window_delegate2.move_count()); EXPECT_EQ(gfx::Point(30, 30), window_delegate2.last_event_location()); window_delegate1.reset(); window_delegate2.reset(); @@ -938,8 +980,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(1, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location()); } @@ -967,8 +1009,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) { child2.SetBounds(gfx::Rect(20, 30, 100, 100)); child2.Show(); - EXPECT_FALSE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(0, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); // child1 has a custom targeter set which would always return itself as the // target window therefore event should go to child1 unlike @@ -986,8 +1028,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(1, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location()); window_delegate1.reset(); window_delegate2.reset(); @@ -1003,8 +1045,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(1, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); EXPECT_EQ(gfx::Point(70, 90), window_delegate1.last_event_location()); } @@ -1037,8 +1079,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) { child2->SetBounds(gfx::Rect(20, 30, 100, 100)); child2->Show(); - EXPECT_FALSE(window_delegate1->got_move()); - EXPECT_FALSE(window_delegate2->got_move()); + EXPECT_EQ(0, window_delegate1->move_count()); + EXPECT_EQ(0, window_delegate2->move_count()); // child1 has a custom targeter set which would always return itself as the // target window therefore event should go to child1. @@ -1055,8 +1097,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1->got_move()); - EXPECT_FALSE(window_delegate2->got_move()); + EXPECT_EQ(1, window_delegate1->move_count()); + EXPECT_EQ(0, window_delegate2->move_count()); EXPECT_EQ(gfx::Point(50, 60), window_delegate1->last_event_location()); window_delegate1->reset(); window_delegate2->reset(); @@ -1076,8 +1118,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_FALSE(window_delegate1->got_move()); - EXPECT_TRUE(window_delegate2->got_move()); + EXPECT_EQ(0, window_delegate1->move_count()); + EXPECT_EQ(1, window_delegate2->move_count()); EXPECT_EQ(gfx::Point(30, 30), window_delegate2->last_event_location()); child2.reset(); child1.reset(); @@ -1104,8 +1146,8 @@ TEST_F(WindowTreeClientClientTest, InputEventRootWindow) { child.SetBounds(gfx::Rect(10, 10, 100, 100)); child.Show(); - EXPECT_FALSE(root_handler.got_move()); - EXPECT_FALSE(child_delegate.got_move()); + EXPECT_EQ(0, root_handler.move_count()); + EXPECT_EQ(0, child_delegate.move_count()); const gfx::Point event_location_in_child(20, 30); const uint32_t event_id = 1; @@ -1121,9 +1163,9 @@ TEST_F(WindowTreeClientClientTest, InputEventRootWindow) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(root_handler.got_move()); + EXPECT_EQ(1, root_handler.move_count()); EXPECT_EQ(gfx::Point(20, 30), root_handler.last_event_location()); - EXPECT_FALSE(child_delegate.got_move()); + EXPECT_EQ(0, child_delegate.move_count()); EXPECT_EQ(gfx::Point(), child_delegate.last_event_location()); } @@ -1145,7 +1187,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { child.SetBounds(gfx::Rect(10, 10, 100, 100)); child.Show(); - EXPECT_FALSE(window_delegate.got_press()); + EXPECT_EQ(0, window_delegate.press_count()); EXPECT_FALSE(env->IsMouseButtonDown()); EXPECT_FALSE(env->mouse_button_flags()); EXPECT_EQ(gfx::Point(), env->last_mouse_location()); @@ -1154,7 +1196,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { 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(), + ui::ET_POINTER_DOWN, event_location, event_location, ui::EF_LEFT_MOUSE_BUTTON, 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), ui::EventTimeForNow()); @@ -1164,7 +1206,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate.got_press()); + EXPECT_EQ(1, window_delegate.press_count()); EXPECT_TRUE(env->IsMouseButtonDown()); EXPECT_EQ(1024, env->mouse_button_flags()); // ui::EF_LEFT_MOUSE_BUTTON EXPECT_EQ(event_location, env->last_mouse_location()); @@ -1174,7 +1216,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { event_id = 2; window_delegate.set_event_id(event_id); ui::PointerEvent pointer_event_up( - ui::ET_POINTER_UP, event_location1, gfx::Point(), + 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()); @@ -1187,7 +1229,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { // aura::Env, location shouldn't be updated. EXPECT_EQ(ui::mojom::EventResult::UNHANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_FALSE(window_delegate.got_release()); + EXPECT_EQ(0, window_delegate.release_count()); EXPECT_FALSE(env->IsMouseButtonDown()); EXPECT_FALSE(env->mouse_button_flags()); EXPECT_EQ(event_location, env->last_mouse_location()); @@ -1211,7 +1253,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) { child.SetBounds(gfx::Rect(10, 10, 100, 100)); child.Show(); - EXPECT_FALSE(window_delegate.got_press()); + EXPECT_EQ(0, window_delegate.press_count()); EXPECT_FALSE(env->is_touch_down()); const gfx::Point event_location(2, 3); @@ -1227,7 +1269,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate.got_press()); + EXPECT_EQ(1, window_delegate.press_count()); EXPECT_TRUE(env->is_touch_down()); window_delegate.reset(); @@ -1246,7 +1288,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) { // aura::Env. EXPECT_EQ(ui::mojom::EventResult::UNHANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_FALSE(window_delegate.got_release()); + EXPECT_EQ(0, window_delegate.release_count()); EXPECT_FALSE(env->is_touch_down()); } @@ -1865,7 +1907,7 @@ class CloseWindowWindowTreeHostObserver : public aura::WindowTreeHostObserver { bool root_destroyed() const { return root_destroyed_; } // aura::WindowTreeHostObserver:: - void OnHostCloseRequested(const aura::WindowTreeHost* host) override { + void OnHostCloseRequested(aura::WindowTreeHost* host) override { root_destroyed_ = true; } @@ -2306,6 +2348,7 @@ TEST_F(WindowTreeClientWmTest, ManuallyCreateDisplay) { WindowTreeHostMusInitParams init_params = WindowTreeClientPrivate(window_tree_client_impl()) .CallCreateInitParamsForNewDisplay(); + init_params.display_id = display_params->display->id(); init_params.display_init_params = std::move(display_params); WindowTreeHostMus window_tree_host(std::move(init_params)); window_tree_host.InitHost(); @@ -2379,7 +2422,9 @@ TEST_F(WindowTreeClientClientTestHighDPI, PointerEventsInDip) { // Delegate received the event in Dips. const ui::PointerEvent* last_event = last_event_observed(); ASSERT_TRUE(last_event); - EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, location_pixels), + // NOTE: the root and location are the same as there was no window supplied to + // OnPointerEventObserved(). + EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, root_location_pixels), last_event->location()); EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, root_location_pixels), last_event->root_location()); @@ -2416,8 +2461,8 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) { child2.SetBounds(gfx::Rect(20, 30, 100, 100)); child2.Show(); - EXPECT_FALSE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(0, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); // child1 has a custom targeter set which would always return itself as the // target window therefore event should go to child1 and should be in dip. @@ -2425,19 +2470,26 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) { uint32_t event_id = 1; window_delegate1.set_event_id(event_id); window_delegate2.set_event_id(event_id); - std::unique_ptr<ui::Event> ui_event( - new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_pixels, - gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); + std::unique_ptr<ui::Event> ui_event(new ui::MouseEvent( + ui::ET_MOUSE_MOVED, event_location_in_pixels, event_location_in_pixels, + ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( event_id, server_id(&child1), window_tree_host.display_id(), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(1, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); const gfx::Point event_location_in_dip(25, 30); EXPECT_EQ(event_location_in_dip, window_delegate1.last_event_location()); +#if defined(USE_OZONE) + // For ozone there should be NativeEvent. + EXPECT_TRUE(window_delegate1.last_mouse_event_had_native_event()); + // And the location of the NativeEvent should be in pixels. + EXPECT_EQ(event_location_in_pixels, + window_delegate1.last_native_event_location()); +#endif window_delegate1.reset(); window_delegate2.reset(); @@ -2451,8 +2503,8 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) { EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); - EXPECT_TRUE(window_delegate1.got_move()); - EXPECT_FALSE(window_delegate2.got_move()); + EXPECT_EQ(1, window_delegate1.move_count()); + EXPECT_EQ(0, window_delegate2.move_count()); gfx::Point transformed_event_location_in_dip(event_location_in_dip.x() + 20, event_location_in_dip.y() + 30); EXPECT_EQ(transformed_event_location_in_dip, @@ -2473,4 +2525,76 @@ TEST_F(WindowTreeClientDestructionTest, Shutdown) { window2.Init(ui::LAYER_NOT_DRAWN); } +TEST_F(WindowTreeClientWmTest, ObservedPointerEvents) { + const gfx::Rect bounds(1, 2, 101, 102); + std::unique_ptr<DisplayInitParams> display_params = + base::MakeUnique<DisplayInitParams>(); + const int64_t display_id = 201; + float device_scale_factor = 2.0f; + float ui_scale_factor = 1.5f; + display_params->display = base::MakeUnique<display::Display>(display_id); + display_params->display->set_bounds(bounds); + display_params->viewport_metrics.bounds_in_pixels = bounds; + display_params->viewport_metrics.device_scale_factor = device_scale_factor; + display_params->viewport_metrics.ui_scale_factor = ui_scale_factor; + WindowTreeHostMusInitParams init_params = + WindowTreeClientPrivate(window_tree_client_impl()) + .CallCreateInitParamsForNewDisplay(); + init_params.display_id = display_id; + init_params.display_init_params = std::move(display_params); + + WindowTreeHostMus window_tree_host(std::move(init_params)); + window_tree_host.InitHost(); + gfx::Transform scale_transform; + scale_transform.Scale(ui_scale_factor, ui_scale_factor); + window_tree_host.window()->SetTransform(scale_transform); + window_tree_host.compositor()->SetScaleAndSize(device_scale_factor, + bounds.size()); + + // Start a pointer watcher for all events excluding move events. + window_tree_client_impl()->StartPointerWatcher(false /* want_moves */); + + // Simulate the server sending an observed event. + const gfx::Point location_pixels(10, 12); + const gfx::Point root_location_pixels(14, 16); + std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent( + ui::ET_POINTER_DOWN, location_pixels, root_location_pixels, + ui::EF_CONTROL_DOWN, 0, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1), + base::TimeTicks())); + std::unique_ptr<ui::PointerEvent> pointer_event_down2( + ui::Event::Clone(*pointer_event_down).release()->AsPointerEvent()); + window_tree_client()->OnPointerEventObserved(std::move(pointer_event_down), + 0u, display_id); + + ASSERT_FALSE(observed_pointer_events().empty()); + const ui::PointerEvent* last_event = observed_pointer_events().back().get(); + ASSERT_TRUE(last_event); + EXPECT_EQ(nullptr, last_event->target()); + // NOTE: the root and location are the same as there was no window supplied to + // OnPointerEventObserved(). + EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor, + root_location_pixels), + last_event->location()); + EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor, + root_location_pixels), + last_event->root_location()); + + observed_pointer_events().clear(); + window_tree_client()->OnPointerEventObserved( + std::move(pointer_event_down2), + WindowMus::Get(window_tree_host.window())->server_id(), display_id); + ASSERT_FALSE(observed_pointer_events().empty()); + last_event = observed_pointer_events().back().get(); + ASSERT_TRUE(last_event); + EXPECT_EQ(nullptr, last_event->target()); + // |location| from the server has already had |ui_scale_factor| applied, so + // it won't be reapplied here. + EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor, location_pixels), + last_event->location()); + EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor, + root_location_pixels), + last_event->root_location()); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc index a529a0bcc3a..927258842c2 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.cc +++ b/chromium/ui/aura/mus/window_tree_host_mus.cc @@ -41,8 +41,11 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params) delegate_(init_params.window_tree_client) { gfx::Rect bounds_in_pixels; display_init_params_ = std::move(init_params.display_init_params); - if (display_init_params_) + if (display_init_params_) { bounds_in_pixels = display_init_params_->viewport_metrics.bounds_in_pixels; + if (display_init_params_->display) + DCHECK_EQ(display_id_, display_init_params_->display->id()); + } window()->SetProperty(kWindowTreeHostMusKey, this); // TODO(sky): find a cleaner way to set this! Better solution is to likely // have constructor take aura::Window. @@ -84,6 +87,12 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params) // Mus windows are assumed hidden. compositor()->SetVisible(false); + + if (window_mus->window_mus_type() == + WindowMusType::DISPLAY_MANUALLY_CREATED) { + compositor()->SetLocalSurfaceId( + window_mus->GetOrAllocateLocalSurfaceId(bounds_in_pixels.size())); + } } WindowTreeHostMus::~WindowTreeHostMus() { @@ -151,6 +160,12 @@ void WindowTreeHostMus::CancelWindowMove() { delegate_->OnWindowTreeHostCancelWindowMove(this); } +void WindowTreeHostMus::ConfineCursorToBounds( + const gfx::Rect& bounds_in_pixels) { + delegate_->OnWindowTreeHostConfineCursorToBounds(bounds_in_pixels, + display_id_); +} + display::Display WindowTreeHostMus::GetDisplay() const { display::Display display; display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_, &display); @@ -195,13 +210,23 @@ void WindowTreeHostMus::OnCloseRequest() { void WindowTreeHostMus::MoveCursorToScreenLocationInPixels( const gfx::Point& location_in_pixels) { - gfx::Point screen_location_in_pixels = location_in_pixels; - gfx::Point location = GetLocationOnScreenInPixels(); - screen_location_in_pixels.Offset(-location.x(), -location.y()); - delegate_->OnWindowTreeHostMoveCursorToDisplayLocation( - screen_location_in_pixels, display_id_); + // |location_in_pixels| is relative to the display. + delegate_->OnWindowTreeHostMoveCursorToDisplayLocation(location_in_pixels, + display_id_); +} - Env::GetInstance()->set_last_mouse_location(location_in_pixels); +gfx::Transform WindowTreeHostMus::GetRootTransformForLocalEventCoordinates() + const { + if (WindowMus::Get(window())->window_mus_type() != + WindowMusType::DISPLAY_MANUALLY_CREATED) { + return WindowTreeHost::GetRootTransformForLocalEventCoordinates(); + } + // Local events already have the transform set on the window applied, so + // don't apply it again. + gfx::Transform transform; + const float scale = window()->layer()->device_scale_factor(); + transform.Scale(scale, scale); + return transform; } } // namespace aura diff --git a/chromium/ui/aura/mus/window_tree_host_mus.h b/chromium/ui/aura/mus/window_tree_host_mus.h index 764a7b0e91d..2ab21f4c626 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.h +++ b/chromium/ui/aura/mus/window_tree_host_mus.h @@ -80,6 +80,9 @@ class AURA_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform { // PerformWindowMove(). void CancelWindowMove(); + // Tells the window manager to confine the cursor to these specific bounds. + void ConfineCursorToBounds(const gfx::Rect& pixel_bounds); + // Used during initial setup. Returns the DisplayInitParams // supplied to the constructor. std::unique_ptr<DisplayInitParams> ReleaseDisplayInitParams(); @@ -98,6 +101,7 @@ class AURA_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform { void OnCloseRequest() override; void MoveCursorToScreenLocationInPixels( const gfx::Point& location_in_pixels) override; + gfx::Transform GetRootTransformForLocalEventCoordinates() const override; private: int64_t display_id_; 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 4ea7c2bf60c..b80e3389182 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h +++ b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h @@ -76,6 +76,12 @@ class AURA_EXPORT WindowTreeHostMusDelegate { const gfx::Point& location_in_pixels, int64_t display_id) = 0; + // Called to confine the cursor to a set of bounds in pixels. Only available + // to the window manager. + virtual void OnWindowTreeHostConfineCursorToBounds( + const gfx::Rect& bounds_in_pixels, + int64_t display_id) = 0; + // Called when a WindowTreeHostMus is created without a WindowPort. // TODO: this should take an unordered_map, see http://crbug.com/670515. virtual std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel( |