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 @@ ...@@ -4,6 +4,9 @@
#include "ash/wm/window_mirror_view.h" #include "ash/wm/window_mirror_view.h"
#include <algorithm>
#include <memory>
#include "ash/wm/widget_finder.h" #include "ash/wm/widget_finder.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
...@@ -28,6 +31,23 @@ void EnsureAllChildrenAreVisible(ui::Layer* layer) { ...@@ -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 } // namespace
WindowMirrorView::WindowMirrorView(aura::Window* source, WindowMirrorView::WindowMirrorView(aura::Window* source,
...@@ -40,8 +60,7 @@ WindowMirrorView::WindowMirrorView(aura::Window* source, ...@@ -40,8 +60,7 @@ WindowMirrorView::WindowMirrorView(aura::Window* source,
WindowMirrorView::~WindowMirrorView() { WindowMirrorView::~WindowMirrorView() {
// Make sure |source_| has outlived |this|. See crbug.com/681207 // Make sure |source_| has outlived |this|. See crbug.com/681207
DCHECK(source_->layer()); DCHECK(source_->layer());
if (layer_owner_) RemoveTargetWindowFromSource(target_, source_);
source_->ClearProperty(aura::client::kMirroringEnabledKey);
} }
void WindowMirrorView::RecreateMirrorLayers() { void WindowMirrorView::RecreateMirrorLayers() {
...@@ -85,10 +104,51 @@ void WindowMirrorView::OnVisibleBoundsChanged() { ...@@ -85,10 +104,51 @@ void WindowMirrorView::OnVisibleBoundsChanged() {
InitLayerOwner(); InitLayerOwner();
} }
void WindowMirrorView::InitLayerOwner() { void WindowMirrorView::NativeViewHierarchyChanged() {
if (!layer_owner_) View::NativeViewHierarchyChanged();
source_->SetProperty(aura::client::kMirroringEnabledKey, true); 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 */); layer_owner_ = ::wm::MirrorLayers(source_, false /* sync_bounds */);
SetPaintToLayer(); SetPaintToLayer();
......
...@@ -40,10 +40,18 @@ class WindowMirrorView : public views::View { ...@@ -40,10 +40,18 @@ class WindowMirrorView : public views::View {
void Layout() override; void Layout() override;
bool GetNeedsNotificationWhenVisibleBoundsChange() const override; bool GetNeedsNotificationWhenVisibleBoundsChange() const override;
void OnVisibleBoundsChanged() override; void OnVisibleBoundsChanged() override;
void NativeViewHierarchyChanged() override;
void AddedToWidget() override;
void RemovedFromWidget() override;
private: private:
void InitLayerOwner(); 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 // Gets the root of the layer tree that was lifted from |source_| (and is now
// a child of |this->layer()|). // a child of |this->layer()|).
ui::Layer* GetMirrorLayer(); ui::Layer* GetMirrorLayer();
...@@ -55,6 +63,9 @@ class WindowMirrorView : public views::View { ...@@ -55,6 +63,9 @@ class WindowMirrorView : public views::View {
// The original window that is being represented by |this|. // The original window that is being represented by |this|.
aura::Window* source_; 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 // Retains ownership of the mirror layer tree. This is lazily initialized
// the first time the view becomes visible. // the first time the view becomes visible.
std::unique_ptr<ui::LayerTreeOwner> layer_owner_; std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop_current.h" #include "base/message_loop/message_loop_current.h"
...@@ -356,19 +357,93 @@ aura::Window* GetHostWindow(aura::Window* window) { ...@@ -356,19 +357,93 @@ aura::Window* GetHostWindow(aura::Window* window) {
return window->parent(); return window->parent();
} }
// Returns true iff the aura::client::kMirroringEnabledKey property is set for } // namespace
// |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;
aura::Window* const host_window = GetHostWindow(window); // A class to observe windows that are mirroring the WebContentsView's host
return host_window && // window. It keeps track of the occlusion state for each of these mirror
host_window->GetProperty(aura::client::kMirroringEnabledKey); // 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 class WebContentsViewAura::WindowObserver
: public aura::WindowObserver, public aura::WindowTreeHostObserver { : public aura::WindowObserver, public aura::WindowTreeHostObserver {
...@@ -437,8 +512,16 @@ class WebContentsViewAura::WindowObserver ...@@ -437,8 +512,16 @@ class WebContentsViewAura::WindowObserver
void OnWindowPropertyChanged(aura::Window* window, void OnWindowPropertyChanged(aura::Window* window,
const void* key, const void* key,
intptr_t old) override { intptr_t old) override {
if (key == aura::client::kMirroringEnabledKey) if (key == aura::client::kMirrorWindowList) {
view_->UpdateWebContentsVisibility(); 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: // Overridden WindowTreeHostObserver:
...@@ -778,7 +861,8 @@ void WebContentsViewAura::UpdateWebContentsVisibility() { ...@@ -778,7 +861,8 @@ void WebContentsViewAura::UpdateWebContentsVisibility() {
Visibility WebContentsViewAura::GetVisibility() const { Visibility WebContentsViewAura::GetVisibility() const {
if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE || if (window_->occlusion_state() == aura::Window::OcclusionState::VISIBLE ||
WindowIsMirrored(window_.get())) { (mirror_window_observer_ &&
mirror_window_observer_->HasVisibleMirrorWindow())) {
return Visibility::VISIBLE; return Visibility::VISIBLE;
} }
......
...@@ -66,6 +66,7 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -66,6 +66,7 @@ class CONTENT_EXPORT WebContentsViewAura
private: private:
class WindowObserver; class WindowObserver;
class MirrorWindowObserver;
~WebContentsViewAura() override; ~WebContentsViewAura() override;
...@@ -209,6 +210,8 @@ class CONTENT_EXPORT WebContentsViewAura ...@@ -209,6 +210,8 @@ class CONTENT_EXPORT WebContentsViewAura
std::unique_ptr<WindowObserver> window_observer_; std::unique_ptr<WindowObserver> window_observer_;
std::unique_ptr<MirrorWindowObserver> mirror_window_observer_;
// The WebContentsImpl whose contents we display. // The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_; WebContentsImpl* web_contents_;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_windows.h" #include "ui/aura/test/test_windows.h"
#include "ui/aura/test/window_test_api.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/display/display_switches.h" #include "ui/display/display_switches.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -24,6 +25,7 @@ namespace content { ...@@ -24,6 +25,7 @@ namespace content {
namespace { namespace {
constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20); constexpr gfx::Rect kBounds = gfx::Rect(0, 0, 20, 20);
constexpr gfx::Rect kMirrorWindowBounds = gfx::Rect(20, 0, 20, 20);
} // namespace } // namespace
class WebContentsViewAuraTest : public RenderViewHostTestHarness { class WebContentsViewAuraTest : public RenderViewHostTestHarness {
...@@ -41,10 +43,15 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness { ...@@ -41,10 +43,15 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness {
occluding_window_.reset(aura::test::CreateTestWindowWithDelegateAndType( occluding_window_.reset(aura::test::CreateTestWindowWithDelegateAndType(
nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(), nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kBounds, root_window(),
false)); false));
mirror_window_.reset(aura::test::CreateTestWindowWithDelegateAndType(
nullptr, aura::client::WINDOW_TYPE_NORMAL, 0, kMirrorWindowBounds,
nullptr, false));
} }
void TearDown() override { void TearDown() override {
occluding_window_.reset(); occluding_window_.reset();
mirror_window_.reset();
RenderViewHostTestHarness::TearDown(); RenderViewHostTestHarness::TearDown();
} }
...@@ -55,9 +62,33 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness { ...@@ -55,9 +62,33 @@ class WebContentsViewAuraTest : public RenderViewHostTestHarness {
aura::Window* GetNativeView() { return web_contents()->GetNativeView(); } 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. // |occluding_window_| occludes |web_contents()| when it's shown.
std::unique_ptr<aura::Window> occluding_window_; std::unique_ptr<aura::Window> occluding_window_;
// |mirror_window_| mirrors |web_contents()|.
std::unique_ptr<aura::Window> mirror_window_;
private: private:
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest); DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
}; };
...@@ -89,32 +120,47 @@ TEST_F(WebContentsViewAuraTest, OccludeView) { ...@@ -89,32 +120,47 @@ TEST_F(WebContentsViewAuraTest, OccludeView) {
EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), Visibility::VISIBLE);
} }
TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenView) { TEST_F(WebContentsViewAuraTest, MirrorWindowForHiddenView) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide(); root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
HideMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show(); root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, true);
ShowMirrorWindow();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); 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; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion); scoped_feature_list.InitAndEnableFeature(features::kWebContentsOcclusion);
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show(); occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
GetNativeView()->SetProperty(aura::client::kMirroringEnabledKey, false);
DisableMirrorWindow(GetNativeView());
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
} }
...@@ -122,15 +168,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewParent) { ...@@ -122,15 +168,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewParent) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide(); root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show(); root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
} }
...@@ -141,9 +198,14 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewParent) { ...@@ -141,9 +198,14 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewParent) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show(); occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
} }
...@@ -163,15 +225,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewHost) { ...@@ -163,15 +225,26 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForHiddenViewHost) {
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
root_window()->Hide(); root_window()->Hide();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::HIDDEN);
root_window()->Show(); root_window()->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
} }
...@@ -192,11 +265,17 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewHost) { ...@@ -192,11 +265,17 @@ TEST_F(WebContentsViewAuraTest, MirroringEnabledForOccludedViewHost) {
intermediate_window->Show(); intermediate_window->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::VISIBLE);
occluding_window_->Show(); occluding_window_->Show();
EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED); 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); 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); EXPECT_EQ(web_contents()->GetVisibility(), content::Visibility::OCCLUDED);
} }
......
...@@ -26,6 +26,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t) ...@@ -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, int64_t)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*) 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, aura::Window*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, std::vector<aura::Window*>*)
namespace aura { namespace aura {
namespace client { namespace client {
...@@ -50,7 +51,9 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kDrawAttentionKey, false); ...@@ -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(FocusClient*, kFocusClientKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, 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(Window*, kChildModalParentKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE); DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr); DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define UI_AURA_CLIENT_AURA_CONSTANTS_H_ #define UI_AURA_CLIENT_AURA_CONSTANTS_H_
#include <string> #include <string>
#include <vector>
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
...@@ -81,9 +82,10 @@ AURA_EXPORT extern const WindowProperty<Window*>* const kHostWindowKey; ...@@ -81,9 +82,10 @@ AURA_EXPORT extern const WindowProperty<Window*>* const kHostWindowKey;
// A property key to store the minimum size of the window. // A property key to store the minimum size of the window.
AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize; AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize;
// A property key to indicate that a window is being "mirrored" and its contents // A property key to store a list of windows showing a mirror of the window this
// should render regardless of its actual visibility state. // property is set on.
AURA_EXPORT extern const WindowProperty<bool>* const kMirroringEnabledKey; AURA_EXPORT extern const WindowProperty<std::vector<Window*>*>* const
kMirrorWindowList;
// The modal parent of a child modal window. // The modal parent of a child modal window.
AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey; AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey;
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "ui/aura/test/window_test_api.h" #include "ui/aura/test/window_test_api.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
...@@ -31,5 +30,9 @@ void WindowTestApi::DisableFrameSinkRegistration() { ...@@ -31,5 +30,9 @@ void WindowTestApi::DisableFrameSinkRegistration() {
window_->disable_frame_sink_id_registration_ = true; window_->disable_frame_sink_id_registration_ = true;
} }
void WindowTestApi::SetOcclusionState(aura::Window::OcclusionState state) {
window_->SetOcclusionInfo(state, SkRegion());
}
} // namespace test } // namespace test
} // namespace aura } // namespace aura
...@@ -6,11 +6,9 @@ ...@@ -6,11 +6,9 @@
#define UI_AURA_TEST_WINDOW_TEST_API_H_ #define UI_AURA_TEST_WINDOW_TEST_API_H_
#include "base/macros.h" #include "base/macros.h"
#include "ui/aura/window.h"
namespace aura { namespace aura {
class Window;
namespace test { namespace test {
class WindowTestApi { class WindowTestApi {
...@@ -23,6 +21,8 @@ class WindowTestApi { ...@@ -23,6 +21,8 @@ class WindowTestApi {
void DisableFrameSinkRegistration(); void DisableFrameSinkRegistration();
void SetOcclusionState(aura::Window::OcclusionState state);
private: private:
Window* window_; Window* window_;
......
...@@ -893,6 +893,9 @@ void Window::SetOcclusionInfo(OcclusionState occlusion_state, ...@@ -893,6 +893,9 @@ void Window::SetOcclusionInfo(OcclusionState occlusion_state,
occluded_region_ = occluded_region; occluded_region_ = occluded_region;
if (delegate_) if (delegate_)
delegate_->OnWindowOcclusionChanged(occlusion_state, occluded_region); delegate_->OnWindowOcclusionChanged(occlusion_state, occluded_region);
for (WindowObserver& observer : observers_)
observer.OnWindowOcclusionChanged(this);
} }
} }
......
...@@ -174,6 +174,9 @@ class AURA_EXPORT WindowObserver : public base::CheckedObserver { ...@@ -174,6 +174,9 @@ class AURA_EXPORT WindowObserver : public base::CheckedObserver {
// embedded). // embedded).
virtual void OnEmbeddedAppDisconnected(Window* window) {} virtual void OnEmbeddedAppDisconnected(Window* window) {}
// Called when the occlusion state of |window| changes.
virtual void OnWindowOcclusionChanged(Window* window) {}
protected: protected:
~WindowObserver() override; ~WindowObserver() override;
}; };
......
...@@ -126,7 +126,9 @@ void WindowOcclusionTracker::Track(Window* window) { ...@@ -126,7 +126,9 @@ void WindowOcclusionTracker::Track(Window* window) {
DCHECK(window != window->GetRootWindow()); DCHECK(window != window->GetRootWindow());
auto insert_result = tracked_windows_.insert({window, {}}); auto insert_result = tracked_windows_.insert({window, {}});
DCHECK(insert_result.second); if (!insert_result.second)
return;
if (!window_observer_.IsObserving(window)) if (!window_observer_.IsObserving(window))
window_observer_.Add(window); window_observer_.Add(window);
if (window->GetRootWindow()) 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