Commit e70dc7a2 authored by Malay Keshav's avatar Malay Keshav Committed by Commit Bot

Use mirror window occlusion state to update webcontent visibility

This patch makes WebContentsViewAura manage its web content's visibility
state based on its current mirror window's occlusion state. To achieve
this, the patch makes the following changes:
 - Adds a new callback in WindowObserver to receive occlusion state
   changes.
 - Creates a subclass of aura::WindowObserver to manage mirror window
   occlusion states for the WebContentsViewAura.
 - Replaces a DCHECK with an early return when an already tracked window
   is requested to be tracked again.
 - Replaces the boolean window property of mirror window with a vector
   list of mirror windows.
 - Updates the unittest and adds a new method to WindowTestApi.

Bug: 901555
Change-Id: I70566c544def6129c7410af84f91e6501a5479d5
Component: Window Mirror View, web contents, Window occlusion tracker
Reviewed-on: https://chromium-review.googlesource.com/c/1313753Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612457}
parent 64394d90
......@@ -4,6 +4,9 @@
#include "ash/wm/window_mirror_view.h"
#include <algorithm>
#include <memory>
#include "ash/wm/widget_finder.h"
#include "ash/wm/window_state.h"
#include "ui/aura/client/aura_constants.h"
......@@ -28,6 +31,23 @@ void EnsureAllChildrenAreVisible(ui::Layer* layer) {
}
}
// Removes 1 instance of an element from a multiset.
void EraseFromList(std::vector<aura::Window*>* targets, aura::Window* target) {
auto it = std::find(targets->begin(), targets->end(), target);
if (it != targets->end())
targets->erase(it);
}
void RemoveTargetWindowFromSource(aura::Window* target, aura::Window* source) {
if (!target || !source)
return;
std::vector<aura::Window*>* target_window_list =
source->GetProperty(aura::client::kMirrorWindowList);
if (!target_window_list)
return;
EraseFromList(target_window_list, target);
}
} // namespace
WindowMirrorView::WindowMirrorView(aura::Window* source,
......@@ -40,8 +60,7 @@ WindowMirrorView::WindowMirrorView(aura::Window* source,
WindowMirrorView::~WindowMirrorView() {
// Make sure |source_| has outlived |this|. See crbug.com/681207
DCHECK(source_->layer());
if (layer_owner_)
source_->ClearProperty(aura::client::kMirroringEnabledKey);
RemoveTargetWindowFromSource(target_, source_);
}
void WindowMirrorView::RecreateMirrorLayers() {
......@@ -85,10 +104,51 @@ void WindowMirrorView::OnVisibleBoundsChanged() {
InitLayerOwner();
}
void WindowMirrorView::InitLayerOwner() {
if (!layer_owner_)
source_->SetProperty(aura::client::kMirroringEnabledKey, true);
void WindowMirrorView::NativeViewHierarchyChanged() {
View::NativeViewHierarchyChanged();
DCHECK(GetWidget());
UpdateSourceWindowProperty();
}
void WindowMirrorView::AddedToWidget() {
UpdateSourceWindowProperty();
}
void WindowMirrorView::RemovedFromWidget() {
RemoveTargetWindowFromSource(target_, source_);
target_ = nullptr;
}
void WindowMirrorView::UpdateSourceWindowProperty() {
DCHECK(GetWidget());
std::vector<aura::Window*>* target_window_list =
source_->GetProperty(aura::client::kMirrorWindowList);
// Remove 1 instance of |target_| from the list.
if (target_ && target_window_list)
EraseFromList(target_window_list, target_);
// Set and insert the new target window associated with this mirror view.
target_ = GetWidget()->GetNativeWindow();
target_->TrackOcclusionState();
// Allocate new memory for |target_window_list| here because as soon as a
// call is made to SetProperty, the previous memory will be deallocated.
auto temp_list =
target_window_list
? std::make_unique<std::vector<aura::Window*>>(*target_window_list)
: std::make_unique<std::vector<aura::Window*>>();
temp_list->push_back(target_);
// Set the property to trigger a call to OnWindowPropertyChanged() on all the
// window observer.
// NOTE: This will deallocate the current property value so make sure new
// memory has been allocated for the property value.
source_->SetProperty(aura::client::kMirrorWindowList, temp_list.release());
}
void WindowMirrorView::InitLayerOwner() {
layer_owner_ = ::wm::MirrorLayers(source_, false /* sync_bounds */);
SetPaintToLayer();
......
......@@ -40,10 +40,18 @@ class WindowMirrorView : public views::View {
void Layout() override;
bool GetNeedsNotificationWhenVisibleBoundsChange() const override;
void OnVisibleBoundsChanged() override;
void NativeViewHierarchyChanged() override;
void AddedToWidget() override;
void RemovedFromWidget() override;
private:
void InitLayerOwner();
// Ensures that the |target_| window is in the list of mirror windows that is
// set as a property on the |source_| window. This method triggers the
// OnWindowPropertyChanged() on WindowObservers.
void UpdateSourceWindowProperty();
// Gets the root of the layer tree that was lifted from |source_| (and is now
// a child of |this->layer()|).
ui::Layer* GetMirrorLayer();
......@@ -55,6 +63,9 @@ class WindowMirrorView : public views::View {
// The original window that is being represented by |this|.
aura::Window* source_;
// The window which contains this mirror view.
aura::Window* target_ = nullptr;
// Retains ownership of the mirror layer tree. This is lazily initialized
// the first time the view becomes visible.
std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
......
......@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_current.h"
......@@ -356,19 +357,93 @@ aura::Window* GetHostWindow(aura::Window* window) {
return window->parent();
}
// Returns true iff the aura::client::kMirroringEnabledKey property is set for
// |window| or its parent. That indicates that |window| is being displayed in
// Alt-Tab view on ChromeOS.
bool WindowIsMirrored(aura::Window* window) {
if (window->GetProperty(aura::client::kMirroringEnabledKey))
return true;
} // namespace
aura::Window* const host_window = GetHostWindow(window);
return host_window &&
host_window->GetProperty(aura::client::kMirroringEnabledKey);
}
// A class to observe windows that are mirroring the WebContentsView's host
// window. It keeps track of the occlusion state for each of these mirror
// windows and requests an update for the webcontent visibility if any of their
// occlusion state changes.
class WebContentsViewAura::MirrorWindowObserver : public aura::WindowObserver {
public:
explicit MirrorWindowObserver(WebContentsViewAura* view) : view_(view) {}
~MirrorWindowObserver() override {
for (auto* mirror_window : mirror_windows_) {
DCHECK(mirror_window->HasObserver(this));
mirror_window->RemoveObserver(this);
}
}
} // namespace
// Starts observing the list of windows provided by |mirror_windows|. Results
// in removing itself as an observer from all other windows. Triggers a
// request to update web content visibilty based on the occlusion state of the
// newly added windows.
void UpdateMirrorWindowList(
const std::vector<aura::Window*>* mirror_windows) {
for (auto* mirror_window : mirror_windows_) {
DCHECK(mirror_window->HasObserver(this));
mirror_window->RemoveObserver(this);
}
mirror_windows_.clear();
visible_mirror_windows_.clear();
if (!mirror_windows) {
view_->UpdateWebContentsVisibility();
return;
}
// Add self as an observer to the list of mirror windows.
for (auto* mirror_window : *mirror_windows) {
auto insert_result = mirror_windows_.insert(mirror_window);
if (insert_result.second)
mirror_window->AddObserver(this);
if (mirror_window->occlusion_state() ==
aura::Window::OcclusionState::VISIBLE) {
visible_mirror_windows_.insert(mirror_window);
}
}
view_->UpdateWebContentsVisibility();
}
// Returns true if there are any mirror windows that this class is observing
// that has their occlusion state set to VISIBLE.
bool HasVisibleMirrorWindow() const { return visible_mirror_windows_.size(); }
private:
// aura::WindowObserver:
void OnWindowDestroyed(aura::Window* mirror_window) override {
mirror_windows_.erase(mirror_window);
visible_mirror_windows_.erase(mirror_window);
}
// aura::WindowObserver:
void OnWindowOcclusionChanged(aura::Window* mirror_window) override {
auto it = visible_mirror_windows_.find(mirror_window);
if (mirror_window->occlusion_state() ==
aura::Window::OcclusionState::VISIBLE &&
it == visible_mirror_windows_.end()) {
visible_mirror_windows_.insert(mirror_window);
} else if (mirror_window->occlusion_state() !=
aura::Window::OcclusionState::VISIBLE &&
it != visible_mirror_windows_.end()) {
visible_mirror_windows_.erase(it);
} else {
return;
}
view_->UpdateWebContentsVisibility();
}
// Subset of |mirror_windows_| that are currently VISIBLE.
base::flat_set<aura::Window*> visible_mirror_windows_;
// Set of mirror windows that this class is observing.
base::flat_set<aura::Window*> mirror_windows_;
WebContentsViewAura* view_;
DISALLOW_COPY_AND_ASSIGN(MirrorWindowObserver);
};
class WebContentsViewAura::WindowObserver
: public aura::WindowObserver, public aura::WindowTreeHostObserver {
......@@ -437,8 +512,16 @@ class WebContentsViewAura::WindowObserver
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override {
if (key == aura::client::kMirroringEnabledKey)
view_->UpdateWebContentsVisibility();
if (key == aura::client::kMirrorWindowList) {
if (!view_->mirror_window_observer_) {
view_->mirror_window_observer_ =
std::make_unique<MirrorWindowObserver>(view_);
}
const std::vector<aura::Window*>* mirror_window_list =
window->GetProperty(aura::client::kMirrorWindowList);
view_->mirror_window_observer_->UpdateMirrorWindowList(
mirror_window_list);
}
}
// Overridden WindowTreeHostObserver:
......@@ -778,7 +861,8 @@ void WebContentsViewAura::UpdateWebContentsVisibility() {
Visibility WebContentsViewAura::GetVisibility() const {
if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE ||
WindowIsMirrored(window_.get())) {
(mirror_window_observer_ &&
mirror_window_observer_->HasVisibleMirrorWindow())) {
return Visibility::VISIBLE;
}
......
......@@ -66,6 +66,7 @@ class CONTENT_EXPORT WebContentsViewAura
private:
class WindowObserver;
class MirrorWindowObserver;
~WebContentsViewAura() override;
......@@ -209,6 +210,8 @@ class CONTENT_EXPORT WebContentsViewAura
std::unique_ptr<WindowObserver> window_observer_;
std::unique_ptr<MirrorWindowObserver> mirror_window_observer_;
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
......
......@@ -16,6 +16,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/test/window_test_api.h"
#include "ui/aura/window.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/geometry/rect.h"
......@@ -24,6 +25,7 @@ namespace content {
namespace {
constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20);
constexpr gfx::Rect kMirrorWindowBounds = gfx::Rect(20, 0, 20, 20);
} // namespace
class WebContentsViewAuraTest : public RenderViewHostTestHarness {
......@@ -41,10 +43,15 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness {
occluding_window_.reset(aura::test::CreateTestWindowWithDelegateAndType(
nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(),
false));
mirror_window_.reset(aura::test::CreateTestWindowWithDelegateAndType(
nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kMirrorWindowBounds,
nullptr, false));
}
void TearDown() override {
occluding_window_.reset();
mirror_window_.reset();
RenderViewHostTestHarness::TearDown();
}
......@@ -55,9 +62,33 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness {
aura::Window* GetNativeView() { return web_contents()->GetNativeView(); }
void EnableMirrorWindow(aura::Window* target_window) {
auto* mirror_window_list = new std::vector<aura::Window*>;
mirror_window_list->push_back(mirror_window_.get());
target_window->SetProperty(aura::client::kMirrorWindowList,
mirror_window_list);
}
void DisableMirrorWindow(aura::Window* target_window) {
target_window->ClearProperty(aura::client::kMirrorWindowList);
}
void ShowMirrorWindow() {
aura::test::WindowTestApi(mirror_window_.get())
.SetOcclusionState(aura::Window::OcclusionState::VISIBLE);
}
void HideMirrorWindow() {
aura::test::WindowTestApi(mirror_window_.get())
.SetOcclusionState(aura::Window::OcclusionState::HIDDEN);
}
// |occluding_window_| occludes |web_contents()| when it's shown.
std::unique_ptr<aura::Window> occluding_window_;
// |mirror_window_| mirrors |web_contents()|.
std::unique_ptr<aura::Window> mirror_window_;
private:
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
......@@ -89,32 +120,47 @@ TEST_F(WebContentsViewAuraTest, OccludeView) {
EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
}
TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenView) {
TEST_F(WebContentsViewAuraTest, MirrorWindowForHiddenView) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
ShowMirrorWindow();
EnableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
HideMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
}
TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedView) {
TEST_F(WebContentsViewAuraTest, MirrorWindowForOccludedView) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
}
......@@ -122,15 +168,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewParent) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
HideMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
}
......@@ -141,9 +198,14 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewParent) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
}
......@@ -163,15 +225,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewHost) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
HideMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
}
......@@ -192,11 +265,17 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewHost) {
intermediate_window->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, true);
EnableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(root_window());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
}
......
......@@ -26,6 +26,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, std::vector<aura::Window*>*)
namespace aura {
namespace client {
......@@ -50,7 +51,9 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kDrawAttentionKey, false);
DEFINE_UI_CLASS_PROPERTY_KEY(FocusClient*, kFocusClientKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kMirroringEnabledKey, false);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::vector<Window*>,
kMirrorWindowList,
nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr);
......
......@@ -6,6 +6,7 @@
#define UI_AURA_CLIENT_AURA_CONSTANTS_H_
#include <string>
#include <vector>
#include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h"
......@@ -81,9 +82,10 @@ AURA_EXPORT extern const WindowProperty<Window*>* const kHostWindowKey;
// A property key to store the minimum size of the window.
AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize;
// A property key to indicate that a window is being "mirrored" and its contents
// should render regardless of its actual visibility state.
AURA_EXPORT extern const WindowProperty<bool>* const kMirroringEnabledKey;
// A property key to store a list of windows showing a mirror of the window this
// property is set on.
AURA_EXPORT extern const WindowProperty<std::vector<Window*>*>* const
kMirrorWindowList;
// The modal parent of a child modal window.
AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey;
......
......@@ -4,7 +4,6 @@
#include "ui/aura/test/window_test_api.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
......@@ -31,5 +30,9 @@ void WindowTestApi::DisableFrameSinkRegistration() {
window_->disable_frame_sink_id_registration_ = true;
}
void WindowTestApi::SetOcclusionState(aura::Window::OcclusionState state) {
window_->SetOcclusionInfo(state, SkRegion());
}
} // namespace test
} // namespace aura
......@@ -6,11 +6,9 @@
#define UI_AURA_TEST_WINDOW_TEST_API_H_
#include "base/macros.h"
#include "ui/aura/window.h"
namespace aura {
class Window;
namespace test {
class WindowTestApi {
......@@ -23,6 +21,8 @@ class WindowTestApi {
void DisableFrameSinkRegistration();
void SetOcclusionState(aura::Window::OcclusionState state);
private:
Window* window_;
......
......@@ -893,6 +893,9 @@ void Window::SetOcclusionInfo(OcclusionState occlusion_state,
occluded_region_ = occluded_region;
if (delegate_)
delegate_->OnWindowOcclusionChanged(occlusion_state, occluded_region);
for (WindowObserver& observer : observers_)
observer.OnWindowOcclusionChanged(this);
}
}
......
......@@ -174,6 +174,9 @@ class AURA_EXPORT WindowObserver : public base::CheckedObserver {
// embedded).
virtual void OnEmbeddedAppDisconnected(Window* window) {}
// Called when the occlusion state of |window| changes.
virtual void OnWindowOcclusionChanged(Window* window) {}
protected:
~WindowObserver() override;
};
......
......@@ -126,7 +126,9 @@ void WindowOcclusionTracker::Track(Window* window) {
DCHECK(window != window->GetRootWindow());
auto insert_result = tracked_windows_.insert({window, {}});
DCHECK(insert_result.second);
if (!insert_result.second)
return;
if (!window_observer_.IsObserving(window))
window_observer_.Add(window);
if (window->GetRootWindow())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment