diff options
Diffstat (limited to 'chromium/ui/aura')
53 files changed, 1307 insertions, 772 deletions
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn index 0e63f4b6fb1..04f009d70b7 100644 --- a/chromium/ui/aura/BUILD.gn +++ b/chromium/ui/aura/BUILD.gn @@ -67,6 +67,7 @@ jumbo_component("aura") { "mus/window_tree_host_mus.h", "mus/window_tree_host_mus_delegate.h", "mus/window_tree_host_mus_init_params.h", + "scoped_keyboard_hook.h", "scoped_window_targeter.h", "window.h", "window_delegate.h", @@ -126,6 +127,7 @@ jumbo_component("aura") { "mus/window_tree_client_delegate.cc", "mus/window_tree_host_mus.cc", "mus/window_tree_host_mus_init_params.cc", + "scoped_keyboard_hook.cc", "scoped_window_targeter.cc", "window.cc", "window_event_dispatcher.cc", @@ -155,6 +157,7 @@ jumbo_component("aura") { "//mojo/public/cpp/system", "//net", "//services/service_manager/public/cpp", + "//services/ui/common:mus_common", "//services/ui/public/cpp", "//services/ui/public/interfaces", "//skia", @@ -176,10 +179,6 @@ jumbo_component("aura") { "//ui/compositor", ] - data_deps = [ - "//services/ui", - ] - if (use_x11) { deps += [ "//ui/events/platform/x11", @@ -268,6 +267,7 @@ jumbo_static_library("test_support") { public_deps = [ ":aura", + "//services/ui/common:mus_common", # Must be public as headers include ui_features.h. "//ui/base:ui_features", diff --git a/chromium/ui/aura/DEPS b/chromium/ui/aura/DEPS index 7a319fed221..8deffa55def 100644 --- a/chromium/ui/aura/DEPS +++ b/chromium/ui/aura/DEPS @@ -11,7 +11,8 @@ include_rules = [ "+mojo/public/cpp/bindings", "+net/base/filename_util.h", "+services/service_manager/public/cpp", - "+services/service_manager/public/interfaces", + "+services/service_manager/public/mojom", + "+services/ui/common", "+services/ui/public/interfaces", "+skia/ext", "+third_party/skia", diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc index 618b51e3121..c171556d287 100644 --- a/chromium/ui/aura/client/aura_constants.cc +++ b/chromium/ui/aura/client/aura_constants.cc @@ -73,6 +73,7 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(base::string16, kTitleKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0); DEFINE_UI_CLASS_PROPERTY_KEY(SkColor, kTopViewColor, SK_ColorTRANSPARENT); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr); +DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowCornerRadiusKey, -1); DEFINE_UI_CLASS_PROPERTY_KEY(ui::mojom::WindowType, kWindowTypeKey, ui::mojom::WindowType::UNKNOWN); diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h index 3730ab710ee..f0f8b6cbf53 100644 --- a/chromium/ui/aura/client/aura_constants.h +++ b/chromium/ui/aura/client/aura_constants.h @@ -152,6 +152,10 @@ AURA_EXPORT extern const WindowProperty<gfx::ImageSkia*>* const kWindowIconKey; // Indicates the type of embedding within the given window. AURA_EXPORT extern const WindowProperty<WindowEmbedType>* const kEmbedType; +// The corner radius of a window in DIPs. Currently only used for shadows. +// Default is -1, meaning "unspecified". 0 Ensures corners are square. +AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey; + AURA_EXPORT extern const WindowProperty<ui::mojom::WindowType>* const kWindowTypeKey; diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc index 08d1d4db88a..b62fcc15aba 100644 --- a/chromium/ui/aura/env.cc +++ b/chromium/ui/aura/env.cc @@ -25,8 +25,10 @@ #include "ui/events/platform/platform_event_source.h" #if defined(USE_OZONE) +#include "ui/gfx/client_native_pixmap_factory.h" #include "ui/ozone/public/client_native_pixmap_factory_ozone.h" #include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/ozone_switches.h" #endif namespace aura { @@ -163,9 +165,6 @@ Env::Env(Mode mode) is_touch_down_(false), get_last_mouse_location_from_mus_(mode_ == Mode::MUS), input_state_lookup_(InputStateLookup::Create()), -#if defined(USE_OZONE) - native_pixmap_factory_(ui::CreateClientNativePixmapFactoryOzone()), -#endif context_factory_(nullptr), context_factory_private_(nullptr) { DCHECK(lazy_tls_ptr.Pointer()->Get() == NULL); @@ -173,13 +172,13 @@ Env::Env(Mode mode) } void Env::Init() { +#if defined(USE_OZONE) + ui::CreateClientNativePixmapFactoryOzone(); + DCHECK(gfx::ClientNativePixmapFactory::GetInstance()); +#endif if (mode_ == Mode::MUS) { EnableMusOSExchangeDataProvider(); EnableMusOverrideInputInjector(); -#if defined(USE_OZONE) - // Required by all Aura-using clients of services/ui - gfx::ClientNativePixmapFactory::SetInstance(native_pixmap_factory_.get()); -#endif return; } @@ -193,8 +192,9 @@ void Env::Init() { // instead of checking flags here. params.single_process = command_line->HasSwitch("single-process") || command_line->HasSwitch("in-process-gpu"); + params.using_mojo = command_line->HasSwitch(switches::kEnableDrmMojo); + ui::OzonePlatform::InitializeForUI(params); - gfx::ClientNativePixmapFactory::SetInstance(native_pixmap_factory_.get()); #endif if (!ui::PlatformEventSource::GetInstance()) event_source_ = ui::PlatformEventSource::CreateDefault(); diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h index bf0e401979b..bc615fdb3a1 100644 --- a/chromium/ui/aura/env.h +++ b/chromium/ui/aura/env.h @@ -26,12 +26,6 @@ namespace base { class UnguessableToken; } -#if defined(USE_OZONE) -namespace gfx { -class ClientNativePixmapFactory; -} -#endif - namespace mojo { template <typename MojoInterface> class InterfacePtr; @@ -214,12 +208,6 @@ class AURA_EXPORT Env : public ui::EventTarget, std::unique_ptr<InputStateLookup> input_state_lookup_; std::unique_ptr<ui::PlatformEventSource> event_source_; -#if defined(USE_OZONE) - // Factory for pixmaps that can use be transported from the client to the GPU - // process using a low-level ozone-provided platform specific mechanism. - std::unique_ptr<gfx::ClientNativePixmapFactory> native_pixmap_factory_; -#endif - ui::ContextFactory* context_factory_; ui::ContextFactoryPrivate* context_factory_private_; diff --git a/chromium/ui/aura/env_input_state_controller.cc b/chromium/ui/aura/env_input_state_controller.cc index 6807055790b..0478abf599c 100644 --- a/chromium/ui/aura/env_input_state_controller.cc +++ b/chromium/ui/aura/env_input_state_controller.cc @@ -47,7 +47,7 @@ void EnvInputStateController::UpdateStateForTouchEvent( case ui::ET_TOUCH_CANCELLED: if (!event.HasNativeEvent()) break; - // fallthrough + FALLTHROUGH; case ui::ET_TOUCH_RELEASED: touch_ids_down_ = (touch_ids_down_ | (1 << event.pointer_details().id)) ^ (1 << event.pointer_details().id); diff --git a/chromium/ui/aura/hit_test_data_provider_aura.cc b/chromium/ui/aura/hit_test_data_provider_aura.cc index 1b35ed642b4..0f7600aae12 100644 --- a/chromium/ui/aura/hit_test_data_provider_aura.cc +++ b/chromium/ui/aura/hit_test_data_provider_aura.cc @@ -44,8 +44,8 @@ HitTestDataProviderAura::HitTestDataProviderAura(aura::Window* window) HitTestDataProviderAura::~HitTestDataProviderAura() {} -viz::mojom::HitTestRegionListPtr HitTestDataProviderAura::GetHitTestData() - const { +viz::mojom::HitTestRegionListPtr HitTestDataProviderAura::GetHitTestData( + const viz::CompositorFrame& compositor_frame) const { const ui::mojom::EventTargetingPolicy event_targeting_policy = window_->event_targeting_policy(); if (!window_->IsVisible() || @@ -58,6 +58,7 @@ viz::mojom::HitTestRegionListPtr HitTestDataProviderAura::GetHitTestData() ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY ? viz::mojom::kHitTestIgnore : viz::mojom::kHitTestMine; + // TODO(crbug.com/805416): Use pixels instead of DIP units for bounds. hit_test_region_list->bounds = window_->bounds(); GetHitTestDataRecursively(window_, hit_test_region_list.get()); diff --git a/chromium/ui/aura/hit_test_data_provider_aura.h b/chromium/ui/aura/hit_test_data_provider_aura.h index 9993a31ae2c..5887e821702 100644 --- a/chromium/ui/aura/hit_test_data_provider_aura.h +++ b/chromium/ui/aura/hit_test_data_provider_aura.h @@ -22,7 +22,8 @@ class AURA_EXPORT HitTestDataProviderAura : public viz::HitTestDataProvider { ~HitTestDataProviderAura() override; // HitTestDataProvider: - viz::mojom::HitTestRegionListPtr GetHitTestData() const override; + viz::mojom::HitTestRegionListPtr GetHitTestData( + const viz::CompositorFrame& compositor_frame) const override; private: // Recursively walks the children of |window| and uses |window|'s diff --git a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc index b157f28fc7d..96a6d82decd 100644 --- a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc +++ b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc @@ -118,6 +118,7 @@ class HitTestDataProviderAuraTest : public test::AuraTestBaseMus { root_->AddChild(window2_); root_->AddChild(window3_); + compositor_frame_ = viz::CompositorFrame(); hit_test_data_provider_ = std::make_unique<HitTestDataProviderAura>(root()); } @@ -130,6 +131,7 @@ class HitTestDataProviderAuraTest : public test::AuraTestBaseMus { Window* window2() { return window2_; } Window* window3() { return window3_; } Window* window4() { return window4_; } + viz::CompositorFrame compositor_frame_; private: std::unique_ptr<Window> root_; @@ -146,7 +148,8 @@ class HitTestDataProviderAuraTest : public test::AuraTestBaseMus { // 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(); + const auto hit_test_data_1 = + hit_test_data_provider()->GetHitTestData(compositor_frame_); 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()); @@ -164,7 +167,8 @@ TEST_F(HitTestDataProviderAuraTest, Stacking) { } root()->StackChildAbove(window2(), window3()); - const auto hit_test_data_2 = hit_test_data_provider()->GetHitTestData(); + const auto hit_test_data_2 = + hit_test_data_provider()->GetHitTestData(compositor_frame_); 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()); @@ -186,8 +190,9 @@ TEST_F(HitTestDataProviderAuraTest, Stacking) { // Tests that the hit-test regions get expanded with a custom event targeter. TEST_F(HitTestDataProviderAuraTest, CustomTargeter) { window3()->SetEventTargeter(std::make_unique<TestWindowTargeter>()); - window2()->set_embed_frame_sink_id(viz::FrameSinkId(1, 2)); - const auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + window2()->SetEmbedFrameSinkId(viz::FrameSinkId(1, 2)); + const auto hit_test_data = + hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); EXPECT_EQ(hit_test_data->bounds, root()->bounds()); @@ -229,7 +234,8 @@ TEST_F(HitTestDataProviderAuraTest, CustomTargeter) { // Tests that the complex hit-test shape can be set with a custom targeter. TEST_F(HitTestDataProviderAuraTest, HoleTargeter) { window3()->SetEventTargeter(std::make_unique<TestHoleWindowTargeter>()); - const auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + const auto hit_test_data = + hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); EXPECT_EQ(hit_test_data->bounds, root()->bounds()); @@ -263,13 +269,14 @@ TEST_F(HitTestDataProviderAuraTest, HoleTargeter) { TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE); - auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + auto hit_test_data = + hit_test_data_provider()->GetHitTestData(compositor_frame_); 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(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); EXPECT_EQ(hit_test_data->regions.size(), 3u); @@ -277,7 +284,7 @@ TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY); window3()->SetEventTargetingPolicy( ui::mojom::EventTargetingPolicy::TARGET_ONLY); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); EXPECT_EQ(hit_test_data->regions.size(), 2u); @@ -286,7 +293,7 @@ TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY); window3()->SetEventTargetingPolicy( ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestIgnore); EXPECT_EQ(hit_test_data->regions.size(), 2u); @@ -295,7 +302,7 @@ TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); window3()->SetEventTargetingPolicy( ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine); EXPECT_EQ(hit_test_data->regions.size(), 3u); @@ -304,30 +311,31 @@ TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) { // Tests that we do not submit hit-test data for invisible windows and for // children of a child surface. TEST_F(HitTestDataProviderAuraTest, DoNotSubmit) { - auto hit_test_data = hit_test_data_provider()->GetHitTestData(); + auto hit_test_data = + hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->regions.size(), 3u); window2()->Hide(); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->regions.size(), 2u); - window3()->set_embed_frame_sink_id(viz::FrameSinkId(1, 3)); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + window3()->SetEmbedFrameSinkId(viz::FrameSinkId(1, 3)); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->regions.size(), 1u); root()->Hide(); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_FALSE(hit_test_data); root()->Show(); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->regions.size(), 1u); - root()->set_embed_frame_sink_id(viz::FrameSinkId(1, 1)); - hit_test_data = hit_test_data_provider()->GetHitTestData(); + root()->SetEmbedFrameSinkId(viz::FrameSinkId(1, 1)); + hit_test_data = hit_test_data_provider()->GetHitTestData(compositor_frame_); ASSERT_TRUE(hit_test_data); EXPECT_EQ(hit_test_data->regions.size(), 0u); } diff --git a/chromium/ui/aura/local/layer_tree_frame_sink_local.cc b/chromium/ui/aura/local/layer_tree_frame_sink_local.cc index 954176f0fcf..a5ce5a4d677 100644 --- a/chromium/ui/aura/local/layer_tree_frame_sink_local.cc +++ b/chromium/ui/aura/local/layer_tree_frame_sink_local.cc @@ -23,12 +23,9 @@ LayerTreeFrameSinkLocal::LayerTreeFrameSinkLocal( const std::string& debug_label) : cc::LayerTreeFrameSink(nullptr, nullptr, nullptr, nullptr, nullptr), frame_sink_id_(frame_sink_id), - host_frame_sink_manager_(host_frame_sink_manager), - weak_factory_(this) { + host_frame_sink_manager_(host_frame_sink_manager) { host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this); -#if DCHECK_IS_ON() host_frame_sink_manager_->SetFrameSinkDebugLabel(frame_sink_id_, debug_label); -#endif } LayerTreeFrameSinkLocal::~LayerTreeFrameSinkLocal() { @@ -56,16 +53,11 @@ void LayerTreeFrameSinkLocal::SetSurfaceChangedCallback( surface_changed_callback_ = callback; } -base::WeakPtr<LayerTreeFrameSinkLocal> LayerTreeFrameSinkLocal::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - void LayerTreeFrameSinkLocal::DetachFromClient() { DCHECK(thread_checker_); DCHECK(thread_checker_->CalledOnValidThread()); client_->SetBeginFrameSource(nullptr); begin_frame_source_.reset(); - support_->EvictCurrentSurface(); support_.reset(); thread_checker_.reset(); cc::LayerTreeFrameSink::DetachFromClient(); @@ -87,9 +79,7 @@ void LayerTreeFrameSinkLocal::SubmitCompositorFrame( DCHECK(local_surface_id_.is_valid()); - bool result = - support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)); - DCHECK(result); + support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)); } void LayerTreeFrameSinkLocal::DidNotProduceFrame( @@ -101,6 +91,19 @@ void LayerTreeFrameSinkLocal::DidNotProduceFrame( support_->DidNotProduceFrame(ack); } +void LayerTreeFrameSinkLocal::DidAllocateSharedBitmap( + mojo::ScopedSharedBufferHandle buffer, + const viz::SharedBitmapId& id) { + // No software compositing used with this implementation. + NOTIMPLEMENTED(); +} + +void LayerTreeFrameSinkLocal::DidDeleteSharedBitmap( + const viz::SharedBitmapId& id) { + // No software compositing used with this implementation. + NOTIMPLEMENTED(); +} + void LayerTreeFrameSinkLocal::DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) { DCHECK(thread_checker_); diff --git a/chromium/ui/aura/local/layer_tree_frame_sink_local.h b/chromium/ui/aura/local/layer_tree_frame_sink_local.h index 25dc6cf74b9..83217f46ce8 100644 --- a/chromium/ui/aura/local/layer_tree_frame_sink_local.h +++ b/chromium/ui/aura/local/layer_tree_frame_sink_local.h @@ -42,8 +42,6 @@ class LayerTreeFrameSinkLocal : public cc::LayerTreeFrameSink, // Set a callback which will be called when the surface is changed. void SetSurfaceChangedCallback(const SurfaceChangedCallback& callback); - base::WeakPtr<LayerTreeFrameSinkLocal> GetWeakPtr(); - const viz::LocalSurfaceId& local_surface_id() const { return local_surface_id_; } @@ -54,6 +52,9 @@ class LayerTreeFrameSinkLocal : public cc::LayerTreeFrameSink, void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id) override; void SubmitCompositorFrame(viz::CompositorFrame frame) override; void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; + void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, + const viz::SharedBitmapId& id) override; + void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; // viz::mojom::CompositorFrameSinkClient: void DidReceiveCompositorFrameAck( @@ -84,7 +85,6 @@ class LayerTreeFrameSinkLocal : public cc::LayerTreeFrameSink, std::unique_ptr<viz::ExternalBeginFrameSource> begin_frame_source_; std::unique_ptr<base::ThreadChecker> thread_checker_; SurfaceChangedCallback surface_changed_callback_; - base::WeakPtrFactory<LayerTreeFrameSinkLocal> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSinkLocal); }; diff --git a/chromium/ui/aura/local/window_port_local.cc b/chromium/ui/aura/local/window_port_local.cc index c9b3213d26f..787fbc5e7cc 100644 --- a/chromium/ui/aura/local/window_port_local.cc +++ b/chromium/ui/aura/local/window_port_local.cc @@ -4,7 +4,7 @@ #include "ui/aura/local/window_port_local.h" -#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/host/host_frame_sink_manager.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" #include "ui/aura/local/layer_tree_frame_sink_local.h" @@ -118,26 +118,20 @@ void WindowPortLocal::OnPropertyChanged( std::unique_ptr<cc::LayerTreeFrameSink> WindowPortLocal::CreateLayerTreeFrameSink() { - DCHECK(!frame_sink_id_.is_valid()); auto* context_factory_private = aura::Env::GetInstance()->context_factory_private(); - frame_sink_id_ = context_factory_private->AllocateFrameSinkId(); + auto frame_sink_id = context_factory_private->AllocateFrameSinkId(); auto frame_sink = std::make_unique<LayerTreeFrameSinkLocal>( - frame_sink_id_, context_factory_private->GetHostFrameSinkManager(), + frame_sink_id, context_factory_private->GetHostFrameSinkManager(), window_->GetName()); + window_->SetEmbedFrameSinkId(frame_sink_id); frame_sink->SetSurfaceChangedCallback(base::Bind( &WindowPortLocal::OnSurfaceChanged, weak_factory_.GetWeakPtr())); frame_sink_ = frame_sink->GetWeakPtr(); AllocateLocalSurfaceId(); - if (window_->GetRootWindow()) - window_->layer()->GetCompositor()->AddFrameSink(frame_sink_id_); return std::move(frame_sink); } -viz::SurfaceId WindowPortLocal::GetSurfaceId() const { - return viz::SurfaceId(frame_sink_id_, local_surface_id_); -} - void WindowPortLocal::AllocateLocalSurfaceId() { last_device_scale_factor_ = ui::GetScaleFactorForNativeView(window_); last_size_ = window_->bounds().size(); @@ -152,34 +146,14 @@ const viz::LocalSurfaceId& WindowPortLocal::GetLocalSurfaceId() { return local_surface_id_; } -viz::FrameSinkId WindowPortLocal::GetFrameSinkId() const { - return frame_sink_id_; -} - -void WindowPortLocal::OnWindowAddedToRootWindow() { - if (frame_sink_id_.is_valid()) - window_->layer()->GetCompositor()->AddFrameSink(frame_sink_id_); -} - -void WindowPortLocal::OnWillRemoveWindowFromRootWindow() { - if (frame_sink_id_.is_valid()) - window_->layer()->GetCompositor()->RemoveFrameSink(frame_sink_id_); -} - void WindowPortLocal::OnEventTargetingPolicyChanged() {} void WindowPortLocal::OnSurfaceChanged(const viz::SurfaceInfo& surface_info) { - DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_); + DCHECK_EQ(surface_info.id().frame_sink_id(), window_->GetFrameSinkId()); DCHECK_EQ(surface_info.id().local_surface_id(), local_surface_id_); - scoped_refptr<viz::SurfaceReferenceFactory> reference_factory = - aura::Env::GetInstance() - ->context_factory_private() - ->GetFrameSinkManager() - ->surface_manager() - ->reference_factory(); - window_->layer()->SetShowPrimarySurface(surface_info.id(), - window_->bounds().size(), - SK_ColorWHITE, reference_factory); + window_->layer()->SetShowPrimarySurface( + surface_info.id(), window_->bounds().size(), SK_ColorWHITE, + cc::DeadlinePolicy::UseDefaultDeadline()); window_->layer()->SetFallbackSurfaceId(surface_info.id()); } diff --git a/chromium/ui/aura/local/window_port_local.h b/chromium/ui/aura/local/window_port_local.h index be24ab4f8d9..58abd724537 100644 --- a/chromium/ui/aura/local/window_port_local.h +++ b/chromium/ui/aura/local/window_port_local.h @@ -46,12 +46,8 @@ class AURA_EXPORT WindowPortLocal : public WindowPort { int64_t old_value, std::unique_ptr<ui::PropertyData> data) override; std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override; - viz::SurfaceId GetSurfaceId() const override; void AllocateLocalSurfaceId() override; const viz::LocalSurfaceId& GetLocalSurfaceId() override; - viz::FrameSinkId GetFrameSinkId() const override; - void OnWindowAddedToRootWindow() override; - void OnWillRemoveWindowFromRootWindow() override; void OnEventTargetingPolicyChanged() override; bool ShouldRestackTransientChildren() override; @@ -59,12 +55,11 @@ class AURA_EXPORT WindowPortLocal : public WindowPort { void OnSurfaceChanged(const viz::SurfaceInfo& surface_info); Window* const window_; - viz::FrameSinkId frame_sink_id_; gfx::Size last_size_; float last_device_scale_factor_ = 1.0f; viz::LocalSurfaceId local_surface_id_; viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; - base::WeakPtr<aura::LayerTreeFrameSinkLocal> frame_sink_; + base::WeakPtr<cc::LayerTreeFrameSink> frame_sink_; base::WeakPtrFactory<WindowPortLocal> weak_factory_; diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc index 17029d25b7b..7863b68f365 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.cc +++ b/chromium/ui/aura/mus/client_surface_embedder.cc @@ -5,7 +5,6 @@ #include "ui/aura/mus/client_surface_embedder.h" #include "base/memory/ptr_util.h" -#include "components/viz/common/surfaces/stub_surface_reference_factory.h" #include "ui/aura/window.h" #include "ui/gfx/geometry/dip_util.h" @@ -30,15 +29,15 @@ 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 viz::StubSurfaceReferenceFactory(); } ClientSurfaceEmbedder::~ClientSurfaceEmbedder() = default; void ClientSurfaceEmbedder::SetPrimarySurfaceId( const viz::SurfaceId& surface_id) { - surface_layer_->SetShowPrimarySurface(surface_id, window_->bounds().size(), - SK_ColorWHITE, ref_factory_); + surface_layer_->SetShowPrimarySurface( + surface_id, window_->bounds().size(), SK_ColorWHITE, + cc::DeadlinePolicy::UseDefaultDeadline()); } void ClientSurfaceEmbedder::SetFallbackSurfaceInfo( @@ -95,4 +94,9 @@ void ClientSurfaceEmbedder::UpdateSizeAndGutters() { window_->layer()->StackAtTop(surface_layer_.get()); } +const viz::SurfaceId& ClientSurfaceEmbedder::GetPrimarySurfaceIdForTesting() + const { + return *surface_layer_->GetPrimarySurfaceId(); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/client_surface_embedder.h b/chromium/ui/aura/mus/client_surface_embedder.h index e5085af030e..5017c44951a 100644 --- a/chromium/ui/aura/mus/client_surface_embedder.h +++ b/chromium/ui/aura/mus/client_surface_embedder.h @@ -8,19 +8,15 @@ #include <memory> #include "base/macros.h" -#include "base/memory/ref_counted.h" #include "components/viz/common/surfaces/surface_info.h" -#include "components/viz/common/surfaces/surface_reference_factory.h" +#include "ui/aura/aura_export.h" +#include "ui/compositor/layer.h" #include "ui/gfx/geometry/insets.h" namespace gfx { class Insets; } -namespace ui { -class Layer; -} - namespace aura { class Window; @@ -28,7 +24,7 @@ class Window; // Used by WindowPortMus when it is embedding a client. Responsible for setting // up layers containing content from the client, parenting them to the window's // layer, and updating them when the client submits new surfaces. -class ClientSurfaceEmbedder { +class AURA_EXPORT ClientSurfaceEmbedder { public: // TODO(fsamuel): Insets might differ when the window is maximized. We should // deal with that case as well. @@ -53,6 +49,8 @@ class ClientSurfaceEmbedder { ui::Layer* BottomGutterForTesting() { return bottom_gutter_.get(); } + const viz::SurfaceId& GetPrimarySurfaceIdForTesting() const; + private: // The window which embeds the client. Window* window_; @@ -70,8 +68,6 @@ class ClientSurfaceEmbedder { bool inject_gutter_; gfx::Insets client_area_insets_; - scoped_refptr<viz::SurfaceReferenceFactory> ref_factory_; - DISALLOW_COPY_AND_ASSIGN(ClientSurfaceEmbedder); }; diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.cc b/chromium/ui/aura/mus/drag_drop_controller_mus.cc index 55d271583bf..532b0364807 100644 --- a/chromium/ui/aura/mus/drag_drop_controller_mus.cc +++ b/chromium/ui/aura/mus/drag_drop_controller_mus.cc @@ -40,7 +40,7 @@ namespace aura { // State related to a drag initiated by this client. struct DragDropControllerMus::CurrentDragState { - Id window_id; + ui::Id window_id; // The change id of the drag. Used to identify the drag on the server. uint32_t change_id; diff --git a/chromium/ui/aura/mus/mus_context_factory.cc b/chromium/ui/aura/mus/mus_context_factory.cc index f95b744e593..f2b4dc0c60e 100644 --- a/chromium/ui/aura/mus/mus_context_factory.cc +++ b/chromium/ui/aura/mus/mus_context_factory.cc @@ -21,9 +21,6 @@ namespace aura { MusContextFactory::MusContextFactory(ui::Gpu* gpu) : gpu_(gpu), - resource_settings_( - // TODO(sad): http://crbug.com/675431 - viz::CreateResourceSettings()), weak_ptr_factory_(this) {} MusContextFactory::~MusContextFactory() {} @@ -89,8 +86,4 @@ cc::TaskGraphRunner* MusContextFactory::GetTaskGraphRunner() { return raster_thread_helper_.task_graph_runner(); } -const viz::ResourceSettings& MusContextFactory::GetResourceSettings() const { - 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 ab1b1950f62..532af0fad23 100644 --- a/chromium/ui/aura/mus/mus_context_factory.h +++ b/chromium/ui/aura/mus/mus_context_factory.h @@ -17,10 +17,6 @@ #include "ui/aura/aura_export.h" #include "ui/compositor/compositor.h" -namespace cc { -class ResourceSettings; -} - namespace gpu { class GpuChannelHost; } @@ -51,13 +47,11 @@ class AURA_EXPORT MusContextFactory : public ui::ContextFactory { double GetRefreshRate() const override; gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; - const viz::ResourceSettings& GetResourceSettings() const override; void AddObserver(ui::ContextFactoryObserver* observer) override {} void RemoveObserver(ui::ContextFactoryObserver* observer) override {} ui::RasterThreadHelper raster_thread_helper_; ui::Gpu* gpu_; - 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/mus_types.h b/chromium/ui/aura/mus/mus_types.h index 8c4f305f3b2..84b95f65da8 100644 --- a/chromium/ui/aura/mus/mus_types.h +++ b/chromium/ui/aura/mus/mus_types.h @@ -7,20 +7,14 @@ #include <stdint.h> +#include "services/ui/common/types.h" + // Typedefs for the transport types. These typedefs match that of the mojom // file, see it for specifics. namespace aura { -// Used to identify windows and change ids. -using Id = uint32_t; - -// Used to identify a client as well as a client-specific window id. For -// example, the Id for a window consists of the ClientSpecificId of the client -// and the ClientSpecificId of the window. -using ClientSpecificId = uint16_t; - -constexpr Id kInvalidServerId = 0; +constexpr ui::Id kInvalidServerId = 0; enum class WindowMusType { // The window is an embed root. That is, the client received this window by diff --git a/chromium/ui/aura/mus/property_converter.cc b/chromium/ui/aura/mus/property_converter.cc index 8839c507cb6..7a0a67e0177 100644 --- a/chromium/ui/aura/mus/property_converter.cc +++ b/chromium/ui/aura/mus/property_converter.cc @@ -49,6 +49,10 @@ bool ValidateShowState(int64_t value) { value == int64_t(ui::mojom::ShowState::FULLSCREEN); } +bool ValidateWindowCornerRadius(int64_t value) { + return value >= -1; +} + } // namespace PropertyConverter::PrimitiveProperty::PrimitiveProperty() {} @@ -96,6 +100,10 @@ PropertyConverter::PropertyConverter() { ui::mojom::WindowManager::kName_Property); RegisterString16Property(client::kTitleKey, ui::mojom::WindowManager::kWindowTitle_Property); + RegisterPrimitiveProperty( + client::kWindowCornerRadiusKey, + ui::mojom::WindowManager::kWindowCornerRadius_Property, + base::BindRepeating(&ValidateWindowCornerRadius)); } PropertyConverter::~PropertyConverter() {} diff --git a/chromium/ui/aura/mus/system_input_injector_mus.cc b/chromium/ui/aura/mus/system_input_injector_mus.cc index 7b062808248..1aa83e5a10f 100644 --- a/chromium/ui/aura/mus/system_input_injector_mus.cc +++ b/chromium/ui/aura/mus/system_input_injector_mus.cc @@ -76,6 +76,7 @@ void SystemInputInjectorMus::InjectMouseButton(ui::EventFlags button, break; case ui::EF_MIDDLE_MOUSE_BUTTON: modifier = ui::MODIFIER_MIDDLE_MOUSE_BUTTON; + break; default: LOG(WARNING) << "Invalid flag: " << button << " for the button parameter"; return; diff --git a/chromium/ui/aura/mus/text_input_client_impl.cc b/chromium/ui/aura/mus/text_input_client_impl.cc index 9f926a779c0..514a69a5611 100644 --- a/chromium/ui/aura/mus/text_input_client_impl.cc +++ b/chromium/ui/aura/mus/text_input_client_impl.cc @@ -39,8 +39,8 @@ void TextInputClientImpl::ClearCompositionText() { text_input_client_->ClearCompositionText(); } -void TextInputClientImpl::InsertText(const std::string& text) { - text_input_client_->InsertText(base::UTF8ToUTF16(text)); +void TextInputClientImpl::InsertText(const base::string16& text) { + text_input_client_->InsertText(text); } void TextInputClientImpl::InsertChar(std::unique_ptr<ui::Event> event) { diff --git a/chromium/ui/aura/mus/text_input_client_impl.h b/chromium/ui/aura/mus/text_input_client_impl.h index 46bf153d5c3..5f5b98d4807 100644 --- a/chromium/ui/aura/mus/text_input_client_impl.h +++ b/chromium/ui/aura/mus/text_input_client_impl.h @@ -31,7 +31,7 @@ class TextInputClientImpl : public ui::mojom::TextInputClient { void SetCompositionText(const ui::CompositionText& composition) override; void ConfirmCompositionText() override; void ClearCompositionText() override; - void InsertText(const std::string& text) override; + void InsertText(const base::string16& text) override; void InsertChar(std::unique_ptr<ui::Event> event) override; void DispatchKeyEventPostIME( std::unique_ptr<ui::Event> event, diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h index 355b4805bac..ade1846d660 100644 --- a/chromium/ui/aura/mus/window_mus.h +++ b/chromium/ui/aura/mus/window_mus.h @@ -67,7 +67,7 @@ class AURA_EXPORT WindowMus { } static WindowMus* Get(Window* window); - Id server_id() const { return server_id_; } + ui::Id server_id() const { return server_id_; } WindowMusType window_mus_type() const { return window_mus_type_; } @@ -135,9 +135,9 @@ class AURA_EXPORT WindowMus { // Just for set_server_id(), which other places should not call. friend class WindowTreeClient; - void set_server_id(Id id) { server_id_ = id; } + void set_server_id(ui::Id id) { server_id_ = id; } - Id server_id_ = kInvalidServerId; + ui::Id server_id_ = kInvalidServerId; const WindowMusType window_mus_type_; }; diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc index 5b4bcab052d..45dd67e18ef 100644 --- a/chromium/ui/aura/mus/window_port_mus.cc +++ b/chromium/ui/aura/mus/window_port_mus.cc @@ -6,7 +6,7 @@ #include "base/memory/ptr_util.h" #include "components/viz/client/local_surface_id_provider.h" -#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/host/host_frame_sink_manager.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/transient_window_client.h" #include "ui/aura/env.h" @@ -19,6 +19,7 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_observer.h" #include "ui/base/class_property.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches_util.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -131,10 +132,12 @@ WindowPortMus::RequestLayerTreeFrameSink( return layer_tree_frame_sink; } -viz::FrameSinkId WindowPortMus::GetFrameSinkId() const { - if (window_->IsEmbeddingClient()) - return window_->embed_frame_sink_id(); - return viz::FrameSinkId(0, server_id()); +viz::FrameSinkId WindowPortMus::GenerateFrameSinkIdFromServerId() const { + // With mus, the client does not know its own client id. So it uses a constant + // value of 0. This gets replaced in the server side with the correct value + // where appropriate. + constexpr int kClientSelfId = 0; + return viz::FrameSinkId(kClientSelfId, server_id()); } WindowPortMus::ServerChangeIdType WindowPortMus::ScheduleChange( @@ -302,7 +305,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); - window_->set_embed_frame_sink_id(frame_sink_id); + window_->SetEmbedFrameSinkId(frame_sink_id); UpdatePrimarySurfaceId(); } @@ -331,14 +334,14 @@ void WindowPortMus::SetFallbackSurfaceInfo( const viz::SurfaceInfo& surface_info) { if (!window_->IsEmbeddingClient()) { // |primary_surface_id_| shold not be valid, since we didn't know the - // |window_->embed_frame_sink_id()|. + // |window_->frame_sink_id()|. DCHECK(!primary_surface_id_.is_valid()); - window_->set_embed_frame_sink_id(surface_info.id().frame_sink_id()); + window_->SetEmbedFrameSinkId(surface_info.id().frame_sink_id()); UpdatePrimarySurfaceId(); } // The frame sink id should never be changed. - DCHECK_EQ(surface_info.id().frame_sink_id(), window_->embed_frame_sink_id()); + DCHECK_EQ(surface_info.id().frame_sink_id(), window_->GetFrameSinkId()); fallback_surface_info_ = surface_info; UpdateClientSurfaceEmbedder(); @@ -403,10 +406,11 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved( void WindowPortMus::AllocateLocalSurfaceId() { local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); + UpdatePrimarySurfaceId(); } const viz::LocalSurfaceId& WindowPortMus::GetLocalSurfaceId() { - if (switches::IsMusHostingViz()) + if (base::FeatureList::IsEnabled(features::kMash)) return local_surface_id_; if (!window_->IsEmbeddingClient() && !window_->IsRootWindow()) return local_surface_id_; @@ -559,17 +563,18 @@ WindowPortMus::CreateLayerTreeFrameSink() { DCHECK(!local_layer_tree_frame_sink_); std::unique_ptr<cc::LayerTreeFrameSink> frame_sink; - if (switches::IsMusHostingViz()) { + if (base::FeatureList::IsEnabled(features::kMash)) { auto client_layer_tree_frame_sink = RequestLayerTreeFrameSink(nullptr, aura::Env::GetInstance() ->context_factory() ->GetGpuMemoryBufferManager()); local_layer_tree_frame_sink_ = client_layer_tree_frame_sink->GetWeakPtr(); frame_sink = std::move(client_layer_tree_frame_sink); + window_->SetEmbedFrameSinkId(GenerateFrameSinkIdFromServerId()); } else { auto* context_factory_private = aura::Env::GetInstance()->context_factory_private(); - auto frame_sink_id = GetFrameSinkId(); + auto frame_sink_id = window_->GetFrameSinkId(); DCHECK(frame_sink_id.is_valid()); auto layer_tree_frame_sink_local = std::make_unique<LayerTreeFrameSinkLocal>( @@ -577,10 +582,7 @@ WindowPortMus::CreateLayerTreeFrameSink() { window_->GetName()); layer_tree_frame_sink_local->SetSurfaceChangedCallback(base::BindRepeating( &WindowPortMus::OnSurfaceChanged, weak_ptr_factory_.GetWeakPtr())); - if (window_->layer()->GetCompositor()) { - window_->layer()->GetCompositor()->AddFrameSink(GetFrameSinkId()); - is_frame_sink_id_added_to_compositor_ = true; - } + window_->SetEmbedFrameSinkId(frame_sink_id); local_layer_tree_frame_sink_ = layer_tree_frame_sink_local->GetWeakPtr(); frame_sink = std::move(layer_tree_frame_sink_local); } @@ -593,29 +595,6 @@ WindowPortMus::CreateLayerTreeFrameSink() { return frame_sink; } -viz::SurfaceId WindowPortMus::GetSurfaceId() const { - return viz::SurfaceId(window_->embed_frame_sink_id(), local_surface_id_); -} - -void WindowPortMus::OnWindowAddedToRootWindow() { - if (switches::IsMusHostingViz()) - return; - if (local_layer_tree_frame_sink_) { - DCHECK(!is_frame_sink_id_added_to_compositor_); - window_->layer()->GetCompositor()->AddFrameSink(GetFrameSinkId()); - is_frame_sink_id_added_to_compositor_ = true; - } -} - -void WindowPortMus::OnWillRemoveWindowFromRootWindow() { - if (switches::IsMusHostingViz()) - return; - if (is_frame_sink_id_added_to_compositor_) { - window_->layer()->GetCompositor()->RemoveFrameSink(GetFrameSinkId()); - is_frame_sink_id_added_to_compositor_ = false; - } -} - void WindowPortMus::OnEventTargetingPolicyChanged() { SetEventTargetingPolicy(window_->event_targeting_policy()); } @@ -636,12 +615,12 @@ void WindowPortMus::UpdatePrimarySurfaceId() { return; primary_surface_id_ = - viz::SurfaceId(window_->embed_frame_sink_id(), local_surface_id_); + viz::SurfaceId(window_->GetFrameSinkId(), local_surface_id_); UpdateClientSurfaceEmbedder(); } void WindowPortMus::UpdateClientSurfaceEmbedder() { - if (!switches::IsMusHostingViz()) + if (!base::FeatureList::IsEnabled(features::kMash)) return; if (window_mus_type() != WindowMusType::TOP_LEVEL_IN_WM && window_mus_type() != WindowMusType::EMBED_IN_OWNER && @@ -661,18 +640,14 @@ void WindowPortMus::UpdateClientSurfaceEmbedder() { } void WindowPortMus::OnSurfaceChanged(const viz::SurfaceInfo& surface_info) { - DCHECK(!switches::IsMusHostingViz()); - DCHECK_EQ(surface_info.id().frame_sink_id(), GetFrameSinkId()); + // TODO(fsamuel): Rename OnFirstSurfaceActivation() and set primary earlier + // based on feedback from LayerTreeFrameSinkLocal. + DCHECK(!base::FeatureList::IsEnabled(features::kMash)); + DCHECK_EQ(surface_info.id().frame_sink_id(), window_->GetFrameSinkId()); DCHECK_EQ(surface_info.id().local_surface_id(), local_surface_id_); - scoped_refptr<viz::SurfaceReferenceFactory> reference_factory = - aura::Env::GetInstance() - ->context_factory_private() - ->GetFrameSinkManager() - ->surface_manager() - ->reference_factory(); - window_->layer()->SetShowPrimarySurface(surface_info.id(), - window_->bounds().size(), - SK_ColorWHITE, reference_factory); + window_->layer()->SetShowPrimarySurface( + surface_info.id(), window_->bounds().size(), SK_ColorWHITE, + cc::DeadlinePolicy::UseDefaultDeadline()); window_->layer()->SetFallbackSurfaceId(surface_info.id()); } diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h index 318ea8fc5bf..8228ff89d3c 100644 --- a/chromium/ui/aura/mus/window_port_mus.h +++ b/chromium/ui/aura/mus/window_port_mus.h @@ -99,10 +99,7 @@ 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; + viz::FrameSinkId GenerateFrameSinkIdFromServerId() const; private: friend class WindowPortMusTest; @@ -157,7 +154,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { // Contains data needed to identify a change from the server. struct ServerChangeData { // Applies to ADD, ADD_TRANSIENT, REMOVE, REMOVE_TRANSIENT, and REORDER. - Id child_id; + ui::Id child_id; // Applies to BOUNDS. This should be in dip. gfx::Rect bounds_in_dip; // Applies to VISIBLE. @@ -275,11 +272,8 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { int64_t old_value, std::unique_ptr<ui::PropertyData> data) override; std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override; - viz::SurfaceId GetSurfaceId() const override; void AllocateLocalSurfaceId() override; const viz::LocalSurfaceId& GetLocalSurfaceId() override; - void OnWindowAddedToRootWindow() override; - void OnWillRemoveWindowFromRootWindow() override; void OnEventTargetingPolicyChanged() override; bool ShouldRestackTransientChildren() override; @@ -314,7 +308,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus { // for a local aura::Window, we need keep a weak ptr of it, so we can update // the local surface id when necessary. base::WeakPtr<cc::LayerTreeFrameSink> local_layer_tree_frame_sink_; - bool is_frame_sink_id_added_to_compositor_ = false; base::WeakPtrFactory<WindowPortMus> weak_ptr_factory_; diff --git a/chromium/ui/aura/mus/window_port_mus_unittest.cc b/chromium/ui/aura/mus/window_port_mus_unittest.cc index 107d663e87c..8425624d63c 100644 --- a/chromium/ui/aura/mus/window_port_mus_unittest.cc +++ b/chromium/ui/aura/mus/window_port_mus_unittest.cc @@ -7,9 +7,10 @@ #include "components/viz/client/client_layer_tree_frame_sink.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/local/layer_tree_frame_sink_local.h" +#include "ui/aura/mus/client_surface_embedder.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/window.h" -#include "ui/base/ui_base_switches_util.h" +#include "ui/base/ui_base_features.h" namespace aura { @@ -34,7 +35,7 @@ TEST_F(WindowPortMusTest, LayerTreeFrameSinkGetsCorrectLocalSurfaceId) { window.SetBounds(gfx::Rect(300, 300)); // Notify the window that it will embed an external client, so that it // correctly generates LocalSurfaceId. - window.set_embed_frame_sink_id(viz::FrameSinkId(0, 1)); + window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); viz::LocalSurfaceId local_surface_id = window.GetLocalSurfaceId(); ASSERT_TRUE(local_surface_id.is_valid()); @@ -46,7 +47,7 @@ TEST_F(WindowPortMusTest, LayerTreeFrameSinkGetsCorrectLocalSurfaceId) { auto mus_frame_sink = GetFrameSinkFor(&window); ASSERT_TRUE(mus_frame_sink); auto frame_sink_local_surface_id = - switches::IsMusHostingViz() + base::FeatureList::IsEnabled(features::kMash) ? static_cast<viz::ClientLayerTreeFrameSink*>(mus_frame_sink.get()) ->local_surface_id() : static_cast<LayerTreeFrameSinkLocal*>(mus_frame_sink.get()) @@ -55,4 +56,24 @@ TEST_F(WindowPortMusTest, LayerTreeFrameSinkGetsCorrectLocalSurfaceId) { EXPECT_EQ(frame_sink_local_surface_id, local_surface_id); } +TEST_F(WindowPortMusTest, ClientSurfaceEmbedderUpdatesLayer) { + // If mus is not hosting viz, we don't have ClientSurfaceEmbedder. + if (!base::FeatureList::IsEnabled(features::kMash)) + return; + + Window window(nullptr); + window.Init(ui::LAYER_NOT_DRAWN); + window.SetBounds(gfx::Rect(300, 300)); + window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); + + // Allocate a new LocalSurfaceId. The ui::Layer should be updated. + window.AllocateLocalSurfaceId(); + + auto* window_mus = WindowPortMus::Get(&window); + viz::LocalSurfaceId local_surface_id = window.GetLocalSurfaceId(); + viz::SurfaceId primary_surface_id = + window_mus->client_surface_embedder()->GetPrimarySurfaceIdForTesting(); + EXPECT_EQ(local_surface_id, primary_surface_id.local_surface_id()); +} + } // namespace aura diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc index 760d35f4c9d..a75ee126a46 100644 --- a/chromium/ui/aura/mus/window_tree_client.cc +++ b/chromium/ui/aura/mus/window_tree_client.cc @@ -24,6 +24,7 @@ #include "mojo/public/cpp/bindings/map.h" #include "services/service_manager/public/cpp/connector.h" #include "services/ui/common/accelerator_util.h" +#include "services/ui/common/util.h" #include "services/ui/public/cpp/gpu/gpu.h" #include "services/ui/public/cpp/property_type_converters.h" #include "services/ui/public/interfaces/constants.mojom.h" @@ -57,6 +58,7 @@ #include "ui/aura/window_port_for_shutdown.h" #include "ui/aura/window_tracker.h" #include "ui/base/layout.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches_util.h" #include "ui/base/ui_base_types.h" #include "ui/display/screen.h" @@ -69,10 +71,6 @@ namespace aura { namespace { -inline uint16_t HiWord(uint32_t id) { - return static_cast<uint16_t>((id >> 16) & 0xFFFF); -} - struct WindowPortPropertyDataMus : public ui::PropertyData { std::string transport_name; std::unique_ptr<std::vector<uint8_t>> transport_value; @@ -166,24 +164,13 @@ std::unique_ptr<ui::Event> MapEvent(const ui::Event& event) { return ui::Event::Clone(event); } -// Set the |target| to be the target window of this |event| and send it to -// the EventSink. -void DispatchEventToTarget(ui::Event* event, WindowMus* target) { - ui::Event::DispatcherApi dispatch_helper(event); - // Ignore the target for key events. They need to go to the focused window, - // which may have changed by the time we process the event. - if (!event->IsKeyEvent()) - dispatch_helper.set_target(target->GetWindow()); - GetWindowTreeHostMus(target)->SendEventToSink(event); -} - // Use for acks from mus that are expected to always succeed and if they don't // a crash is triggered. void OnAckMustSucceed(const base::Location& from_here, bool success) { CHECK(success) << "Context: " << from_here.ToString(); } -Id GetServerIdForWindow(Window* window) { +ui::Id GetServerIdForWindow(Window* window) { return window ? WindowMus::Get(window)->server_id() : kInvalidServerId; } @@ -225,7 +212,7 @@ WindowTreeClient::WindowTreeClient( io_task_runner = io_thread_->task_runner(); } - if (switches::IsMusHostingViz()) { + if (base::FeatureList::IsEnabled(features::kMash)) { gpu_ = ui::Gpu::Create(connector, ui::mojom::kServiceName, io_task_runner); compositor_context_factory_ = @@ -402,7 +389,7 @@ void WindowTreeClient::ScheduleEmbed( } void WindowTreeClient::AttachCompositorFrameSink( - Id window_id, + ui::Id window_id, viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, viz::mojom::CompositorFrameSinkClientPtr client) { DCHECK(tree_); @@ -413,9 +400,14 @@ void WindowTreeClient::AttachCompositorFrameSink( void WindowTreeClient::RegisterWindowMus(WindowMus* window) { DCHECK(windows_.find(window->server_id()) == windows_.end()); windows_[window->server_id()] = window; + if (window->GetWindow()) { + auto* port = WindowPortMus::Get(window->GetWindow()); + window->GetWindow()->set_frame_sink_id( + port->GenerateFrameSinkIdFromServerId()); + } } -WindowMus* WindowTreeClient::GetWindowByServerId(Id id) { +WindowMus* WindowTreeClient::GetWindowByServerId(ui::Id id) { IdToWindowMap::const_iterator it = windows_.find(id); return it != windows_.end() ? it->second : nullptr; } @@ -606,7 +598,8 @@ std::unique_ptr<WindowTreeHostMus> WindowTreeClient::CreateWindowTreeHost( if (window_manager_delegate_ && (window_mus_type == WindowMusType::EMBED || window_mus_type == WindowMusType::DISPLAY_AUTOMATICALLY_CREATED)) { - init_params.uses_real_accelerated_widget = !::switches::IsMusHostingViz(); + init_params.uses_real_accelerated_widget = + !::base::FeatureList::IsEnabled(features::kMash); } std::unique_ptr<WindowTreeHostMus> window_tree_host = std::make_unique<WindowTreeHostMus>(std::move(init_params)); @@ -712,7 +705,7 @@ void WindowTreeClient::OnEmbedImpl( ui::mojom::WindowTree* window_tree, ui::mojom::WindowDataPtr root_data, int64_t display_id, - Id focused_window_id, + ui::Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id) { WindowTreeConnectionEstablished(window_tree); @@ -886,8 +879,9 @@ 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(), - switches::IsMusHostingViz() ? display_init_params->mirrors - : std::vector<display::Display>(), + base::FeatureList::IsEnabled(features::kMash) + ? display_init_params->mirrors + : std::vector<display::Display>(), base::Bind(&OnAckMustSucceed, FROM_HERE)); } } @@ -1101,7 +1095,7 @@ std::set<Window*> WindowTreeClient::GetRoots() { bool WindowTreeClient::WasCreatedByThisClient(const WindowMus* window) const { // 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()) && + return !ui::ClientIdFromTransportId(window->server_id()) && roots_.count(const_cast<WindowMus*>(window)) == 0; } @@ -1163,7 +1157,7 @@ void WindowTreeClient::OnEmbed( ui::mojom::WindowDataPtr root_data, ui::mojom::WindowTreePtr tree, int64_t display_id, - Id focused_window_id, + ui::Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id) { DCHECK(!tree_ptr_); @@ -1181,13 +1175,13 @@ void WindowTreeClient::OnEmbed( focused_window_id, drawn, local_surface_id); } -void WindowTreeClient::OnEmbeddedAppDisconnected(Id window_id) { +void WindowTreeClient::OnEmbeddedAppDisconnected(ui::Id window_id) { WindowMus* window = GetWindowByServerId(window_id); if (window) window->NotifyEmbeddedAppDisconnected(); } -void WindowTreeClient::OnUnembed(Id window_id) { +void WindowTreeClient::OnUnembed(ui::Id window_id) { WindowMus* window = GetWindowByServerId(window_id); if (!window) return; @@ -1196,8 +1190,8 @@ void WindowTreeClient::OnUnembed(Id window_id) { delete window; } -void WindowTreeClient::OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) { +void WindowTreeClient::OnCaptureChanged(ui::Id new_capture_window_id, + ui::Id old_capture_window_id) { WindowMus* new_capture_window = GetWindowByServerId(new_capture_window_id); WindowMus* lost_capture_window = GetWindowByServerId(old_capture_window_id); if (!new_capture_window && !lost_capture_window) @@ -1212,8 +1206,10 @@ void WindowTreeClient::OnCaptureChanged(Id new_capture_window_id, } void WindowTreeClient::OnFrameSinkIdAllocated( - Id window_id, + ui::Id window_id, const viz::FrameSinkId& frame_sink_id) { + if (!base::FeatureList::IsEnabled(features::kMash)) + return; WindowMus* window = GetWindowByServerId(window_id); if (!window) return; @@ -1295,7 +1291,7 @@ void WindowTreeClient::OnTopLevelCreated( } void WindowTreeClient::OnWindowBoundsChanged( - Id window_id, + ui::Id window_id, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, const base::Optional<viz::LocalSurfaceId>& local_surface_id) { @@ -1311,7 +1307,7 @@ void WindowTreeClient::OnWindowBoundsChanged( } void WindowTreeClient::OnWindowTransformChanged( - Id window_id, + ui::Id window_id, const gfx::Transform& old_transform, const gfx::Transform& new_transform) { WindowMus* window = GetWindowByServerId(window_id); @@ -1326,7 +1322,7 @@ void WindowTreeClient::OnWindowTransformChanged( } void WindowTreeClient::OnClientAreaChanged( - uint32_t window_id, + ui::Id window_id, const gfx::Insets& new_client_area, const std::vector<gfx::Rect>& new_additional_client_areas) { WindowMus* window = GetWindowByServerId(window_id); @@ -1345,8 +1341,8 @@ void WindowTreeClient::OnClientAreaChanged( new_additional_client_areas_in_dip); } -void WindowTreeClient::OnTransientWindowAdded(uint32_t window_id, - uint32_t transient_window_id) { +void WindowTreeClient::OnTransientWindowAdded(ui::Id window_id, + ui::Id transient_window_id) { WindowMus* window = GetWindowByServerId(window_id); WindowMus* transient_window = GetWindowByServerId(transient_window_id); // window or transient_window or both may be null if a local delete occurs @@ -1355,8 +1351,8 @@ void WindowTreeClient::OnTransientWindowAdded(uint32_t window_id, window->AddTransientChildFromServer(transient_window); } -void WindowTreeClient::OnTransientWindowRemoved(uint32_t window_id, - uint32_t transient_window_id) { +void WindowTreeClient::OnTransientWindowRemoved(ui::Id window_id, + ui::Id transient_window_id) { WindowMus* window = GetWindowByServerId(window_id); WindowMus* transient_window = GetWindowByServerId(transient_window_id); // window or transient_window or both may be null if a local delete occurs @@ -1366,9 +1362,9 @@ void WindowTreeClient::OnTransientWindowRemoved(uint32_t window_id, } void WindowTreeClient::OnWindowHierarchyChanged( - Id window_id, - Id old_parent_id, - Id new_parent_id, + ui::Id window_id, + ui::Id old_parent_id, + ui::Id new_parent_id, std::vector<ui::mojom::WindowDataPtr> windows) { const bool was_window_known = GetWindowByServerId(window_id) != nullptr; @@ -1388,8 +1384,8 @@ void WindowTreeClient::OnWindowHierarchyChanged( old_parent->RemoveChildFromServer(window); } -void WindowTreeClient::OnWindowReordered(Id window_id, - Id relative_window_id, +void WindowTreeClient::OnWindowReordered(ui::Id window_id, + ui::Id relative_window_id, ui::mojom::OrderDirection direction) { WindowMus* window = GetWindowByServerId(window_id); WindowMus* relative_window = GetWindowByServerId(relative_window_id); @@ -1400,7 +1396,7 @@ void WindowTreeClient::OnWindowReordered(Id window_id, } } -void WindowTreeClient::OnWindowDeleted(Id window_id) { +void WindowTreeClient::OnWindowDeleted(ui::Id window_id) { WindowMus* window = GetWindowByServerId(window_id); if (!window) return; @@ -1418,7 +1414,8 @@ void WindowTreeClient::OnWindowDeleted(Id window_id) { } } -void WindowTreeClient::OnWindowVisibilityChanged(Id window_id, bool visible) { +void WindowTreeClient::OnWindowVisibilityChanged(ui::Id window_id, + bool visible) { WindowMus* window = GetWindowByServerId(window_id); if (!window) return; @@ -1430,7 +1427,7 @@ void WindowTreeClient::OnWindowVisibilityChanged(Id window_id, bool visible) { SetWindowVisibleFromServer(window, visible); } -void WindowTreeClient::OnWindowOpacityChanged(Id window_id, +void WindowTreeClient::OnWindowOpacityChanged(ui::Id window_id, float old_opacity, float new_opacity) { WindowMus* window = GetWindowByServerId(window_id); @@ -1444,7 +1441,7 @@ void WindowTreeClient::OnWindowOpacityChanged(Id window_id, window->SetOpacityFromServer(new_opacity); } -void WindowTreeClient::OnWindowParentDrawnStateChanged(Id window_id, +void WindowTreeClient::OnWindowParentDrawnStateChanged(ui::Id window_id, bool drawn) { // TODO: route to WindowTreeHost. /* @@ -1455,7 +1452,7 @@ void WindowTreeClient::OnWindowParentDrawnStateChanged(Id window_id, } void WindowTreeClient::OnWindowSharedPropertyChanged( - Id window_id, + ui::Id window_id, const std::string& name, const base::Optional<std::vector<uint8_t>>& transport_data) { WindowMus* window = GetWindowByServerId(window_id); @@ -1476,14 +1473,13 @@ void WindowTreeClient::OnWindowSharedPropertyChanged( void WindowTreeClient::OnWindowInputEvent( uint32_t event_id, - Id window_id, + ui::Id window_id, int64_t display_id, - Id display_root_window_id, + ui::Id display_root_window_id, const gfx::PointF& event_location_in_screen_pixel_layout, std::unique_ptr<ui::Event> event, bool matches_pointer_watcher) { DCHECK(event); - WindowMus* window = GetWindowByServerId(window_id); // May be null. if (matches_pointer_watcher && has_pointer_watcher_) { @@ -1549,23 +1545,30 @@ void WindowTreeClient::OnWindowInputEvent( #endif WindowMus* display_root_window = GetWindowByServerId(display_root_window_id); - if (display_root_window && window && event->IsLocatedEvent() && + if (display_root_window && event->IsLocatedEvent() && display::Screen::GetScreen()->GetPrimaryDisplay().id() == display::kUnifiedDisplayId) { - // Dispatch to the root window of the display supplying the event. This - // allows Ash to determine the event position in the unified desktop mode, - // where each physical display mirrors part of a single virtual display. - // This paralells the behavior of unified desktop mode in classic Ash mode. - DispatchEventToTarget(event_to_dispatch, display_root_window); - } else { - DispatchEventToTarget(event_to_dispatch, window); - } + // In Ash's unified desktop mode, each physical display mirrors part of a + // single virtual display. Dispatch events to the root window of the mirror + // display supplying the event, using locations relative to that display. + // Use a null target to ensure events reach the MusUnifiedEventTargeter. + // This paralells the behavior of unified desktop mode in classic Ash. + ui::Event::DispatcherApi(event_to_dispatch).set_target(nullptr); + ui::LocatedEvent* located_event = event_to_dispatch->AsLocatedEvent(); + located_event->set_location_f(located_event->root_location_f()); + window = display_root_window; + } else if (!event->IsKeyEvent()) { + // Set |window| as the target, except for key events. Key events go to the + // focused window, which may have changed by the time we process the event. + ui::Event::DispatcherApi(event_to_dispatch).set_target(window->GetWindow()); + } + GetWindowTreeHostMus(window)->SendEventToSink(event_to_dispatch); ack_handler.set_handled(event_to_dispatch->handled()); } void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event, - uint32_t window_id, + ui::Id window_id, int64_t display_id) { DCHECK(event); DCHECK(event->IsPointerEvent()); @@ -1580,7 +1583,7 @@ void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event, target_window ? target_window->GetWindow() : nullptr); } -void WindowTreeClient::OnWindowFocused(Id focused_window_id) { +void WindowTreeClient::OnWindowFocused(ui::Id focused_window_id) { WindowMus* focused_window = GetWindowByServerId(focused_window_id); InFlightFocusChange new_change(this, focus_synchronizer_.get(), focused_window); @@ -1590,7 +1593,7 @@ void WindowTreeClient::OnWindowFocused(Id focused_window_id) { focus_synchronizer_->SetFocusFromServer(focused_window); } -void WindowTreeClient::OnWindowCursorChanged(Id window_id, +void WindowTreeClient::OnWindowCursorChanged(ui::Id window_id, ui::CursorData cursor) { WindowMus* window = GetWindowByServerId(window_id); if (!window) @@ -1604,7 +1607,7 @@ void WindowTreeClient::OnWindowCursorChanged(Id window_id, } void WindowTreeClient::OnWindowSurfaceChanged( - Id window_id, + ui::Id window_id, const viz::SurfaceInfo& surface_info) { WindowMus* window = GetWindowByServerId(window_id); if (!window) @@ -1623,7 +1626,7 @@ void WindowTreeClient::OnDragDropStart( drag_drop_controller_->OnDragDropStart(mojo::UnorderedMapToMap(mime_data)); } -void WindowTreeClient::OnDragEnter(Id window_id, +void WindowTreeClient::OnDragEnter(ui::Id window_id, uint32_t key_state, const gfx::Point& position, uint32_t effect_bitmask, @@ -1632,7 +1635,7 @@ void WindowTreeClient::OnDragEnter(Id window_id, GetWindowByServerId(window_id), key_state, position, effect_bitmask)); } -void WindowTreeClient::OnDragOver(Id window_id, +void WindowTreeClient::OnDragOver(ui::Id window_id, uint32_t key_state, const gfx::Point& position, uint32_t effect_bitmask, @@ -1641,7 +1644,7 @@ void WindowTreeClient::OnDragOver(Id window_id, GetWindowByServerId(window_id), key_state, position, effect_bitmask)); } -void WindowTreeClient::OnDragLeave(Id window_id) { +void WindowTreeClient::OnDragLeave(ui::Id window_id) { drag_drop_controller_->OnDragLeave(GetWindowByServerId(window_id)); } @@ -1649,7 +1652,7 @@ void WindowTreeClient::OnDragDropDone() { drag_drop_controller_->OnDragDropDone(); } -void WindowTreeClient::OnCompleteDrop(Id window_id, +void WindowTreeClient::OnCompleteDrop(ui::Id window_id, uint32_t key_state, const gfx::Point& position, uint32_t effect_bitmask, @@ -1723,7 +1726,7 @@ void WindowTreeClient::GetWindowManager( this, std::move(internal))); } -void WindowTreeClient::RequestClose(uint32_t window_id) { +void WindowTreeClient::RequestClose(ui::Id window_id) { WindowMus* window = GetWindowByServerId(window_id); if (!window || !IsRoot(window)) return; @@ -1797,7 +1800,7 @@ void WindowTreeClient::WmDisplayModified(const display::Display& display) { } void WindowTreeClient::WmSetBounds(uint32_t change_id, - Id window_id, + ui::Id window_id, const gfx::Rect& transit_bounds_in_pixels) { WindowMus* window = GetWindowByServerId(window_id); if (window) { @@ -1816,7 +1819,7 @@ void WindowTreeClient::WmSetBounds(uint32_t change_id, void WindowTreeClient::WmSetProperty( uint32_t change_id, - Id window_id, + ui::Id window_id, const std::string& name, const base::Optional<std::vector<uint8_t>>& transit_data) { WindowMus* window = GetWindowByServerId(window_id); @@ -1838,13 +1841,13 @@ void WindowTreeClient::WmSetProperty( window_manager_client_->WmResponse(change_id, result); } -void WindowTreeClient::WmSetModalType(Id window_id, ui::ModalType type) { +void WindowTreeClient::WmSetModalType(ui::Id window_id, ui::ModalType type) { WindowMus* window = GetWindowByServerId(window_id); if (window) window_manager_delegate_->OnWmSetModalType(window->GetWindow(), type); } -void WindowTreeClient::WmSetCanFocus(Id window_id, bool can_focus) { +void WindowTreeClient::WmSetCanFocus(ui::Id window_id, bool can_focus) { WindowMus* window = GetWindowByServerId(window_id); if (window) window_manager_delegate_->OnWmSetCanFocus(window->GetWindow(), can_focus); @@ -1873,7 +1876,7 @@ void WindowTreeClient::WmCreateTopLevelWindow( kInvalidServerId); return; } - embedded_windows_[base::checked_cast<ClientSpecificId>( + embedded_windows_[base::checked_cast<ui::ClientSpecificId>( frame_sink_id.client_id())] .insert(window); if (window_manager_client_) { @@ -1883,7 +1886,7 @@ void WindowTreeClient::WmCreateTopLevelWindow( } } -void WindowTreeClient::WmClientJankinessChanged(ClientSpecificId client_id, +void WindowTreeClient::WmClientJankinessChanged(ui::ClientSpecificId client_id, bool janky) { if (window_manager_delegate_) { auto it = embedded_windows_.find(client_id); @@ -1926,7 +1929,7 @@ void WindowTreeClient::WmDestroyDragImage() { } void WindowTreeClient::WmPerformMoveLoop(uint32_t change_id, - Id window_id, + ui::Id window_id, ui::mojom::MoveLoopSource source, const gfx::Point& cursor_location) { if (!window_manager_delegate_ || current_wm_move_loop_change_ != 0) { @@ -1956,7 +1959,7 @@ void WindowTreeClient::WmCancelMoveLoop(uint32_t change_id) { window_manager_delegate_->OnWmCancelMoveLoop(window->GetWindow()); } -void WindowTreeClient::WmDeactivateWindow(Id window_id) { +void WindowTreeClient::WmDeactivateWindow(ui::Id window_id) { if (!window_manager_delegate_) return; @@ -1974,8 +1977,9 @@ void WindowTreeClient::WmDeactivateWindow(Id window_id) { window_manager_delegate_->OnWmDeactivateWindow(window->GetWindow()); } -void WindowTreeClient::WmStackAbove(uint32_t wm_change_id, Id above_id, - Id below_id) { +void WindowTreeClient::WmStackAbove(uint32_t wm_change_id, + ui::Id above_id, + ui::Id below_id) { if (!window_manager_delegate_) return; @@ -2011,7 +2015,7 @@ void WindowTreeClient::WmStackAbove(uint32_t wm_change_id, Id above_id, window_manager_client_->WmResponse(wm_change_id, true); } -void WindowTreeClient::WmStackAtTop(uint32_t wm_change_id, uint32_t window_id) { +void WindowTreeClient::WmStackAtTop(uint32_t wm_change_id, ui::Id window_id) { if (!window_manager_delegate_) return; @@ -2030,7 +2034,7 @@ void WindowTreeClient::WmStackAtTop(uint32_t wm_change_id, uint32_t window_id) { window_manager_client_->WmResponse(wm_change_id, true); } -void WindowTreeClient::WmPerformWmAction(Id window_id, +void WindowTreeClient::WmPerformWmAction(ui::Id window_id, const std::string& action) { if (!window_manager_delegate_) return; @@ -2056,7 +2060,7 @@ void WindowTreeClient::OnCursorTouchVisibleChanged(bool enabled) { window_manager_delegate_->OnCursorTouchVisibleChanged(enabled); } -void WindowTreeClient::OnEventBlockedByModalWindow(Id window_id) { +void WindowTreeClient::OnEventBlockedByModalWindow(ui::Id window_id) { if (!window_manager_delegate_) return; @@ -2162,7 +2166,7 @@ void WindowTreeClient::InjectEvent(const ui::Event& event, int64_t display_id) { // refused. if (event_injector_) { event_injector_->DispatchEvent(display_id, ui::Event::Clone(event), - base::Bind([](bool result) {})); + base::DoNothing()); } } diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h index de8395f2627..1a887b9a322 100644 --- a/chromium/ui/aura/mus/window_tree_client.h +++ b/chromium/ui/aura/mus/window_tree_client.h @@ -165,7 +165,7 @@ class AURA_EXPORT WindowTreeClient base::OnceCallback<void(const base::UnguessableToken&)> callback); void AttachCompositorFrameSink( - Id window_id, + ui::Id window_id, viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, viz::mojom::CompositorFrameSinkClientPtr client); @@ -207,14 +207,14 @@ class AURA_EXPORT WindowTreeClient SERVER, }; - using IdToWindowMap = std::map<Id, WindowMus*>; + using IdToWindowMap = std::map<ui::Id, WindowMus*>; // TODO(sky): this assumes change_ids never wrap, which is a bad assumption. using InFlightMap = std::map<uint32_t, std::unique_ptr<InFlightChange>>; void RegisterWindowMus(WindowMus* window); - WindowMus* GetWindowByServerId(Id id); + WindowMus* GetWindowByServerId(ui::Id id); bool IsWindowKnown(aura::Window* window); @@ -296,7 +296,7 @@ class AURA_EXPORT WindowTreeClient void OnEmbedImpl(ui::mojom::WindowTree* window_tree, ui::mojom::WindowDataPtr root_data, int64_t display_id, - Id focused_window_id, + ui::Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id); @@ -361,14 +361,14 @@ class AURA_EXPORT WindowTreeClient ui::mojom::WindowDataPtr root, ui::mojom::WindowTreePtr tree, int64_t display_id, - Id focused_window_id, + ui::Id focused_window_id, bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnEmbeddedAppDisconnected(Id window_id) override; - void OnUnembed(Id window_id) override; - void OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) override; - void OnFrameSinkIdAllocated(Id window_id, + void OnEmbeddedAppDisconnected(ui::Id window_id) override; + void OnUnembed(ui::Id window_id) override; + void OnCaptureChanged(ui::Id new_capture_window_id, + ui::Id old_capture_window_id) override; + void OnFrameSinkIdAllocated(ui::Id window_id, const viz::FrameSinkId& frame_sink_id) override; void OnTopLevelCreated( uint32_t change_id, @@ -377,79 +377,79 @@ class AURA_EXPORT WindowTreeClient bool drawn, const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; void OnWindowBoundsChanged( - Id window_id, + ui::Id window_id, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnWindowTransformChanged(Id window_id, + void OnWindowTransformChanged(ui::Id window_id, const gfx::Transform& old_transform, const gfx::Transform& new_transform) override; void OnClientAreaChanged( - uint32_t window_id, + ui::Id window_id, const gfx::Insets& new_client_area, const std::vector<gfx::Rect>& new_additional_client_areas) override; - void OnTransientWindowAdded(uint32_t window_id, - uint32_t transient_window_id) override; - void OnTransientWindowRemoved(uint32_t window_id, - uint32_t transient_window_id) override; + void OnTransientWindowAdded(ui::Id window_id, + ui::Id transient_window_id) override; + void OnTransientWindowRemoved(ui::Id window_id, + ui::Id transient_window_id) override; void OnWindowHierarchyChanged( - Id window_id, - Id old_parent_id, - Id new_parent_id, + ui::Id window_id, + ui::Id old_parent_id, + ui::Id new_parent_id, std::vector<ui::mojom::WindowDataPtr> windows) override; - void OnWindowReordered(Id window_id, - Id relative_window_id, + void OnWindowReordered(ui::Id window_id, + ui::Id relative_window_id, ui::mojom::OrderDirection direction) override; - void OnWindowDeleted(Id window_id) override; - void OnWindowVisibilityChanged(Id window_id, bool visible) override; - void OnWindowOpacityChanged(Id window_id, + void OnWindowDeleted(ui::Id window_id) override; + void OnWindowVisibilityChanged(ui::Id window_id, bool visible) override; + void OnWindowOpacityChanged(ui::Id window_id, float old_opacity, float new_opacity) override; - void OnWindowParentDrawnStateChanged(Id window_id, bool drawn) override; + void OnWindowParentDrawnStateChanged(ui::Id window_id, bool drawn) override; void OnWindowSharedPropertyChanged( - Id window_id, + ui::Id window_id, const std::string& name, const base::Optional<std::vector<uint8_t>>& transport_data) override; void OnWindowInputEvent( uint32_t event_id, - Id window_id, + ui::Id window_id, int64_t display_id, - Id display_root_window_id, + ui::Id display_root_window_id, const gfx::PointF& event_location_in_screen_pixel_layout, std::unique_ptr<ui::Event> event, bool matches_pointer_watcher) override; void OnPointerEventObserved(std::unique_ptr<ui::Event> event, - uint32_t window_id, + ui::Id window_id, int64_t display_id) override; - void OnWindowFocused(Id focused_window_id) override; - void OnWindowCursorChanged(Id window_id, ui::CursorData cursor) override; - void OnWindowSurfaceChanged(Id window_id, + void OnWindowFocused(ui::Id focused_window_id) override; + void OnWindowCursorChanged(ui::Id window_id, ui::CursorData cursor) override; + void OnWindowSurfaceChanged(ui::Id window_id, const viz::SurfaceInfo& surface_info) override; void OnDragDropStart( const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) override; - void OnDragEnter(Id window_id, + void OnDragEnter(ui::Id window_id, uint32_t event_flags, const gfx::Point& position, uint32_t effect_bitmask, const OnDragEnterCallback& callback) override; - void OnDragOver(Id window_id, + void OnDragOver(ui::Id window_id, uint32_t event_flags, const gfx::Point& position, uint32_t effect_bitmask, const OnDragOverCallback& callback) override; - void OnDragLeave(Id window_id) override; - void OnCompleteDrop(Id window_id, + void OnDragLeave(ui::Id window_id) override; + void OnCompleteDrop(ui::Id window_id, uint32_t event_flags, const gfx::Point& position, uint32_t effect_bitmask, const OnCompleteDropCallback& callback) override; - void OnPerformDragDropCompleted(uint32_t window, + void OnPerformDragDropCompleted(uint32_t change_id, bool success, uint32_t action_taken) override; void OnDragDropDone() override; void OnChangeCompleted(uint32_t change_id, bool success) override; - void RequestClose(uint32_t window_id) override; + void RequestClose(ui::Id window_id) override; void SetBlockingContainers( const std::vector<BlockingContainers>& all_blocking_containers) override; void GetWindowManager( @@ -468,21 +468,21 @@ class AURA_EXPORT WindowTreeClient void WmDisplayRemoved(int64_t display_id) override; void WmDisplayModified(const display::Display& display) override; void WmSetBounds(uint32_t change_id, - Id window_id, + ui::Id window_id, const gfx::Rect& transit_bounds_in_pixels) override; void WmSetProperty( uint32_t change_id, - Id window_id, + ui::Id window_id, const std::string& name, const base::Optional<std::vector<uint8_t>>& transit_data) override; - void WmSetModalType(Id window_id, ui::ModalType type) override; - void WmSetCanFocus(Id window_id, bool can_focus) override; + void WmSetModalType(ui::Id window_id, ui::ModalType type) override; + void WmSetCanFocus(ui::Id window_id, bool can_focus) override; void WmCreateTopLevelWindow( uint32_t change_id, const viz::FrameSinkId& frame_sink_id, const std::unordered_map<std::string, std::vector<uint8_t>>& transport_properties) override; - void WmClientJankinessChanged(ClientSpecificId client_id, + void WmClientJankinessChanged(ui::ClientSpecificId client_id, bool janky) override; void WmBuildDragImage(const gfx::Point& screen_location, const SkBitmap& drag_image, @@ -492,19 +492,21 @@ class AURA_EXPORT WindowTreeClient const WmMoveDragImageCallback& callback) override; void WmDestroyDragImage() override; void WmPerformMoveLoop(uint32_t change_id, - Id window_id, + ui::Id window_id, ui::mojom::MoveLoopSource source, const gfx::Point& cursor_location) override; - void WmCancelMoveLoop(uint32_t window_id) override; - void WmDeactivateWindow(Id window_id) override; - void WmStackAbove(uint32_t change_id, Id above_id, Id below_id) override; - void WmStackAtTop(uint32_t change_id, uint32_t window_id) override; - void WmPerformWmAction(Id window_id, const std::string& action) override; + void WmCancelMoveLoop(uint32_t change_id) override; + void WmDeactivateWindow(ui::Id window_id) override; + void WmStackAbove(uint32_t change_id, + ui::Id above_id, + ui::Id below_id) override; + void WmStackAtTop(uint32_t change_id, ui::Id window_id) override; + void WmPerformWmAction(ui::Id window_id, const std::string& action) override; 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; + void OnEventBlockedByModalWindow(ui::Id window_id) override; // Overridden from WindowManagerClient: void SetFrameDecorationValues( @@ -602,7 +604,7 @@ class AURA_EXPORT WindowTreeClient service_manager::Connector* connector_; // Id assigned to the next window created. - ClientSpecificId next_window_id_; + ui::ClientSpecificId next_window_id_; // Id used for the next change id supplied to the server. uint32_t next_change_id_; @@ -615,7 +617,7 @@ class AURA_EXPORT WindowTreeClient std::set<WindowMus*> roots_; IdToWindowMap windows_; - std::map<ClientSpecificId, std::set<Window*>> embedded_windows_; + std::map<ui::ClientSpecificId, std::set<Window*>> embedded_windows_; std::unique_ptr<CaptureSynchronizer> capture_synchronizer_; @@ -660,7 +662,7 @@ class AURA_EXPORT WindowTreeClient // The current change id for the window manager. uint32_t current_wm_move_loop_change_ = 0u; - Id current_wm_move_loop_window_id_ = 0u; + ui::Id current_wm_move_loop_window_id_ = 0u; std::unique_ptr<DragDropControllerMus> drag_drop_controller_; diff --git a/chromium/ui/aura/mus/window_tree_client_delegate.h b/chromium/ui/aura/mus/window_tree_client_delegate.h index e76d2efbac0..2481d0e0fdf 100644 --- a/chromium/ui/aura/mus/window_tree_client_delegate.h +++ b/chromium/ui/aura/mus/window_tree_client_delegate.h @@ -8,7 +8,7 @@ #include <memory> #include <string> -#include "services/service_manager/public/interfaces/interface_provider.mojom.h" +#include "services/service_manager/public/mojom/interface_provider.mojom.h" #include "services/ui/public/interfaces/window_tree.mojom.h" #include "ui/aura/aura_export.h" diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc index 07e385325c5..1ed6c0c3428 100644 --- a/chromium/ui/aura/mus/window_tree_client_unittest.cc +++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "cc/base/switches.h" #include "components/viz/common/surfaces/surface_info.h" @@ -44,6 +45,7 @@ #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host_observer.h" #include "ui/base/class_property.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" #include "ui/compositor/compositor.h" #include "ui/display/display.h" @@ -68,13 +70,13 @@ const char kTestPropertyServerKey1[] = "test-property-server1"; const char kTestPropertyServerKey2[] = "test-property-server2"; const char kTestPropertyServerKey3[] = "test-property-server3"; -Id server_id(Window* window) { +ui::Id server_id(Window* window) { return window ? WindowMus::Get(window)->server_id() : 0; } std::unique_ptr<Window> CreateWindowUsingId( WindowTreeClient* window_tree_client, - Id server_id, + ui::Id server_id, Window* parent = nullptr) { ui::mojom::WindowData window_data; window_data.window_id = server_id; @@ -194,9 +196,7 @@ class WindowTreeClientWmTestSurfaceSync // WindowTreeClientWmTest: void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMus); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kMusHostingViz); + feature_list_.InitAndEnableFeature(features::kMash); if (GetParam()) { base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kForceDeviceScaleFactor, "2"); @@ -205,6 +205,8 @@ class WindowTreeClientWmTestSurfaceSync } private: + base::test::ScopedFeatureList feature_list_; + DISALLOW_COPY_AND_ASSIGN(WindowTreeClientWmTestSurfaceSync); }; @@ -485,7 +487,7 @@ TEST_P(WindowTreeClientWmTestSurfaceSync, SetBoundsLocalSurfaceIdChanges) { // Verifies a new window from the server doesn't result in attempting to add // the window back to the server. TEST_F(WindowTreeClientWmTest, AddFromServerDoesntAddAgain) { - const Id child_window_id = server_id(root_window()) + 11; + const ui::Id child_window_id = server_id(root_window()) + 11; ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New(); data->parent_id = server_id(root_window()); data->window_id = child_window_id; @@ -527,7 +529,7 @@ TEST_F(WindowTreeClientWmTest, ReparentFromServerDoesntAddAgain) { TEST_F(WindowTreeClientWmTest, OnWindowHierarchyChangedWithProperties) { RegisterTestProperties(GetPropertyConverter()); window_tree()->AckAllChanges(); - const Id child_window_id = server_id(root_window()) + 11; + const ui::Id child_window_id = server_id(root_window()) + 11; ui::mojom::WindowDataPtr data = ui::mojom::WindowData::New(); const uint8_t server_test_property1_value = 91; data->properties[kTestPropertyServerKey1] = @@ -535,6 +537,9 @@ TEST_F(WindowTreeClientWmTest, OnWindowHierarchyChangedWithProperties) { data->properties[ui::mojom::WindowManager::kWindowType_InitProperty] = mojo::ConvertTo<std::vector<uint8_t>>( static_cast<int32_t>(ui::mojom::WindowType::BUBBLE)); + constexpr int kWindowCornerRadiusValue = 6; + data->properties[ui::mojom::WindowManager::kWindowCornerRadius_Property] = + ConvertToPropertyTransportValue(kWindowCornerRadiusValue); data->parent_id = server_id(root_window()); data->window_id = child_window_id; data->bounds = gfx::Rect(1, 2, 3, 4); @@ -549,6 +554,8 @@ TEST_F(WindowTreeClientWmTest, OnWindowHierarchyChangedWithProperties) { Window* child = root_window()->children()[0]; EXPECT_FALSE(child->TargetVisibility()); EXPECT_EQ(server_test_property1_value, child->GetProperty(kTestPropertyKey1)); + EXPECT_EQ(kWindowCornerRadiusValue, + child->GetProperty(client::kWindowCornerRadiusKey)); EXPECT_EQ(child->type(), client::WINDOW_TYPE_POPUP); EXPECT_EQ(ui::mojom::WindowType::BUBBLE, child->GetProperty(client::kWindowTypeKey)); @@ -1009,7 +1016,7 @@ TEST_F(WindowTreeClientClientTest, InputEventBasic) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_child, gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child), window_tree_host.display_id(), Id(), + event_id, server_id(&child), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location_in_child), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); @@ -1045,7 +1052,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPointerEvent) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), base::TimeTicks()); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child), window_tree_host.display_id(), Id(), + event_id, server_id(&child), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(pointer_event), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1081,7 +1088,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPen) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_PEN, 0), ui::EventTimeForNow()); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child), window_tree_host.display_id(), Id(), + event_id, server_id(&child), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(pointer_event), 0); // Pen event was handled. @@ -1129,7 +1136,7 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child1), window_tree_host.display_id(), Id(), + event_id, server_id(&child1), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1150,7 +1157,7 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child1), window_tree_host.display_id(), Id(), + event_id, server_id(&child1), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(*ui_event1.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1198,7 +1205,7 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child1), window_tree_host.display_id(), Id(), + event_id, server_id(&child1), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1215,7 +1222,7 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) { window_delegate1.set_event_id(event_id); window_delegate2.set_event_id(event_id); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child2), window_tree_host.display_id(), Id(), + event_id, server_id(&child2), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1268,8 +1275,9 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location, root_location, ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(child1.get()), window_tree_host->display_id(), Id(), - gfx::PointF(root_location), ui::Event::Clone(*ui_event.get()), 0); + event_id, server_id(child1.get()), window_tree_host->display_id(), + ui::Id(), gfx::PointF(root_location), 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)); @@ -1291,8 +1299,9 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) { window_delegate1->set_event_id(event_id); window_delegate2->set_event_id(event_id); window_tree_client()->OnWindowInputEvent( - event_id, server_id(child1.get()), window_tree_host->display_id(), Id(), - gfx::PointF(root_location), ui::Event::Clone(*ui_event.get()), 0); + event_id, server_id(child1.get()), window_tree_host->display_id(), + ui::Id(), gfx::PointF(root_location), 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)); @@ -1338,7 +1347,7 @@ TEST_F(WindowTreeClientClientTest, InputEventRootWindow) { new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_child, gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0)); window_tree_client()->OnWindowInputEvent( - event_id, server_id(top_level), window_tree_host.display_id(), Id(), + event_id, server_id(top_level), window_tree_host.display_id(), ui::Id(), gfx::PointF(), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); @@ -1382,14 +1391,14 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), ui::EventTimeForNow()); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child), window_tree_host.display_id(), Id(), + event_id, server_id(&child), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(pointer_event_down), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, window_tree()->GetEventResult(event_id)); 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(ui::EF_LEFT_MOUSE_BUTTON, env->mouse_button_flags()); EXPECT_EQ(event_location, env->last_mouse_location()); window_delegate.reset(); @@ -1402,7 +1411,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0), ui::EventTimeForNow()); window_tree_client()->OnWindowInputEvent( - event_id, kInvalidServerId, window_tree_host.display_id(), Id(), + event_id, kInvalidServerId, window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location), ui::Event::Clone(pointer_event_up), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); // WindowTreeClient::OnWindowInputEvent cannot find a target window with @@ -1445,7 +1454,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0), ui::EventTimeForNow()); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child), window_tree_host.display_id(), Id(), + event_id, server_id(&child), window_tree_host.display_id(), ui::Id(), gfx::PointF(), ui::Event::Clone(pointer_event_down), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); EXPECT_EQ(ui::mojom::EventResult::HANDLED, @@ -1461,7 +1470,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) { ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0), ui::EventTimeForNow()); window_tree_client()->OnWindowInputEvent( - event_id, kInvalidServerId, window_tree_host.display_id(), Id(), + event_id, kInvalidServerId, window_tree_host.display_id(), ui::Id(), gfx::PointF(), ui::Event::Clone(pointer_event_up), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); // WindowTreeClient::OnWindowInputEvent cannot find a target window with @@ -1557,7 +1566,7 @@ TEST_F(WindowTreeClientPointerObserverTest, ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 0, ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1), base::TimeTicks::Now())); - window_tree_client()->OnWindowInputEvent(1, server_id(top_level), 0, Id(), + window_tree_client()->OnWindowInputEvent(1, server_id(top_level), 0, ui::Id(), gfx::PointF(), std::move(pointer_event_down), true); @@ -2483,7 +2492,7 @@ TEST_F(WindowTreeClientWmTest, OnWindowHierarchyChangedWithExistingWindow) { Window* window2 = new Window(nullptr); window2->Init(ui::LAYER_NOT_DRAWN); window_tree()->AckAllChanges(); - const Id server_window_id = server_id(root_window()) + 11; + const ui::Id server_window_id = server_id(root_window()) + 11; ui::mojom::WindowDataPtr data1 = ui::mojom::WindowData::New(); ui::mojom::WindowDataPtr data2 = ui::mojom::WindowData::New(); ui::mojom::WindowDataPtr data3 = ui::mojom::WindowData::New(); @@ -2602,7 +2611,7 @@ TEST_F(WindowTreeClientWmTest, FocusInDifferentDisplayThanEvent) { std::unique_ptr<ui::KeyEvent> key_event = std::make_unique<ui::KeyEvent>( ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, ui::EF_NONE); window_tree_client()->OnWindowInputEvent(1, server_id(&child2), kDisplayId2, - Id(), gfx::PointF(), + ui::Id(), gfx::PointF(), std::move(key_event), false); } @@ -2820,7 +2829,7 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) { 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(), Id(), + event_id, server_id(&child1), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location_in_pixels), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); @@ -2845,7 +2854,7 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) { window_delegate1.set_event_id(event_id); window_delegate2.set_event_id(event_id); window_tree_client()->OnWindowInputEvent( - event_id, server_id(&child2), window_tree_host.display_id(), Id(), + event_id, server_id(&child2), window_tree_host.display_id(), ui::Id(), gfx::PointF(event_location_in_pixels), ui::Event::Clone(*ui_event.get()), 0); EXPECT_TRUE(window_tree()->WasEventAcked(event_id)); diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc index a146cfc41b3..3acab45d4e2 100644 --- a/chromium/ui/aura/mus/window_tree_host_mus.cc +++ b/chromium/ui/aura/mus/window_tree_host_mus.cc @@ -15,6 +15,7 @@ #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_tree_host_observer.h" #include "ui/base/class_property.h" +#include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches_util.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -60,8 +61,9 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params) // If window-server is hosting viz, then use the FrameSinkId from the server. // In other cases, let a valid FrameSinkId be selected by // context_factory_private(). - CreateCompositor(switches::IsMusHostingViz() ? window_mus->GetFrameSinkId() - : viz::FrameSinkId()); + CreateCompositor(base::FeatureList::IsEnabled(features::kMash) + ? window_mus->GenerateFrameSinkIdFromServerId() + : viz::FrameSinkId()); if (!init_params.uses_real_accelerated_widget) { gfx::AcceleratedWidget accelerated_widget; // We need accelerated widget numbers to be different for each window and diff --git a/chromium/ui/aura/scoped_keyboard_hook.cc b/chromium/ui/aura/scoped_keyboard_hook.cc new file mode 100644 index 00000000000..96d9d778439 --- /dev/null +++ b/chromium/ui/aura/scoped_keyboard_hook.cc @@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/scoped_keyboard_hook.h" + +#include "base/macros.h" +#include "ui/aura/window_tree_host.h" + +namespace aura { + +ScopedKeyboardHook::ScopedKeyboardHook( + base::WeakPtr<WindowTreeHost> window_tree_host) + : window_tree_host_(window_tree_host) { + DCHECK(window_tree_host_); +} + +ScopedKeyboardHook::~ScopedKeyboardHook() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (window_tree_host_) + window_tree_host_->ReleaseSystemKeyEventCapture(); +} + +} // namespace aura diff --git a/chromium/ui/aura/scoped_keyboard_hook.h b/chromium/ui/aura/scoped_keyboard_hook.h new file mode 100644 index 00000000000..d061544aff2 --- /dev/null +++ b/chromium/ui/aura/scoped_keyboard_hook.h @@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_AURA_SCOPED_KEYBOARD_HOOK_H_ +#define UI_AURA_SCOPED_KEYBOARD_HOOK_H_ + +#include "base/memory/weak_ptr.h" +#include "base/threading/thread_checker.h" +#include "ui/aura/aura_export.h" + +namespace aura { + +class WindowTreeHost; + +// Destroying an instance of this class will clean up the KeyboardHook instance +// owned by WindowTreeHost and prevent future system key events from being +// captured. If the KeyboardHook or WindowTreeHost instances were already +// destroyed, then destroying this instance is a noop. +class AURA_EXPORT ScopedKeyboardHook { + public: + explicit ScopedKeyboardHook(base::WeakPtr<WindowTreeHost> weak_ptr); + ~ScopedKeyboardHook(); + + private: + THREAD_CHECKER(thread_checker_); + + base::WeakPtr<WindowTreeHost> window_tree_host_; + + DISALLOW_COPY_AND_ASSIGN(ScopedKeyboardHook); +}; + +} // namespace aura + +#endif // UI_AURA_SCOPED_KEYBOARD_HOOK_H_ diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc index 063a2861247..0f224d897e0 100644 --- a/chromium/ui/aura/window.cc +++ b/chromium/ui/aura/window.cc @@ -32,6 +32,7 @@ #include "ui/aura/env.h" #include "ui/aura/layout_manager.h" #include "ui/aura/local/layer_tree_frame_sink_local.h" +#include "ui/aura/scoped_keyboard_hook.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_observer.h" @@ -39,6 +40,7 @@ #include "ui/aura/window_port.h" #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" +#include "ui/base/ui_base_features.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" @@ -643,6 +645,19 @@ bool Window::HasCapture() { return capture_client && capture_client->GetCaptureWindow() == this; } +std::unique_ptr<ScopedKeyboardHook> Window::CaptureSystemKeyEvents( + base::Optional<base::flat_set<int>> keys) { + Window* root_window = GetRootWindow(); + if (!root_window) + return nullptr; + + WindowTreeHost* host = root_window->GetHost(); + if (!host) + return nullptr; + + return host->CaptureSystemKeyEvents(std::move(keys)); +} + void Window::SuppressPaint() { layer()->SuppressPaint(); } @@ -779,13 +794,11 @@ void Window::SetVisible(bool visible) { NotifyWindowVisibilityChanged(this, visible); } -void Window::SetOccluded(bool occluded) { - OcclusionState occlusion_state = - occluded ? OcclusionState::OCCLUDED : OcclusionState::NOT_OCCLUDED; +void Window::SetOcclusionState(OcclusionState occlusion_state) { if (occlusion_state != occlusion_state_) { occlusion_state_ = occlusion_state; if (delegate_) - delegate_->OnWindowOcclusionChanged(occluded); + delegate_->OnWindowOcclusionChanged(occlusion_state); } } @@ -943,7 +956,8 @@ void Window::OnStackingChanged() { } void Window::NotifyRemovingFromRootWindow(Window* new_root) { - port_->OnWillRemoveWindowFromRootWindow(); + if (IsEmbeddingClient()) + UnregisterFrameSinkId(); for (WindowObserver& observer : observers_) observer.OnWindowRemovingFromRootWindow(this, new_root); for (Window::Windows::const_iterator it = children_.begin(); @@ -953,7 +967,8 @@ void Window::NotifyRemovingFromRootWindow(Window* new_root) { } void Window::NotifyAddedToRootWindow() { - port_->OnWindowAddedToRootWindow(); + if (IsEmbeddingClient()) + RegisterFrameSinkId(); for (WindowObserver& observer : observers_) observer.OnWindowAddedToRootWindow(this); for (Window::Windows::const_iterator it = children_.begin(); @@ -1032,23 +1047,18 @@ bool Window::NotifyWindowVisibilityChangedDown(aura::Window* target, bool visible) { if (!NotifyWindowVisibilityChangedAtReceiver(target, visible)) return false; // |this| was deleted. - std::set<const Window*> child_already_processed; - bool child_destroyed = false; - do { - child_destroyed = false; - for (Window::Windows::const_iterator it = children_.begin(); - it != children_.end(); ++it) { - if (!child_already_processed.insert(*it).second) - continue; - if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) { - // |*it| was deleted, |it| is invalid and |children_| has changed. - // We exit the current for-loop and enter a new one. - child_destroyed = true; - break; - } - } - } while (child_destroyed); - return true; + + WindowTracker this_tracker; + this_tracker.Add(this); + // Copy |children_| in case iterating mutates |children_|, or destroys an + // existing child. + WindowTracker children(children_); + + while (!this_tracker.windows().empty() && !children.windows().empty()) + children.Pop()->NotifyWindowVisibilityChangedDown(target, visible); + + const bool this_still_valid = !this_tracker.windows().empty(); + return this_still_valid; } void Window::NotifyWindowVisibilityChangedUp(aura::Window* target, @@ -1075,11 +1085,15 @@ bool Window::CleanupGestureState() { } std::unique_ptr<cc::LayerTreeFrameSink> Window::CreateLayerTreeFrameSink() { - return port_->CreateLayerTreeFrameSink(); + auto sink = port_->CreateLayerTreeFrameSink(); + DCHECK(frame_sink_id_.is_valid()); + DCHECK(embeds_external_client_); + DCHECK(GetLocalSurfaceId().is_valid()); + return sink; } viz::SurfaceId Window::GetSurfaceId() const { - return port_->GetSurfaceId(); + return viz::SurfaceId(GetFrameSinkId(), port_->GetLocalSurfaceId()); } void Window::AllocateLocalSurfaceId() { @@ -1090,18 +1104,25 @@ const viz::LocalSurfaceId& Window::GetLocalSurfaceId() const { return port_->GetLocalSurfaceId(); } -viz::FrameSinkId Window::GetFrameSinkId() const { +const viz::FrameSinkId& Window::GetFrameSinkId() const { if (IsRootWindow()) { DCHECK(host_); auto* compositor = host_->compositor(); DCHECK(compositor); return compositor->frame_sink_id(); } - return port_->GetFrameSinkId(); + return frame_sink_id_; +} + +void Window::SetEmbedFrameSinkId(const viz::FrameSinkId& frame_sink_id) { + DCHECK(frame_sink_id.is_valid()); + frame_sink_id_ = frame_sink_id; + embeds_external_client_ = true; + RegisterFrameSinkId(); } bool Window::IsEmbeddingClient() const { - return embed_frame_sink_id_.is_valid(); + return embeds_external_client_; } void Window::OnPaintLayer(const ui::PaintContext& context) { @@ -1241,4 +1262,23 @@ void Window::UpdateLayerName() { #endif } +void Window::RegisterFrameSinkId() { + DCHECK(frame_sink_id_.is_valid()); + DCHECK(IsEmbeddingClient()); + if (registered_frame_sink_id_ || disable_frame_sink_id_registration_) + return; + if (auto* compositor = layer()->GetCompositor()) { + compositor->AddFrameSink(frame_sink_id_); + registered_frame_sink_id_ = true; + } +} + +void Window::UnregisterFrameSinkId() { + if (!registered_frame_sink_id_) + return; + registered_frame_sink_id_ = false; + if (auto* compositor = layer()->GetCompositor()) + compositor->RemoveFrameSink(frame_sink_id_); +} + } // namespace aura diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h index d2ef6774f3c..b6e2dcfb871 100644 --- a/chromium/ui/aura/window.h +++ b/chromium/ui/aura/window.h @@ -14,8 +14,10 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/observer_list.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "ui/aura/aura_export.h" #include "ui/aura/client/window_types.h" @@ -53,6 +55,7 @@ enum class EventTargetingPolicy; namespace aura { class LayoutManager; +class ScopedKeyboardHook; class WindowDelegate; class WindowObserver; class WindowPort; @@ -88,12 +91,26 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // The window's occlusion state isn't tracked // (WindowOcclusionTracker::Track) or hasn't been computed yet. UNKNOWN, - // The window is occluded, i.e. one of these conditions is true: - // - The window is hidden (Window::IsVisible() is true). - // - The bounds of the window are completely covered by opaque windows. + // The window or one of its descendants IsVisible() [1] and: + // - Its bounds aren't completely covered by fully opaque windows [2], or, + // - Its transform, bounds or opacity is animated. + VISIBLE, + // The window or one of its descendants IsVisible() [1], but they all: + // - Have bounds completely covered by fully opaque windows [2], and, + // - Have no transform, bounds or opacity animation. OCCLUDED, - // The window is not occluded. - NOT_OCCLUDED, + // The window is not IsVisible() [1]. + HIDDEN, + // [1] A window can only be IsVisible() if all its parent are IsVisible(). + // [2] A window is "fully opaque" if: + // - It's visible (IsVisible()). + // - It's not transparent (transparent()). + // - It's transform, bounds and opacity aren't animated. + // - Its combined opacity is 1 (GetCombinedOpacity()). + // - The type of its layer is not ui::LAYER_NOT_DRAWN. + // + // TODO(fdoray): A window that clips its children shouldn't be VISIBLE just + // because it has an animated child. }; typedef std::vector<Window*> Windows; @@ -167,10 +184,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // account the visibility of the layer and ancestors, where as this tracks // whether Show() without a Hide() has been invoked. bool TargetVisibility() const { return visible_; } - // Returns the occlusion state of this window. Will be UNKNOWN if the - // occlusion state of this window isn't tracked - // (WindowOcclusionTracker::Track). Will be stale if called within the scope - // of a WindowOcclusionTracker::ScopedPauseOcclusionTracking. + // Returns the occlusion state of this window. Is UNKNOWN if the occlusion + // state of this window isn't tracked (WindowOcclusionTracker::Track) or + // hasn't been computed yet. Is stale if called within the scope of a + // WindowOcclusionTracker::ScopedPauseOcclusionTracking. OcclusionState occlusion_state() const { return occlusion_state_; } // Returns the window's bounds in root window's coordinates. @@ -321,6 +338,13 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Returns true if this window has capture. bool HasCapture(); + // Requests that |keys| be intercepted at the platform level and routed + // directly to the web content. If |keys| has no value, all keys will be + // intercepted. Returns a ScopedKeyboardHook instance which stops capturing + // system key events when destroyed. + std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents( + base::Optional<base::flat_set<int>> keys); + // Suppresses painting window content by disgarding damaged rect and ignoring // new paint requests. This is a one way operation and there is no way to // reenable painting. @@ -368,15 +392,18 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Returns the FrameSinkId. In LOCAL mode, this returns a valid FrameSinkId // only if a LayerTreeFrameSink has been created. In MUS mode, this always // return a valid FrameSinkId. - viz::FrameSinkId GetFrameSinkId() const; - - const viz::FrameSinkId& embed_frame_sink_id() const { - return embed_frame_sink_id_; - } - void set_embed_frame_sink_id(const viz::FrameSinkId& embed_frame_sink_id) { - embed_frame_sink_id_ = embed_frame_sink_id; + const viz::FrameSinkId& GetFrameSinkId() const; + + // Use SetEmbedFrameSinkId() when this window is embedding another client. + // See comment for |frame_sink_id_| below for more details. + void SetEmbedFrameSinkId(const viz::FrameSinkId& embed_frame_sink_id); + void set_frame_sink_id(const viz::FrameSinkId& frame_sink_id) { + DCHECK(!embeds_external_client_); + DCHECK(!frame_sink_id_.is_valid()); + frame_sink_id_ = frame_sink_id; } - // Returns whether this window is an embed window. + + // Returns whether this window is embedding another client. bool IsEmbeddingClient() const; protected: @@ -415,7 +442,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate, void SetVisible(bool visible); // Updates the occlusion state of the window. - void SetOccluded(bool occluded); + void SetOcclusionState(OcclusionState occlusion_state); // Schedules a paint for the Window's entire bounds. void SchedulePaint(); @@ -505,6 +532,11 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Updates the layer name based on the window's name and id. void UpdateLayerName(); + void RegisterFrameSinkId(); + void UnregisterFrameSinkId(); + bool registered_frame_sink_id_ = false; + bool disable_frame_sink_id_registration_ = false; + // Window owns its corresponding WindowPort, but the ref is held as a raw // pointer in |port_| so that it can still be accessed during destruction. // This is important as deleting the WindowPort may result in trying to lookup @@ -547,8 +579,13 @@ class AURA_EXPORT Window : public ui::LayerDelegate, int id_; - // Only set when it is embedding another client inside. - viz::FrameSinkId embed_frame_sink_id_; + // The FrameSinkId associated with this window. If this window is embedding + // another client, then this should be set to the FrameSinkId of that client, + // and |embeds_external_client_| is turned on. However, a window can still + // have a valid FrameSinkId without embedding another client, to facilitate + // hit-testing. + viz::FrameSinkId frame_sink_id_; + bool embeds_external_client_ = false; // Whether layer is initialized as non-opaque. Defaults to false. bool transparent_; diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h index a1ec4d98c72..2b24e2eb0ea 100644 --- a/chromium/ui/aura/window_delegate.h +++ b/chromium/ui/aura/window_delegate.h @@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "ui/aura/aura_export.h" +#include "ui/aura/window.h" #include "ui/events/event_constants.h" #include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" @@ -90,9 +91,10 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler { virtual void OnWindowTargetVisibilityChanged(bool visible) = 0; // Called when the occlusion state of the Window changes while tracked (see - // WindowOcclusionTracker::Track). |is_occluded| indicates whether the Window - // is occluded. Impls must not change any aura::Window. - virtual void OnWindowOcclusionChanged(bool is_occluded) {} + // WindowOcclusionTracker::Track). |occlusion_state| is the new occlusion + // state of the Window. + virtual void OnWindowOcclusionChanged( + Window::OcclusionState occlusion_state) {} // Called from Window::HitTest to check if the window has a custom hit test // mask. It works similar to the views counterparts. That is, if the function diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc index 6fb791a6183..8bfba9421b2 100644 --- a/chromium/ui/aura/window_event_dispatcher.cc +++ b/chromium/ui/aura/window_event_dispatcher.cc @@ -204,15 +204,22 @@ void WindowEventDispatcher::HoldPointerMoves() { void WindowEventDispatcher::ReleasePointerMoves() { --move_hold_count_; DCHECK_GE(move_hold_count_, 0); - if (!move_hold_count_ && held_move_event_) { - // We don't want to call DispatchHeldEvents directly, because this might be - // called from a deep stack while another event, in which case dispatching - // another one may not be safe/expected. Instead we post a task, that we - // may cancel if HoldPointerMoves is called again before it executes. - base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask( - FROM_HERE, base::Bind( - base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents), - held_event_factory_.GetWeakPtr())); + if (!move_hold_count_) { + if (held_move_event_) { + // We don't want to call DispatchHeldEvents directly, because this might + // be called from a deep stack while another event, in which case + // dispatching another one may not be safe/expected. Instead we post a + // task, that we may cancel if HoldPointerMoves is called again before it + // executes. + base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask( + FROM_HERE, + base::BindOnce( + base::IgnoreResult(&WindowEventDispatcher::DispatchHeldEvents), + held_event_factory_.GetWeakPtr())); + } else { + if (did_dispatch_held_move_event_callback_) + base::ResetAndReturn(&did_dispatch_held_move_event_callback_).Run(); + } } TRACE_EVENT_ASYNC_END0("ui", "WindowEventDispatcher::HoldPointerMoves", this); } @@ -765,8 +772,11 @@ void WindowEventDispatcher::OnWindowInitialized(Window* window) { // WindowEventDispatcher, private: ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() { - if (!held_repostable_event_ && !held_move_event_) + if (!held_repostable_event_ && !held_move_event_) { + if (did_dispatch_held_move_event_callback_) + base::ResetAndReturn(&did_dispatch_held_move_event_callback_).Run(); return DispatchDetails(); + } CHECK(!dispatching_held_event_); @@ -798,8 +808,12 @@ ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() { held_move_event_.reset(); } - if (!dispatch_details.dispatcher_destroyed) + if (!dispatch_details.dispatcher_destroyed) { dispatching_held_event_ = nullptr; + if (did_dispatch_held_move_event_callback_) + base::ResetAndReturn(&did_dispatch_held_move_event_callback_).Run(); + } + return dispatch_details; } diff --git a/chromium/ui/aura/window_event_dispatcher.h b/chromium/ui/aura/window_event_dispatcher.h index 4772bd1c962..283866d50b1 100644 --- a/chromium/ui/aura/window_event_dispatcher.h +++ b/chromium/ui/aura/window_event_dispatcher.h @@ -293,6 +293,10 @@ class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor, bool skip_ime_; + // This callback is called when the held move event is dispatched, or when + // pointer moves are released and there is no held move event. + base::OnceClosure did_dispatch_held_move_event_callback_; + // Used to schedule reposting an event. base::WeakPtrFactory<WindowEventDispatcher> repost_event_factory_; diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc index f70d4b415d9..dc9571ef34e 100644 --- a/chromium/ui/aura/window_event_dispatcher_unittest.cc +++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc @@ -35,6 +35,7 @@ #include "ui/aura/window_targeter.h" #include "ui/aura/window_tracker.h" #include "ui/base/hit_test.h" +#include "ui/base/ui_base_features.h" #include "ui/display/screen.h" #include "ui/events/event.h" #include "ui/events/event_handler.h" @@ -2959,19 +2960,19 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowEventDispatcherTest, ::testing::Values(test::BackendType::CLASSIC, test::BackendType::MUS, - test::BackendType::MUS_HOSTING_VIZ)); + test::BackendType::MASH)); INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowEventDispatcherTestWithMessageLoop, ::testing::Values(test::BackendType::CLASSIC, test::BackendType::MUS, - test::BackendType::MUS_HOSTING_VIZ)); + test::BackendType::MASH)); INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowEventDispatcherTestInHighDPI, ::testing::Values(test::BackendType::CLASSIC, test::BackendType::MUS, - test::BackendType::MUS_HOSTING_VIZ)); + test::BackendType::MASH)); using WindowEventDispatcherMusTest = test::AuraTestBaseMus; diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc index 80cc8830197..dff18bd85e7 100644 --- a/chromium/ui/aura/window_occlusion_tracker.cc +++ b/chromium/ui/aura/window_occlusion_tracker.cc @@ -4,11 +4,13 @@ #include "ui/aura/window_occlusion_tracker.h" +#include "base/auto_reset.h" #include "base/containers/adapters.h" +#include "base/debug/dump_without_crashing.h" #include "base/stl_util.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRegion.h" -#include "ui/aura/window.h" +#include "ui/aura/window_tracker.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/transform.h" @@ -23,6 +25,10 @@ constexpr ui::LayerAnimationElement::AnimatableProperties ui::LayerAnimationElement::TRANSFORM | ui::LayerAnimationElement::BOUNDS | ui::LayerAnimationElement::OPACITY; +// Maximum number of times that MaybeComputeOcclusion() should have to recompute +// occlusion states before they become stable. +constexpr int kMaxRecomputeOcclusion = 2; + WindowOcclusionTracker* g_tracker = nullptr; int g_num_pause_occlusion_tracking = 0; @@ -80,6 +86,17 @@ SkIRect GetWindowBoundsInRootWindow( return skirect_bounds; } +// Returns true iff the occlusion states in |tracked_windows| match those +// returned by Window::occlusion_state(). +bool OcclusionStatesMatch( + const base::flat_map<Window*, Window::OcclusionState>& tracked_windows) { + for (const auto& tracked_window : tracked_windows) { + if (tracked_window.second != tracked_window.first->occlusion_state()) + return false; + } + return true; +} + } // namespace WindowOcclusionTracker::ScopedPauseOcclusionTracking:: @@ -92,7 +109,7 @@ WindowOcclusionTracker::ScopedPauseOcclusionTracking:: --g_num_pause_occlusion_tracking; DCHECK_GE(g_num_pause_occlusion_tracking, 0); if (g_tracker) - g_tracker->MaybeRecomputeOcclusion(); + g_tracker->MaybeComputeOcclusion(); } void WindowOcclusionTracker::Track(Window* window) { @@ -102,7 +119,8 @@ void WindowOcclusionTracker::Track(Window* window) { if (!g_tracker) g_tracker = new WindowOcclusionTracker(); - auto insert_result = g_tracker->tracked_windows_.insert(window); + auto insert_result = g_tracker->tracked_windows_.insert( + {window, Window::OcclusionState::UNKNOWN}); DCHECK(insert_result.second); if (!window->HasObserver(g_tracker)) window->AddObserver(g_tracker); @@ -114,39 +132,90 @@ WindowOcclusionTracker::WindowOcclusionTracker() = default; WindowOcclusionTracker::~WindowOcclusionTracker() = default; -void WindowOcclusionTracker::MaybeRecomputeOcclusion() { - if (g_num_pause_occlusion_tracking) +void WindowOcclusionTracker::MaybeComputeOcclusion() { + if (g_num_pause_occlusion_tracking || num_times_occlusion_recomputed_ != 0) return; - for (auto& root_window_pair : root_windows_) { - RootWindowState& root_window_state = root_window_pair.second; - if (root_window_state.dirty == true) { - ScopedPauseOcclusionTracking scoped_pause_occlusion_tracking; - root_window_state.dirty = false; - SkRegion occluded_region; - RecomputeOcclusionImpl(root_window_pair.first, gfx::Transform(), nullptr, - &occluded_region); - // WindowDelegate::OnWindowOcclusionChanged() impls must not change any - // Window. - DCHECK(!root_window_state.dirty); + + base::AutoReset<int> auto_reset(&num_times_occlusion_recomputed_, 0); + + // Recompute occlusion states until either: + // - They are stable, i.e. calling Window::SetOcclusionState() on all tracked + // windows does not provoke changes that could affect occlusion. + // - Occlusion states have been recomputed + // |kMaxComputeOcclusionIterationsBeforeStable| + // times. + // If occlusion states have been recomputed + // |kMaxComputeOcclusionIterationsBeforeStable| times and are still not + // stable, iterate one last time to set the occlusion state of all tracked + // windows based on IsVisible(). + while (num_times_occlusion_recomputed_ <= kMaxRecomputeOcclusion) { + const bool exceeded_max_num_times_occlusion_recomputed = + num_times_occlusion_recomputed_ == kMaxRecomputeOcclusion; + bool found_dirty_root = false; + + // Compute occlusion states and store them in |tracked_windows_|. Do not + // call Window::SetOcclusionState() in this phase to prevent changes to the + // window tree while it is being traversed. + for (auto& root_window_pair : root_windows_) { + if (root_window_pair.second.dirty) { + found_dirty_root = true; + root_window_pair.second.dirty = false; + if (!exceeded_max_num_times_occlusion_recomputed) { + SkRegion occluded_region; + RecomputeOcclusionImpl(root_window_pair.first, gfx::Transform(), + nullptr, &occluded_region); + } + } + } + + ++num_times_occlusion_recomputed_; + + if (!found_dirty_root) + break; + + // Call Window::SetOcclusionState() on tracked windows. A WindowDelegate may + // change the window tree in response to this. + WindowTracker tracked_windows_list; + for (const auto& tracked_window : tracked_windows_) + tracked_windows_list.Add(tracked_window.first); + + while (!tracked_windows_list.windows().empty()) { + Window* window = tracked_windows_list.Pop(); + auto it = tracked_windows_.find(window); + if (it != tracked_windows_.end() && + it->second != Window::OcclusionState::UNKNOWN) { + // Fallback to VISIBLE/HIDDEN if the maximum number of times that + // occlusion can be recomputed was exceeded. + if (exceeded_max_num_times_occlusion_recomputed) { + it->second = window->IsVisible() ? Window::OcclusionState::VISIBLE + : Window::OcclusionState::HIDDEN; + } + + window->SetOcclusionState(it->second); + } } } + + // Sanity check: Occlusion states in |tracked_windows_| should match those + // returned by Window::occlusion_state(). + DCHECK(OcclusionStatesMatch(tracked_windows_)); } -void WindowOcclusionTracker::RecomputeOcclusionImpl( +bool WindowOcclusionTracker::RecomputeOcclusionImpl( Window* window, const gfx::Transform& parent_transform_relative_to_root, const SkIRect* clipped_bounds, SkRegion* occluded_region) { DCHECK(window); - if (WindowIsAnimated(window)) { - SetWindowAndDescendantsAreOccluded(window, false); - return; - } - if (!window->IsVisible()) { SetWindowAndDescendantsAreOccluded(window, true); - return; + return false; + } + + if (WindowIsAnimated(window)) { + SetWindowAndDescendantsAreOccluded(window, false); + return true; } // Compute window bounds. @@ -157,7 +226,7 @@ void WindowOcclusionTracker::RecomputeOcclusionImpl( // For simplicity, windows that are not axis-aligned are considered // unoccluded and do not occlude other windows. SetWindowAndDescendantsAreOccluded(window, false); - return; + return true; } const SkIRect window_bounds = GetWindowBoundsInRootWindow( window, transform_relative_to_root, clipped_bounds); @@ -165,19 +234,23 @@ void WindowOcclusionTracker::RecomputeOcclusionImpl( // Compute children occlusion states. const SkIRect* clipped_bounds_for_children = window->layer()->GetMasksToBounds() ? &window_bounds : clipped_bounds; + bool has_visible_child = false; for (auto* child : base::Reversed(window->children())) { - RecomputeOcclusionImpl(child, transform_relative_to_root, - clipped_bounds_for_children, occluded_region); + has_visible_child |= + RecomputeOcclusionImpl(child, transform_relative_to_root, + clipped_bounds_for_children, occluded_region); } // Compute window occlusion state. if (occluded_region->contains(window_bounds)) { - SetOccluded(window, true); - } else { - SetOccluded(window, false); - if (VisibleWindowIsOpaque(window)) - occluded_region->op(window_bounds, SkRegion::kUnion_Op); + SetOccluded(window, !has_visible_child); + return has_visible_child; } + + SetOccluded(window, false); + if (VisibleWindowIsOpaque(window)) + occluded_region->op(window_bounds, SkRegion::kUnion_Op); + return true; } void WindowOcclusionTracker::CleanupAnimatedWindows() { @@ -188,7 +261,7 @@ void WindowOcclusionTracker::CleanupAnimatedWindows() { animator->RemoveObserver(this); auto root_window_state_it = root_windows_.find(window->GetRootWindow()); if (root_window_state_it != root_windows_.end()) - root_window_state_it->second.dirty = true; + MarkRootWindowAsDirty(&root_window_state_it->second); return true; }); } @@ -219,9 +292,17 @@ void WindowOcclusionTracker::SetWindowAndDescendantsAreOccluded( SetWindowAndDescendantsAreOccluded(child_window, is_occluded); } -void WindowOcclusionTracker::SetOccluded(Window* window, bool occluded) { - if (WindowIsTracked(window)) - window->SetOccluded(occluded); +void WindowOcclusionTracker::SetOccluded(Window* window, bool is_occluded) { + auto tracked_window = tracked_windows_.find(window); + if (tracked_window == tracked_windows_.end()) + return; + + if (!window->IsVisible()) + tracked_window->second = Window::OcclusionState::HIDDEN; + else if (is_occluded) + tracked_window->second = Window::OcclusionState::OCCLUDED; + else + tracked_window->second = Window::OcclusionState::VISIBLE; } bool WindowOcclusionTracker::WindowIsTracked(Window* window) const { @@ -233,7 +314,7 @@ bool WindowOcclusionTracker::WindowIsAnimated(Window* window) const { } template <typename Predicate> -void WindowOcclusionTracker::MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf( +void WindowOcclusionTracker::MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf( Window* window, Predicate predicate) { Window* root_window = window->GetRootWindow(); @@ -253,11 +334,28 @@ void WindowOcclusionTracker::MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf( if (root_window_state_it->second.dirty) return; if (predicate()) { - root_window_state_it->second.dirty = true; - MaybeRecomputeOcclusion(); + MarkRootWindowAsDirty(&root_window_state_it->second); + MaybeComputeOcclusion(); } } +void WindowOcclusionTracker::MarkRootWindowAsDirty( + RootWindowState* root_window_state) { + root_window_state->dirty = true; + + // Generate a crash report when a root window is marked as dirty and occlusion + // states have been recomputed |kMaxRecomputeOcclusion| times, because it + // indicates that they are not stabilizing. Don't report it when + // |num_times_occlusion_recomputed_| is greater than |kMaxRecomputeOcclusion| + // to avoid generating multiple reports from the same client. + // + // TODO(fdoray): Remove this once we are confident that occlusion states are + // stable after |kMaxRecomputeOcclusion| iterations in production. + // https://crbug.com/813076 + if (num_times_occlusion_recomputed_ == kMaxRecomputeOcclusion) + base::debug::DumpWithoutCrashing(); +} + bool WindowOcclusionTracker::WindowOrParentIsAnimated(Window* window) const { while (window && !WindowIsAnimated(window)) window = window->parent(); @@ -315,8 +413,8 @@ void WindowOcclusionTracker::TrackedWindowAddedToRoot(Window* window) { ++root_window_state.num_tracked_windows; if (root_window_state.num_tracked_windows == 1) AddObserverToWindowAndDescendants(root_window); - root_window_state.dirty = true; - MaybeRecomputeOcclusion(); + MarkRootWindowAsDirty(&root_window_state); + MaybeComputeOcclusion(); } void WindowOcclusionTracker::TrackedWindowRemovedFromRoot(Window* window) { @@ -356,13 +454,13 @@ void WindowOcclusionTracker::AddObserverToWindowAndDescendants(Window* window) { void WindowOcclusionTracker::OnLayerAnimationEnded( ui::LayerAnimationSequence* sequence) { CleanupAnimatedWindows(); - MaybeRecomputeOcclusion(); + MaybeComputeOcclusion(); } void WindowOcclusionTracker::OnLayerAnimationAborted( ui::LayerAnimationSequence* sequence) { CleanupAnimatedWindows(); - MaybeRecomputeOcclusion(); + MaybeComputeOcclusion(); } void WindowOcclusionTracker::OnLayerAnimationScheduled( @@ -379,12 +477,12 @@ void WindowOcclusionTracker::OnWindowHierarchyChanged( } void WindowOcclusionTracker::OnWindowAdded(Window* window) { - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf( + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf( window, [=]() { return WindowMoveMayAffectOcclusionStates(window); }); } void WindowOcclusionTracker::OnWillRemoveWindow(Window* window) { - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf(window, [=]() { + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() { return !WindowOrParentIsAnimated(window) && WindowOrDescendantIsOpaque(window); }); @@ -392,7 +490,7 @@ void WindowOcclusionTracker::OnWillRemoveWindow(Window* window) { void WindowOcclusionTracker::OnWindowVisibilityChanged(Window* window, bool visible) { - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf( + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf( window, [=]() { return !WindowOrParentIsAnimated(window); }); } @@ -406,7 +504,7 @@ void WindowOcclusionTracker::OnWindowBoundsChanged( const bool animation_started = (reason == ui::PropertyChangeReason::FROM_ANIMATION) && MaybeObserveAnimatedWindow(window); - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf(window, [=]() { + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() { return animation_started || WindowMoveMayAffectOcclusionStates(window); }); } @@ -419,7 +517,7 @@ void WindowOcclusionTracker::OnWindowOpacitySet( const bool animation_started = (reason == ui::PropertyChangeReason::FROM_ANIMATION) && MaybeObserveAnimatedWindow(window); - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf(window, [=]() { + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() { return animation_started || !WindowOrParentIsAnimated(window); }); } @@ -432,13 +530,13 @@ void WindowOcclusionTracker::OnWindowTransformed( const bool animation_started = (reason == ui::PropertyChangeReason::FROM_ANIMATION) && MaybeObserveAnimatedWindow(window); - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf(window, [=]() { + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() { return animation_started || WindowMoveMayAffectOcclusionStates(window); }); } void WindowOcclusionTracker::OnWindowStackingChanged(Window* window) { - MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf( + MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf( window, [=]() { return WindowMoveMayAffectOcclusionStates(window); }); } @@ -483,8 +581,8 @@ void WindowOcclusionTracker::OnWindowLayerRecreated(Window* window) { animator->RemoveObserver(this); auto root_window_state_it = root_windows_.find(window->GetRootWindow()); if (root_window_state_it != root_windows_.end()) { - root_window_state_it->second.dirty = true; - MaybeRecomputeOcclusion(); + MarkRootWindowAsDirty(&root_window_state_it->second); + MaybeComputeOcclusion(); } } diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h index d3aa02b1ee8..c76f4f4eee0 100644 --- a/chromium/ui/aura/window_occlusion_tracker.h +++ b/chromium/ui/aura/window_occlusion_tracker.h @@ -9,6 +9,7 @@ #include "base/containers/flat_set.h" #include "base/macros.h" #include "ui/aura/aura_export.h" +#include "ui/aura/window.h" #include "ui/aura/window_observer.h" #include "ui/compositor/layer_animation_observer.h" @@ -21,8 +22,6 @@ class Transform; namespace aura { -class Window; - // Notifies tracked Windows when their occlusion state change. // // To start tracking the occlusion state of a Window, call @@ -55,20 +54,30 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, static void Track(Window* window); private: + struct RootWindowState { + // Number of Windows whose occlusion state is tracked under this root + // Window. + int num_tracked_windows = 0; + + // Whether the occlusion state of tracked Windows under this root is stale. + bool dirty = false; + }; + WindowOcclusionTracker(); ~WindowOcclusionTracker() override; // Recomputes the occlusion state of tracked windows under roots marked as // dirty in |root_windows_| if there are no active // ScopedPauseOcclusionTracking instance. - void MaybeRecomputeOcclusion(); + void MaybeComputeOcclusion(); // Recomputes the occlusion state of |window| and its descendants. // |parent_transform_relative_to_root| is the transform of |window->parent()| // relative to the root window. |clipped_bounds| is an optional mask for the // bounds of |window| and its descendants. |occluded_region| is a region - // covered by windows which are on top of |window|. - void RecomputeOcclusionImpl( + // covered by windows which are on top of |window|. Returns true if at least + // one window in the hierarchy starting at |window| is NOT_OCCLUDED. + bool RecomputeOcclusionImpl( Window* window, const gfx::Transform& parent_transform_relative_to_root, const SkIRect* clipped_bounds, @@ -82,13 +91,14 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, // |animated_windows_|, adds |window| to |animated_windows_| and returns true. bool MaybeObserveAnimatedWindow(Window* window); - // Calls SetOccluded(|is_occluded|) on |window| and its descendants if they - // are in |tracked_windows_|. + // Calls SetOccluded() with |is_occluded| as argument for |window| and its + // descendants. void SetWindowAndDescendantsAreOccluded(Window* window, bool is_occluded); - // Calls SetOccluded() on |window| with |occluded| as argument if |window| is - // in |tracked_windows_|. - void SetOccluded(Window* window, bool occluded); + // Updates the occlusion state of |window| in |tracked_windows_|, based on + // |is_occluded| and window->IsVisible(). No-op if |window| is not in + // |tracked_windows_|. + void SetOccluded(Window* window, bool is_occluded); // Returns true if |window| is in |tracked_windows_|. bool WindowIsTracked(Window* window) const; @@ -97,12 +107,15 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, bool WindowIsAnimated(Window* window) const; // If the root of |window| is not dirty and |predicate| is true, marks the - // root of |window| as dirty. Then, calls MaybeRecomputeOcclusion(). + // root of |window| as dirty. Then, calls MaybeComputeOcclusion(). // |predicate| is not evaluated if the root of |window| is already dirty when // this is called. template <typename Predicate> - void MarkRootWindowAsDirtyAndMaybeRecomputeOcclusionIf(Window* window, - Predicate predicate); + void MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(Window* window, + Predicate predicate); + + // Marks |root_window| as dirty. + void MarkRootWindowAsDirty(RootWindowState* root_window_state); // Returns true if |window| or one of its parents is in |animated_windows_|. bool WindowOrParentIsAnimated(Window* window) const; @@ -162,17 +175,8 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, Window* new_root) override; void OnWindowLayerRecreated(Window* window) override; - struct RootWindowState { - // Number of Windows whose occlusion state is tracked under this root - // Window. - int num_tracked_windows = 0; - - // Whether the occlusion state of tracked Windows under this root is stale. - bool dirty = false; - }; - // Windows whose occlusion state is tracked. - base::flat_set<Window*> tracked_windows_; + base::flat_map<Window*, Window::OcclusionState> tracked_windows_; // Windows whose bounds or transform are animated. // @@ -186,6 +190,10 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver, // Root Windows of Windows in |tracked_windows_|. base::flat_map<Window*, RootWindowState> root_windows_; + // Number of times that the current call to MaybeComputeOcclusion() has + // recomputed occlusion states. Always 0 when not in MaybeComputeOcclusion(). + int num_times_occlusion_recomputed_ = 0; + DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTracker); }; diff --git a/chromium/ui/aura/window_occlusion_tracker_unittest.cc b/chromium/ui/aura/window_occlusion_tracker_unittest.cc index 1e04ab52382..6394bd7e42f 100644 --- a/chromium/ui/aura/window_occlusion_tracker_unittest.cc +++ b/chromium/ui/aura/window_occlusion_tracker_unittest.cc @@ -27,17 +27,6 @@ namespace { constexpr base::TimeDelta kTransitionDuration = base::TimeDelta::FromSeconds(3); -enum class WindowOcclusionChangedExpectation { - // Expect OnWindowOcclusionChanged() to be called with true as argument. - OCCLUDED, - - // Expect OnWindowOcclusionChanged() to be called with false as argument. - NOT_OCCLUDED, - - // Don't expect OnWindowOcclusionChanged() to be called. - NO_CALL, -}; - class MockWindowDelegate : public test::ColorTestWindowDelegate { public: MockWindowDelegate() : test::ColorTestWindowDelegate(SK_ColorWHITE) {} @@ -45,33 +34,24 @@ class MockWindowDelegate : public test::ColorTestWindowDelegate { void set_window(Window* window) { window_ = window; } - void set_expectation(WindowOcclusionChangedExpectation expectation) { + void set_expectation(Window::OcclusionState expectation) { expectation_ = expectation; } bool is_expecting_call() const { - return expectation_ != WindowOcclusionChangedExpectation::NO_CALL; + return expectation_ != Window::OcclusionState::UNKNOWN; } - void OnWindowOcclusionChanged(bool occluded) override { + void OnWindowOcclusionChanged( + Window::OcclusionState occlusion_state) override { ASSERT_TRUE(window_); - if (expectation_ == WindowOcclusionChangedExpectation::OCCLUDED) { - EXPECT_TRUE(occluded); - EXPECT_EQ(Window::OcclusionState::OCCLUDED, window_->occlusion_state()); - } else if (expectation_ == - WindowOcclusionChangedExpectation::NOT_OCCLUDED) { - EXPECT_FALSE(occluded); - EXPECT_EQ(Window::OcclusionState::NOT_OCCLUDED, - window_->occlusion_state()); - } else { - ADD_FAILURE() << "Unexpected call to OnWindowOcclusionChanged."; - } - expectation_ = WindowOcclusionChangedExpectation::NO_CALL; + EXPECT_NE(occlusion_state, Window::OcclusionState::UNKNOWN); + EXPECT_EQ(occlusion_state, expectation_); + expectation_ = Window::OcclusionState::UNKNOWN; } private: - WindowOcclusionChangedExpectation expectation_ = - WindowOcclusionChangedExpectation::NO_CALL; + Window::OcclusionState expectation_ = Window::OcclusionState::UNKNOWN; Window* window_ = nullptr; DISALLOW_COPY_AND_ASSIGN(MockWindowDelegate); @@ -113,34 +93,34 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase { } // namespace -// Verify that the non-overlapping windows are notified are not occluded. +// Verify that non-overlapping windows have a VISIBLE occlusion state. // _____ _____ // | | | | // |____| |____| TEST_F(WindowOcclusionTrackerTest, NonOverlappingWindows) { MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(15, 0, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); } -// Verify that partially overlapping windows are not occluded. +// Verify that partially overlapping windows have a VISIBLE occlusion state. // ______ // |__| | // |_____| TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) { MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); } @@ -154,31 +134,31 @@ TEST_F(WindowOcclusionTrackerTest, PartiallyOverlappingWindow) { TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b. Expect it to be non-occluded and expect window a to be // occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15)); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); // Hide window b. Expect window a to be non-occluded and window b to be // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + delegate_b->set_expectation(Window::OcclusionState::HIDDEN); window_b->Hide(); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); // Show window b. Expect window a to be occluded and window b to be non- // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); window_b->Show(); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -193,15 +173,15 @@ TEST_F(WindowOcclusionTrackerTest, HiddenWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b. Expect it to be non-occluded and expect window a to be // occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 15, 15)); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -209,13 +189,13 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { // Change the opacity of window b to 0.5f. Expect both windows to be non- // occluded. EXPECT_FALSE(delegate_a->is_expecting_call()); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); window_b->layer()->SetOpacity(0.5f); EXPECT_FALSE(delegate_a->is_expecting_call()); // Change the opacity of window b back to 1.0f. Expect window a to be // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); window_b->layer()->SetOpacity(1.0f); EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -225,24 +205,24 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create untracked window b. Expect window a to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 15, 15)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Change the opacity of window b to 0.5f. Expect both windows to be non- // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); window_b->layer()->SetOpacity(0.5f); EXPECT_FALSE(delegate_a->is_expecting_call()); // Change the opacity of window b back to 1.0f. Expect window a to be // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); window_b->layer()->SetOpacity(1.0f); EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -255,14 +235,14 @@ TEST_F(WindowOcclusionTrackerTest, SemiTransparentUntrackedWindowCoversWindow) { TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b with bounds that partially cover window a. Expect both // windows to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -270,63 +250,115 @@ TEST_F(WindowOcclusionTrackerTest, TwoWindowsOccludeOneWindow) { // already covered by window b. Expect window a to be occluded and window a/b // to be non-occluded. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(5, 0, 5, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); } -// Verify that when the bounds of a child window do not cover the bounds of a -// parent window, both windows are non-occluded. -TEST_F(WindowOcclusionTrackerTest, ChildDoesNotOccludeParent) { +// Verify that a window and its child that are covered by a sibling are +// occluded. +TEST_F(WindowOcclusionTrackerTest, SiblingOccludesWindowAndChild) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); EXPECT_FALSE(delegate_a->is_expecting_call()); - // Create window b with window a as parent. The bounds of window b do not - // fully cover window a. Expect both windows to be non-occluded. + // Create window b, with bounds that occlude half of its parent window a. + // Expect it to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5), window_a); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create window c, with bounds that occlude window a and window b. Expect it + // to be non-occluded, and window a and b to be occluded. + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 20, 20)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_b->is_expecting_call()); + EXPECT_FALSE(delegate_c->is_expecting_call()); } -// Verify that when the bounds of a child window cover the bounds of a parent -// window, the parent is occluded and the child is non-occluded. Also, verify -// that when the parent of a window changes, occlusion states are updated. -TEST_F(WindowOcclusionTrackerTest, ChildOccludesParent) { +// Verify that a window with one half covered by a child and the other half +// covered by a sibling is non-occluded. +TEST_F(WindowOcclusionTrackerTest, ChildAndSiblingOccludeOneWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Create window b, with bounds that occlude half of its parent window a. + // Expect it to be non-occluded. + MockWindowDelegate* delegate_b = new MockWindowDelegate(); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create window c, with bounds that occlude the other half of window a. + // Expect it to be non-occluded and expect window a to remain non-occluded. + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_c->is_expecting_call()); +} + +// Verify that a window covered by 2 non-occluded children is non-occluded. +TEST_F(WindowOcclusionTrackerTest, ChildrenOccludeOneWindow) { + // Create window a. Expect it to be non-occluded. + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Create window b, with bounds that cover half of its parent window a. Expect + // it to be non-occluded. + MockWindowDelegate* delegate_b = new MockWindowDelegate(); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 20), window_a); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create window c, with bounds that cover the other half of its parent window + // a. Expect it to be non-occluded. Expect window a to remain non-occluded. + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 20), window_a); + EXPECT_FALSE(delegate_c->is_expecting_call()); +} + +// Verify that when the bounds of a child window covers the bounds of a parent +// window but is itself visible, the parent window is visible. +TEST_F(WindowOcclusionTrackerTest, ChildDoesNotOccludeParent) { + // Create window a. Expect it to be non-occluded. + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b with window a as parent. The bounds of window b fully cover - // window a. Expect window a to be occluded but not window b. + // window a. Expect both windows to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a); - EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); // Create window c whose bounds don't overlap existing windows. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(15, 0, 10, 10)); EXPECT_FALSE(delegate_c->is_expecting_call()); - // Change the parent of window b from window a to window c. Expect window a to - // be non-occluded and window c to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + // Change the parent of window b from window a to window c. Expect all windows + // to remain non-occluded. window_c->AddChild(window_b); - EXPECT_FALSE(delegate_a->is_expecting_call()); - EXPECT_FALSE(delegate_c->is_expecting_call()); } // Verify that when the stacking order of windows change, occlusion states are @@ -335,28 +367,28 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) { // Create three windows that have the same bounds. Expect window on top of the // stack to be non-occluded and other windows to be occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); // Move window a on top of the stack. Expect it to be non-occluded and expect // window c to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); root_window()->StackChildAtTop(window_a); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); @@ -369,46 +401,47 @@ TEST_F(WindowOcclusionTrackerTest, StackingChanged) { TEST_F(WindowOcclusionTrackerTest, TransparentParentStackingChanged) { // Create window a which is transparent. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10), root_window(), true); EXPECT_FALSE(delegate_a->is_expecting_call()); - // Create window b which has the same bounds as its parent window a. Expect - // window b to be non-occluded and window a to be occluded. + // Create window b which has the same bounds as its parent window a. Expect it + // to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10), window_a); - EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); // Create window c which is transparent and has the same bounds as window a // and window b. Expect it to be non-occluded. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10), root_window(), true); - EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); // Create window d which has the same bounds as its parent window c. Expect - // window d to be non-occluded and all other windows to be occluded. + // window d to be non-occluded and window a and b to be occluded. MockWindowDelegate* delegate_d = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_d->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_d->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_d, gfx::Rect(0, 0, 10, 10), window_c); + EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); - EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call()); - // Move window a on top of the stack. Expect its child window b to be non- - // occluded and all other windows to be occluded. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - delegate_d->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + // Move window a on top of the stack. Expect window a and b to be non-occluded + // and window c and d to be occluded. + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_d->set_expectation(Window::OcclusionState::OCCLUDED); root_window()->StackChildAtTop(window_a); + EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); + EXPECT_FALSE(delegate_c->is_expecting_call()); EXPECT_FALSE(delegate_d->is_expecting_call()); } @@ -419,12 +452,12 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) { // Create window b. Expect it to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); // Stack window a on top of window b. Expect window b to be occluded. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); root_window()->StackChildAtTop(window_a); EXPECT_FALSE(delegate_b->is_expecting_call()); } @@ -433,17 +466,17 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowStackingChanged) { TEST_F(WindowOcclusionTrackerTest, BoundsChanged) { // Create two non-overlapping windows. Expect them to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); // Move window b on top of window a. Expect window a to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); window_b->SetBounds(window_a->bounds()); EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -464,26 +497,26 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) { // Create 3 windows. Window a is unoccluded. Window c occludes window b. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); window_b->layer()->SetAnimator(test_controller.animator()); MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); // Start animating the bounds of window b so that it moves on top of window a. // Window b should be non-occluded when the animation starts. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); window_b->SetBounds(window_a->bounds()); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -492,7 +525,7 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowBoundsAnimated) { test_controller.Step(kTransitionDuration / 3); // Window b should occlude window a at the end of the animation. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -511,18 +544,18 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { // Create 3 windows. Window a is unoccluded. Window c occludes window b. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); @@ -530,7 +563,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { // Start animating the bounds of window c so that it moves on top of window a. // Window b should be non-occluded when the animation starts. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); window_c->SetBounds(window_a->bounds()); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -539,7 +572,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { test_controller.Step(kTransitionDuration / 3); // Window c should occlude window a at the end of the animation. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -551,14 +584,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowBoundsAnimated) { TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which doesn't overlap window a and is transparent. Expect // it to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), root_window(), true); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -566,13 +599,13 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { // Create window c which has window b as parent and doesn't occlude any // window. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); EXPECT_FALSE(delegate_c->is_expecting_call()); // Move window b so that window c occludes window a. Expect window a to be // occluded and other windows to be non-occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); window_b->SetBounds(gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -582,7 +615,7 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentBoundsChanged) { TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -590,7 +623,7 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) { Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 10, 5, 5)); // Move window b on top of window a. Expect window a to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); window_b->SetBounds(window_a->bounds()); EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -600,18 +633,18 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowBoundsChanged) { TEST_F(WindowOcclusionTrackerTest, TransformChanged) { // Create two non-overlapping windows. Expect them to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); // Scale and translate window b so that it covers window a. Expect window a to // be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); gfx::Transform transform; transform.Translate(0.0f, -10.0f); transform.Scale(2.0f, 2.0f); @@ -635,26 +668,26 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) { // Create 3 windows. Window a is unoccluded. Window c occludes window b. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); window_b->layer()->SetAnimator(test_controller.animator()); MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); // Start animating the transform of window b so that it moves on top of window // a. Window b should be non-occluded when the animation starts. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); auto transform = std::make_unique<ui::InterpolatedScale>( gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1)); transform->SetChild(std::make_unique<ui::InterpolatedTranslation>( @@ -669,7 +702,7 @@ TEST_F(WindowOcclusionTrackerTest, OccludedWindowTransformAnimated) { test_controller.Step(kTransitionDuration / 3); // Window b should occlude window a at the end of the animation. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -688,18 +721,18 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { // Create 3 windows. Window a is unoccluded. Window c occludes window b. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 20, 20)); EXPECT_FALSE(delegate_a->is_expecting_call()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 20, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10)); EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); @@ -707,7 +740,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { // Start animating the bounds of window c so that it moves on top of window a. // Window b should be non-occluded when the animation starts. - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); auto transform = std::make_unique<ui::InterpolatedScale>( gfx::Point3F(1, 1, 1), gfx::Point3F(2.0f, 2.0f, 1)); transform->SetChild(std::make_unique<ui::InterpolatedTranslation>( @@ -722,7 +755,7 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { test_controller.Step(kTransitionDuration / 3); // Window c should occlude window a at the end of the animation. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); test_controller.Step(kTransitionDuration / 3); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -734,14 +767,14 @@ TEST_F(WindowOcclusionTrackerTest, NonOccludedWindowTransformAnimated) { TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which doesn't overlap window a and is transparent. Expect // it to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), root_window(), true); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -749,13 +782,13 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { // Create window c which has window b as parent and doesn't occlude any // window. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); EXPECT_FALSE(delegate_c->is_expecting_call()); // Scale and translate window b so that window c occludes window a. Expect // window a to be occluded and other windows to be non-occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); gfx::Transform transform; transform.Translate(0.0f, -10.0f); transform.Scale(2.0f, 2.0f); @@ -768,7 +801,7 @@ TEST_F(WindowOcclusionTrackerTest, TransparentParentTransformChanged) { TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -777,7 +810,7 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) { // Scale and translate window b so that it occludes window a. Expect window a // to be occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); gfx::Transform transform; transform.Translate(0.0f, -10.0f); transform.Scale(2.0f, 2.0f); @@ -790,17 +823,17 @@ TEST_F(WindowOcclusionTrackerTest, UntrackedWindowTransformChanged) { TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which occludes window a. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Delete window b. Expect a to be non-occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); delete window_b; EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -810,17 +843,17 @@ TEST_F(WindowOcclusionTrackerTest, DeleteUntrackedWindow) { TEST_F(WindowOcclusionTrackerTest, RemoveUntrackedWindow) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which occludes window a. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Delete window b. Expect a to be non-occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); root_window()->RemoveChild(window_b); EXPECT_FALSE(delegate_a->is_expecting_call()); delete window_b; @@ -834,7 +867,7 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) { // Create window b. Expect it to be non-occluded. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_c->is_expecting_call()); @@ -846,19 +879,19 @@ TEST_F(WindowOcclusionTrackerTest, RemoveAndAddTrackedToRoot) { // Create untracked window d which covers window a. Expect window a to be // occluded. - delegate_c->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); Window* window_d = CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_c->is_expecting_call()); // Move window d so that it doesn't cover window c. - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); window_d->SetBounds(gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_c->is_expecting_call()); // Stack window a on top of window c. Expect window c to be non-occluded. This // won't work if WindowOcclusionTracked didn't register as an observer of // window a when window c was made a child of root_window(). - delegate_c->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::OCCLUDED); root_window()->StackChildAtTop(window_a); EXPECT_FALSE(delegate_c->is_expecting_call()); } @@ -874,7 +907,7 @@ class ResizeWindowObserver : public WindowObserver { const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) override { - window_to_resize_->SetBounds(window->bounds()); + window_to_resize_->SetBounds(old_bounds); } private: @@ -891,29 +924,35 @@ class ResizeWindowObserver : public WindowObserver { TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); - // Create window b, which is a child of window a. Expect it to be non- - // occluded. + // Create window b. Expect it to be non-occluded and to occlude window a. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); - Window* window_b = - CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5), window_a); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); - // Create an observer that will resize window b when window a is resized. - ResizeWindowObserver resize_window_observer(window_b); - window_a->AddObserver(&resize_window_observer); - - // Resize window a. Expect window b to be resized so that window a is + // Create window c, which is a child of window b. Expect it to be non- // occluded. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - window_a->SetBounds(gfx::Rect(0, 0, 20, 20)); - EXPECT_FALSE(delegate_a->is_expecting_call()); + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_c = + CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 5, 5), window_b); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create an observer that will resize window c when window b is resized. + ResizeWindowObserver resize_window_observer(window_c); + window_b->AddObserver(&resize_window_observer); + + // Resize window b. Expect window c to be resized so that window a stays + // occluded. Window a should not temporarily be non-occluded. + window_b->SetBounds(gfx::Rect(0, 0, 5, 5)); - window_a->RemoveObserver(&resize_window_observer); + window_b->RemoveObserver(&resize_window_observer); } // Verify that the bounds of windows are changed multiple times within the scope @@ -922,14 +961,14 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) { TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which doesn't overlap window a. Expect it to be non- // occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -942,7 +981,7 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { window_a->SetBounds(gfx::Rect(0, 10, 5, 5)); window_b->SetBounds(window_a->bounds()); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); } EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -951,14 +990,14 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) { TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) { // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b which doesn't overlap window a. Expect it to be non- // occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); @@ -984,7 +1023,7 @@ TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) { window_b->SetBounds(window_a->bounds()); } - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); } EXPECT_FALSE(delegate_a->is_expecting_call()); } @@ -1006,15 +1045,15 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) { CreateUntrackedWindow(gfx::Rect(15, 16, 4, 5), window_b); MockWindowDelegate* delegate_d = new MockWindowDelegate(); - delegate_d->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_d->set_expectation(Window::OcclusionState::VISIBLE); Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(34, 36, 8, 10)); EXPECT_FALSE(delegate_d->is_expecting_call()); - delegate_d->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_d->set_expectation(Window::OcclusionState::OCCLUDED); root_window()->StackChildAtBottom(window_d); EXPECT_FALSE(delegate_d->is_expecting_call()); - delegate_d->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_d->set_expectation(Window::OcclusionState::VISIBLE); window_d->SetBounds(gfx::Rect(35, 36, 8, 10)); EXPECT_FALSE(delegate_d->is_expecting_call()); @@ -1026,26 +1065,24 @@ TEST_F(WindowOcclusionTrackerTest, HierarchyOfTransforms) { // Verify that clipping is taken into account when computing occlusion. TEST_F(WindowOcclusionTrackerTest, Clipping) { - // Create window b. Expect it to be non-occluded. + // Create window a. Expect it to be non-occluded. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); // Create window b. Expect it to be non-occluded. MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 5, 5)); EXPECT_FALSE(delegate_b->is_expecting_call()); window_b->layer()->SetMasksToBounds(true); - // Create window c which has window b as parent. Expect it to occlude window - // b, but not window a since it's clipped. + // Create window c which has window b as parent. Don't expect it to occlude + // window a since its bounds are clipped by window b. MockWindowDelegate* delegate_c = new MockWindowDelegate(); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_c->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_c, gfx::Rect(0, 0, 10, 10), window_b); - EXPECT_FALSE(delegate_b->is_expecting_call()); EXPECT_FALSE(delegate_c->is_expecting_call()); } @@ -1064,7 +1101,7 @@ TEST_F(WindowOcclusionTrackerTest, DestroyWindowWithPendingAnimation) { layer_animation_settings.SetTransitionDuration(kTransitionDuration); MockWindowDelegate* delegate = new MockWindowDelegate(); - delegate->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate->set_expectation(Window::OcclusionState::VISIBLE); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate->is_expecting_call()); window->layer()->SetAnimator(test_controller.animator()); @@ -1092,28 +1129,28 @@ TEST_F(WindowOcclusionTrackerTest, RecreateLayerOfAnimatedWindow) { // Create 2 windows. Window b occludes window a. MockWindowDelegate* delegate_a = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(2, 2, 1, 1)); EXPECT_FALSE(delegate_a->is_expecting_call()); window_a->layer()->SetAnimator(test_controller.animator()); MockWindowDelegate* delegate_b = new MockWindowDelegate(); - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); - delegate_b->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate_a->is_expecting_call()); EXPECT_FALSE(delegate_b->is_expecting_call()); // Start animating the bounds of window a. Window a should be non-occluded // when the animation starts. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); window_a->SetBounds(gfx::Rect(6, 6, 1, 1)); test_controller.Step(kTransitionDuration / 2); EXPECT_FALSE(delegate_a->is_expecting_call()); // Recreate the layer of window b. Expect this to behave the same as if the // animation was abandoned. - delegate_a->set_expectation(WindowOcclusionChangedExpectation::OCCLUDED); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); std::unique_ptr<ui::Layer> old_layer = window_a->RecreateLayer(); EXPECT_FALSE(delegate_a->is_expecting_call()); @@ -1143,7 +1180,7 @@ class ObserverChangingWindowBounds : public WindowObserver { TEST_F(WindowOcclusionTrackerTest, ChangeTrackedWindowBeforeObserveAddToRoot) { // Create a window. Expect it to be non-occluded. MockWindowDelegate* delegate = new MockWindowDelegate(); - delegate->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate->set_expectation(Window::OcclusionState::VISIBLE); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate->is_expecting_call()); @@ -1205,7 +1242,7 @@ TEST_F(WindowOcclusionTrackerTest, // Create a window. Expect it to be non-occluded. MockWindowDelegate* delegate = new MockWindowDelegate(); - delegate->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate->set_expectation(Window::OcclusionState::VISIBLE); Window* window = CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate->is_expecting_call()); window->layer()->SetAnimator(test_controller.animator()); @@ -1237,7 +1274,7 @@ TEST_F(WindowOcclusionTrackerTest, // Create a tracked window. Expect it to be non-occluded. MockWindowDelegate* delegate = new MockWindowDelegate(); - delegate->set_expectation(WindowOcclusionChangedExpectation::NOT_OCCLUDED); + delegate->set_expectation(Window::OcclusionState::VISIBLE); CreateTrackedWindow(delegate, gfx::Rect(0, 0, 10, 10)); EXPECT_FALSE(delegate->is_expecting_call()); @@ -1264,4 +1301,224 @@ TEST_F(WindowOcclusionTrackerTest, window->layer()->GetAnimator()->StopAnimating(); } +namespace { + +class WindowDelegateHidingWindowIfOccluded : public MockWindowDelegate { + public: + WindowDelegateHidingWindowIfOccluded(Window* other_window, + MockWindowDelegate* other_delegate) + : other_window_(other_window), other_delegate_(other_delegate) {} + + // MockWindowDelegate: + void OnWindowOcclusionChanged( + Window::OcclusionState occlusion_state) override { + MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); + if (occlusion_state == Window::OcclusionState::HIDDEN) { + other_window_->Hide(); + other_delegate_->set_expectation(Window::OcclusionState::HIDDEN); + } + } + + private: + Window* other_window_; + MockWindowDelegate* other_delegate_; + + DISALLOW_COPY_AND_ASSIGN(WindowDelegateHidingWindowIfOccluded); +}; + +} // namespace + +// Verify that a window delegate can change the visibility of another window +// when it is notified that its occlusion changed. +TEST_F(WindowOcclusionTrackerTest, HideFromOnWindowOcclusionChanged) { + // Create a tracked window. Expect it to be visible. + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Create a tracked window. Expect it to be visible. + MockWindowDelegate* delegate_b = + new WindowDelegateHidingWindowIfOccluded(window_a, delegate_a); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(5, 5, 10, 10)); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Hide the tracked window. It should be able to hide |window_a|. + delegate_b->set_expectation(Window::OcclusionState::HIDDEN); + window_b->Hide(); + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_b->is_expecting_call()); + EXPECT_FALSE(window_a->IsVisible()); + EXPECT_FALSE(window_b->IsVisible()); +} + +namespace { + +class WindowDelegateDeletingWindow : public MockWindowDelegate { + public: + WindowDelegateDeletingWindow() = default; + + void set_other_window(Window* other_window) { other_window_ = other_window; } + + // MockWindowDelegate: + void OnWindowOcclusionChanged( + Window::OcclusionState occlusion_state) override { + MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); + if (occlusion_state == Window::OcclusionState::OCCLUDED) { + delete other_window_; + other_window_ = nullptr; + } + } + + private: + Window* other_window_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(WindowDelegateDeletingWindow); +}; + +} // namespace + +// Verify that a window can delete a window that is on top of it when it is +// notified that its occlusion changed (a crash would occur if +// WindowOcclusionTracker accessed that window after it was deleted). +TEST_F(WindowOcclusionTrackerTest, DeleteFromOnWindowOcclusionChanged) { + // Create a tracked window. Expect it to be visible. + WindowDelegateDeletingWindow* delegate_a = new WindowDelegateDeletingWindow(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Create a tracked window. Expect it to be visible. + MockWindowDelegate* delegate_b = new MockWindowDelegate(); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(10, 0, 10, 10)); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create a tracked window. Expect it to be visible. + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(20, 0, 10, 10)); + EXPECT_FALSE(delegate_c->is_expecting_call()); + + // |window_c| will be deleted when |window_a| is occluded. + delegate_a->set_other_window(window_c); + + // Move |window_b| on top of |window_a|. + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + window_b->SetBounds(window_a->bounds()); + EXPECT_FALSE(delegate_a->is_expecting_call()); +} + +namespace { + +class WindowDelegateChangingWindowVisibility : public MockWindowDelegate { + public: + WindowDelegateChangingWindowVisibility() = default; + + void set_window_to_update(Window* window) { window_to_update_ = window; } + + // MockWindowDelegate: + void OnWindowOcclusionChanged( + Window::OcclusionState occlusion_state) override { + MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state); + if (!window_to_update_) + return; + + if (window_to_update_->IsVisible()) { + window_to_update_->Hide(); + EXPECT_FALSE(did_set_expectation_from_occlusion_changed_); + set_expectation(Window::OcclusionState::HIDDEN); + did_set_expectation_from_occlusion_changed_ = true; + } else { + window_to_update_->Show(); + if (!did_set_expectation_from_occlusion_changed_) + set_expectation(Window::OcclusionState::VISIBLE); + } + } + + private: + Window* window_to_update_ = nullptr; + bool did_set_expectation_from_occlusion_changed_ = false; + + DISALLOW_COPY_AND_ASSIGN(WindowDelegateChangingWindowVisibility); +}; +} // namespace + +// Verify that if a window changes its visibility every time it is notified that +// its occlusion state changed, the occlusion state of all IsVisible() windows +// is set to NOT_OCCLUDED and no infinite loop is entered. +TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) { + // Create 2 superposed tracked windows. + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + MockWindowDelegate* delegate_b = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_b, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + // Create a hidden tracked window. + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_c = CreateTrackedWindow(delegate_c, gfx::Rect(10, 0, 10, 10)); + EXPECT_FALSE(delegate_c->is_expecting_call()); + delegate_c->set_expectation(Window::OcclusionState::HIDDEN); + window_c->Hide(); + EXPECT_FALSE(delegate_c->is_expecting_call()); + + // Create a tracked window. Expect it to be non-occluded. + auto* delegate_d = new WindowDelegateChangingWindowVisibility(); + delegate_d->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(20, 0, 10, 10)); + EXPECT_FALSE(delegate_d->is_expecting_call()); + + // Store a pointer to |window_d| in |delegate_d|. This will cause a call to + // Show()/Hide() every time |delegate_d| is notified of an occlusion change. + delegate_d->set_window_to_update(window_d); + + // Hide |window_d|. This will cause occlusion to be recomputed multiple times. + // Once the maximum number of times that occlusion can be recomputed is + // reached, the occlusion state of all IsVisible() windows should be set to + // NOT_OCCLUDED. + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + delegate_d->set_expectation(Window::OcclusionState::HIDDEN); + window_d->Hide(); + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_d->is_expecting_call()); +} + +// Verify that the occlusion states are correctly update when a branch of the +// tree is hidden. +TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) { + // Create a branch of 3 tracked windows. Expect them to be visible. + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + MockWindowDelegate* delegate_b = new MockWindowDelegate(); + delegate_b->set_expectation(Window::OcclusionState::VISIBLE); + Window* window_b = + CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10), window_a); + EXPECT_FALSE(delegate_b->is_expecting_call()); + + MockWindowDelegate* delegate_c = new MockWindowDelegate(); + delegate_c->set_expectation(Window::OcclusionState::VISIBLE); + CreateTrackedWindow(delegate_c, gfx::Rect(0, 20, 10, 10), window_b); + EXPECT_FALSE(delegate_c->is_expecting_call()); + + // Hide |window_b| (and hence |window_c|). Expect |window_b| and |window_c| to + // be hidden. + delegate_b->set_expectation(Window::OcclusionState::HIDDEN); + delegate_c->set_expectation(Window::OcclusionState::HIDDEN); + window_b->Hide(); + EXPECT_FALSE(delegate_b->is_expecting_call()); + EXPECT_FALSE(delegate_c->is_expecting_call()); +} + } // namespace aura diff --git a/chromium/ui/aura/window_port.h b/chromium/ui/aura/window_port.h index 46e4c1bb811..a57c5134920 100644 --- a/chromium/ui/aura/window_port.h +++ b/chromium/ui/aura/window_port.h @@ -85,9 +85,6 @@ class AURA_EXPORT WindowPort { virtual std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() = 0; - // Get the current viz::SurfaceId. - virtual viz::SurfaceId GetSurfaceId() const = 0; - // Forces the window to allocate a new viz::LocalSurfaceId for the next // CompositorFrame submission in anticipation of a synchronization operation // that does not involve a resize or a device scale factor change. @@ -98,12 +95,6 @@ class AURA_EXPORT WindowPort { // factor. virtual const viz::LocalSurfaceId& GetLocalSurfaceId() = 0; - // This can return invalid FrameSinkId. - virtual viz::FrameSinkId GetFrameSinkId() const = 0; - - virtual void OnWindowAddedToRootWindow() = 0; - virtual void OnWillRemoveWindowFromRootWindow() = 0; - virtual void OnEventTargetingPolicyChanged() = 0; // See description of function with same name in transient_window_client. diff --git a/chromium/ui/aura/window_port_for_shutdown.cc b/chromium/ui/aura/window_port_for_shutdown.cc index c29e4faad4e..a11a2eed846 100644 --- a/chromium/ui/aura/window_port_for_shutdown.cc +++ b/chromium/ui/aura/window_port_for_shutdown.cc @@ -57,24 +57,12 @@ WindowPortForShutdown::CreateLayerTreeFrameSink() { return nullptr; } -viz::SurfaceId WindowPortForShutdown::GetSurfaceId() const { - return viz::SurfaceId(); -} - void WindowPortForShutdown::AllocateLocalSurfaceId() {} const viz::LocalSurfaceId& WindowPortForShutdown::GetLocalSurfaceId() { return local_surface_id_; } -viz::FrameSinkId WindowPortForShutdown::GetFrameSinkId() const { - return frame_sink_id_; -} - -void WindowPortForShutdown::OnWindowAddedToRootWindow() {} - -void WindowPortForShutdown::OnWillRemoveWindowFromRootWindow() {} - void WindowPortForShutdown::OnEventTargetingPolicyChanged() {} bool WindowPortForShutdown::ShouldRestackTransientChildren() { diff --git a/chromium/ui/aura/window_port_for_shutdown.h b/chromium/ui/aura/window_port_for_shutdown.h index f9b0be555e5..e3d97a5b64d 100644 --- a/chromium/ui/aura/window_port_for_shutdown.h +++ b/chromium/ui/aura/window_port_for_shutdown.h @@ -39,18 +39,13 @@ class WindowPortForShutdown : public WindowPort { int64_t old_value, std::unique_ptr<ui::PropertyData> data) override; std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override; - viz::SurfaceId GetSurfaceId() const override; void AllocateLocalSurfaceId() override; const viz::LocalSurfaceId& GetLocalSurfaceId() override; - viz::FrameSinkId GetFrameSinkId() const override; - void OnWindowAddedToRootWindow() override; - void OnWillRemoveWindowFromRootWindow() override; void OnEventTargetingPolicyChanged() override; bool ShouldRestackTransientChildren() override; private: viz::LocalSurfaceId local_surface_id_; - viz::FrameSinkId frame_sink_id_; DISALLOW_COPY_AND_ASSIGN(WindowPortForShutdown); }; diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc index d81560ae534..a87f7647241 100644 --- a/chromium/ui/aura/window_targeter_unittest.cc +++ b/chromium/ui/aura/window_targeter_unittest.cc @@ -303,6 +303,6 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowTargeterTest, ::testing::Values(test::BackendType::CLASSIC, test::BackendType::MUS, - test::BackendType::MUS_HOSTING_VIZ)); + test::BackendType::MASH)); } // namespace aura diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc index de85e1d8f2d..cbade2495bb 100644 --- a/chromium/ui/aura/window_tree_host.cc +++ b/chromium/ui/aura/window_tree_host.cc @@ -12,6 +12,7 @@ #include "ui/aura/client/capture_client.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" +#include "ui/aura/scoped_keyboard_hook.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_port.h" @@ -242,6 +243,13 @@ void WindowTreeHost::Hide() { compositor()->SetVisible(false); } +std::unique_ptr<ScopedKeyboardHook> WindowTreeHost::CaptureSystemKeyEvents( + base::Optional<base::flat_set<int>> keys) { + if (CaptureSystemKeyEventsImpl(std::move(keys))) + return std::make_unique<ScopedKeyboardHook>(weak_factory_.GetWeakPtr()); + return nullptr; +} + //////////////////////////////////////////////////////////////////////////////// // WindowTreeHost, protected: @@ -252,7 +260,8 @@ WindowTreeHost::WindowTreeHost(std::unique_ptr<WindowPort> window_port) : window_(new Window(nullptr, std::move(window_port))), last_cursor_(ui::CursorType::kNull), input_method_(nullptr), - owned_input_method_(false) { + owned_input_method_(false), + weak_factory_(this) { display::Screen::GetScreen()->AddObserver(this); } diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h index b83f6494fb1..4a3e90b7b55 100644 --- a/chromium/ui/aura/window_tree_host.h +++ b/chromium/ui/aura/window_tree_host.h @@ -8,11 +8,13 @@ #include <stdint.h> #include <memory> -#include <vector> +#include "base/containers/flat_set.h" #include "base/event_types.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/optional.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "ui/aura/aura_export.h" #include "ui/base/cursor/cursor.h" @@ -39,6 +41,8 @@ class ViewProp; } namespace aura { +class ScopedKeyboardHook; + namespace test { class WindowTreeHostTestApi; } @@ -197,7 +201,15 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // Releases OS capture of the root window. virtual void ReleaseCapture() = 0; + // Requests that |keys| be intercepted at the platform level and routed + // directly to the web content. If |keys| is empty, all keys will be + // intercepted. Returns a ScopedKeyboardHook instance which stops capturing + // system key events when destroyed. + std::unique_ptr<ScopedKeyboardHook> CaptureSystemKeyEvents( + base::Optional<base::flat_set<int>> keys); + protected: + friend class ScopedKeyboardHook; friend class TestScreen; // TODO(beng): see if we can remove/consolidate. WindowTreeHost(); @@ -252,6 +264,13 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, void OnDisplayMetricsChanged(const display::Display& display, uint32_t metrics) override; + // Begins capturing system key events. Returns true if successful. + virtual bool CaptureSystemKeyEventsImpl( + base::Optional<base::flat_set<int>> keys) = 0; + + // Stops capturing system keyboard events. + virtual void ReleaseSystemKeyEventCapture() = 0; + protected: const base::ObserverList<WindowTreeHostObserver>& observers() const { return observers_; @@ -308,6 +327,8 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate, // Set to true if this WindowTreeHost is currently holding pointer moves. bool holding_pointer_moves_ = false; + base::WeakPtrFactory<WindowTreeHost> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(WindowTreeHost); }; diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc index 9f25b25e22e..43294f6f232 100644 --- a/chromium/ui/aura/window_tree_host_platform.cc +++ b/chromium/ui/aura/window_tree_host_platform.cc @@ -6,6 +6,7 @@ #include <utility> +#include "base/macros.h" #include "base/run_loop.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" @@ -113,6 +114,14 @@ void WindowTreeHostPlatform::ReleaseCapture() { platform_window_->ReleaseCapture(); } +bool WindowTreeHostPlatform::CaptureSystemKeyEventsImpl( + base::Optional<base::flat_set<int>> native_key_codes) { + NOTIMPLEMENTED(); + return false; +} + +void WindowTreeHostPlatform::ReleaseSystemKeyEventCapture() {} + void WindowTreeHostPlatform::SetCursorNative(gfx::NativeCursor cursor) { if (cursor == current_cursor_) return; diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h index 13ef6ca1e57..5935d1634b6 100644 --- a/chromium/ui/aura/window_tree_host_platform.h +++ b/chromium/ui/aura/window_tree_host_platform.h @@ -63,6 +63,9 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost, float device_pixel_ratio) override; void OnAcceleratedWidgetDestroyed() override; void OnActivationChanged(bool active) override; + bool CaptureSystemKeyEventsImpl( + base::Optional<base::flat_set<int>> native_key_codes) override; + void ReleaseSystemKeyEventCapture() override; private: gfx::AcceleratedWidget widget_; diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc index c9aec7a3001..375e2ddc552 100644 --- a/chromium/ui/aura/window_unittest.cc +++ b/chromium/ui/aura/window_unittest.cc @@ -32,6 +32,7 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_observer.h" +#include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h" #include "ui/base/class_property.h" #include "ui/base/hit_test.h" @@ -113,6 +114,7 @@ DEFINE_UI_CLASS_PROPERTY_TYPE(DeletionTestProperty*); namespace aura { namespace test { +namespace { class WindowTest : public AuraTestBaseWithType { public: @@ -140,8 +142,6 @@ class WindowTest : public AuraTestBaseWithType { DISALLOW_COPY_AND_ASSIGN(WindowTest); }; -namespace { - // Used for verifying destruction methods are invoked. class DestroyTrackingDelegateImpl : public TestWindowDelegate { public: @@ -316,8 +316,6 @@ void OffsetBounds(Window* window, int horizontal, int vertical) { window->SetBounds(bounds); } -} // namespace - TEST_P(WindowTest, GetChildById) { std::unique_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); std::unique_ptr<Window> w11(CreateTestWindowWithId(11, w1.get())); @@ -424,18 +422,19 @@ TEST_P(WindowTest, ContainsMouse) { // Tests that the root window gets a valid LocalSurfaceId. TEST_P(WindowTest, RootWindowHasValidLocalSurfaceId) { // When mus is hosting viz, the LocalSurfaceId is sent from mus. - if (GetParam() == BackendType::MUS_HOSTING_VIZ) + if (GetParam() == BackendType::MASH) return; EXPECT_TRUE(root_window()->GetLocalSurfaceId().is_valid()); } TEST_P(WindowTest, WindowEmbeddingClientHasValidLocalSurfaceId) { // When mus is hosting viz, the LocalSurfaceId is sent from mus. - if (GetParam() == BackendType::MUS_HOSTING_VIZ) + if (GetParam() == BackendType::MASH) return; std::unique_ptr<Window> window(CreateTestWindow( SK_ColorWHITE, 1, gfx::Rect(10, 10, 300, 200), root_window())); - window->set_embed_frame_sink_id(viz::FrameSinkId(0, 1)); + test::WindowTestApi(window.get()).DisableFrameSinkRegistration(); + window->SetEmbedFrameSinkId(viz::FrameSinkId(0, 1)); EXPECT_TRUE(window->GetLocalSurfaceId().is_valid()); } @@ -1673,8 +1672,6 @@ TEST_P(WindowTest, Property) { EXPECT_EQ(nullptr, w->GetNativeWindowProperty(native_prop_key)); } -namespace { - class DeletionTestLayoutManager : public LayoutManager { public: explicit DeletionTestLayoutManager(DeletionTracker* tracker) @@ -1696,8 +1693,6 @@ class DeletionTestLayoutManager : public LayoutManager { DISALLOW_COPY_AND_ASSIGN(DeletionTestLayoutManager); }; -} // namespace - TEST_P(WindowTest, DeleteLayoutManagerBeforeOwnedProps) { DeletionTracker tracker; { @@ -2696,8 +2691,6 @@ TEST_P(WindowTest, OwnedByParentFalse) { EXPECT_EQ(NULL, w2->parent()); } -namespace { - // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from // OnWindowDestroyed(). class OwningWindowDelegate : public TestWindowDelegate { @@ -2716,8 +2709,6 @@ class OwningWindowDelegate : public TestWindowDelegate { DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate); }; -} // namespace - // Creates a window with two child windows. When the first child window is // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child. // This synthesizes BrowserView and the status bubble. Both are children of the @@ -2737,7 +2728,52 @@ TEST_P(WindowTest, DeleteWindowFromOnWindowDestroyed) { parent.reset(); } -namespace { +// WindowObserver implementation that deletes a window in +// OnWindowVisibilityChanged(). +class DeleteOnVisibilityChangedObserver : public WindowObserver { + public: + // |to_observe| is the Window this is added as an observer to. When + // OnWindowVisibilityChanged() is called |to_delete| is deleted. + explicit DeleteOnVisibilityChangedObserver(Window* to_observe, + Window* to_delete) + : to_observe_(to_observe), to_delete_(to_delete) { + to_observe_->AddObserver(this); + } + ~DeleteOnVisibilityChangedObserver() override { + // OnWindowVisibilityChanged() should have been called. + DCHECK(!to_delete_); + } + + // WindowObserver: + void OnWindowVisibilityChanged(Window* window, bool visible) override { + to_observe_->RemoveObserver(this); + delete to_delete_; + to_delete_ = nullptr; + } + + private: + Window* to_observe_; + Window* to_delete_; + + DISALLOW_COPY_AND_ASSIGN(DeleteOnVisibilityChangedObserver); +}; + +TEST_P(WindowTest, DeleteParentWindowFromOnWindowVisibiltyChanged) { + WindowTracker tracker; + Window* root = CreateTestWindowWithId(0, nullptr); + tracker.Add(root); + Window* child1 = CreateTestWindowWithId(0, root); + tracker.Add(child1); + tracker.Add(CreateTestWindowWithId(0, root)); + + // This deletes |root| (the parent) when OnWindowVisibilityChanged() is + // received by |child1|. + DeleteOnVisibilityChangedObserver deletion_observer(child1, root); + // The Hide() calls trigger deleting |root|, which should delete the whole + // tree. + root->Hide(); + EXPECT_TRUE(tracker.windows().empty()); +} // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is // invoked. @@ -2763,8 +2799,6 @@ class BoundsChangeDelegate : public TestWindowDelegate { DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate); }; -} // namespace - // Verifies the delegate is notified when the actual bounds of the layer // change. TEST_P(WindowTest, DelegateNotifiedAsBoundsChange) { @@ -2843,8 +2877,6 @@ TEST_P(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) { EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString()); } -namespace { - // Used by AddChildNotifications to track notification counts. class AddChildNotificationsObserver : public WindowObserver { public: @@ -2871,8 +2903,6 @@ class AddChildNotificationsObserver : public WindowObserver { DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver); }; -} // namespace - // Assertions around when root window notifications are sent. TEST_P(WindowTest, AddChildNotifications) { AddChildNotificationsObserver observer; @@ -3094,8 +3124,6 @@ TEST_P(WindowTest, OnWindowHierarchyChange) { } } -namespace { - class TestLayerAnimationObserver : public ui::LayerAnimationObserver { public: TestLayerAnimationObserver() @@ -3130,8 +3158,6 @@ class TestLayerAnimationObserver : public ui::LayerAnimationObserver { DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver); }; -} // namespace - TEST_P(WindowTest, WindowDestroyCompletesAnimations) { ui::ScopedAnimationDurationScaleMode test_duration_mode( ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); @@ -3240,13 +3266,14 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowTest, ::testing::Values(BackendType::CLASSIC, BackendType::MUS, - BackendType::MUS_HOSTING_VIZ)); + BackendType::MASH)); INSTANTIATE_TEST_CASE_P(/* no prefix */, WindowObserverTest, ::testing::Values(BackendType::CLASSIC, BackendType::MUS, - BackendType::MUS_HOSTING_VIZ)); + BackendType::MASH)); +} // namespace } // namespace test } // namespace aura |