blob: 2365c6399b8fbb840067058ef2fc701ba4bf7f90 [file] [log] [blame]
// Copyright 2016 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 "ash/wm_window.h"
#include "ash/ash_constants.h"
#include "ash/public/cpp/config.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/wm/resize_handle_window_targeter.h"
#include "ash/wm/resize_shadow_controller.h"
#include "ash/wm/widget_finder.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_mirror_view.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_aura.h"
#include "ash/wm/window_util.h"
#include "ash/wm_transient_window_observer.h"
#include "base/memory/ptr_util.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/mus/window_manager_delegate.h"
#include "ui/aura/mus/window_mus.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_observer.h"
#include "ui/base/class_property.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/easy_resize_window_targeter.h"
#include "ui/wm/core/ime_util_chromeos.h"
#include "ui/wm/core/transient_window_manager.h"
#include "ui/wm/core/visibility_controller.h"
#include "ui/wm/core/window_util.h"
DECLARE_UI_CLASS_PROPERTY_TYPE(ash::WmWindow*);
namespace ash {
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(WmWindow, kWmWindowKey, nullptr);
static_assert(aura::Window::kInitialId == kShellWindowId_Invalid,
"ids must match");
namespace {
// A tentative class to set the bounds on the window.
// TODO(oshima): Once all logic is cleaned up, move this to the real layout
// manager with proper friendship.
class BoundsSetter : public aura::LayoutManager {
public:
BoundsSetter() {}
~BoundsSetter() override {}
// aura::LayoutManager overrides:
void OnWindowResized() override {}
void OnWindowAddedToLayout(aura::Window* child) override {}
void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
void OnWindowRemovedFromLayout(aura::Window* child) override {}
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override {}
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override {}
void SetBounds(aura::Window* window, const gfx::Rect& bounds) {
SetChildBoundsDirect(window, bounds);
}
private:
DISALLOW_COPY_AND_ASSIGN(BoundsSetter);
};
} // namespace
// static
bool WmWindow::default_use_empty_minimum_size_for_testing_ = false;
WmWindow::~WmWindow() {
if (added_transient_observer_)
::wm::TransientWindowManager::Get(window_)->RemoveObserver(this);
window_->RemoveObserver(this);
}
// static
const WmWindow* WmWindow::Get(const aura::Window* window) {
if (!window)
return nullptr;
const WmWindow* wm_window = window->GetProperty(kWmWindowKey);
if (wm_window)
return wm_window;
// WmWindow is owned by the aura::Window.
// TODO(sky): fix constness.
return new WmWindow(const_cast<aura::Window*>(window));
}
// static
std::vector<WmWindow*> WmWindow::FromAuraWindows(
const std::vector<aura::Window*>& aura_windows) {
std::vector<WmWindow*> result(aura_windows.size());
for (size_t i = 0; i < aura_windows.size(); ++i)
result[i] = Get(aura_windows[i]);
return result;
}
// static
std::vector<aura::Window*> WmWindow::ToAuraWindows(
const std::vector<WmWindow*>& windows) {
std::vector<aura::Window*> result(windows.size());
for (size_t i = 0; i < windows.size(); ++i)
result[i] = WmWindow::GetAuraWindow(windows[i]);
return result;
}
// static
const aura::Window* WmWindow::GetAuraWindow(const WmWindow* wm_window) {
return wm_window ? static_cast<const WmWindow*>(wm_window)->aura_window()
: nullptr;
}
bool WmWindow::ShouldUseExtendedHitRegion() const {
const WmWindow* parent = Get(window_->parent());
return parent &&
static_cast<const WmWindow*>(parent)
->children_use_extended_hit_region_;
}
void WmWindow::Destroy() {
delete window_;
// WARNING: this has been deleted.
}
const WmWindow* WmWindow::GetRootWindow() const {
return Get(window_->GetRootWindow());
}
RootWindowController* WmWindow::GetRootWindowController() {
aura::Window* root = window_->GetRootWindow();
return root ? RootWindowController::ForWindow(root) : nullptr;
}
ui::wm::WindowType WmWindow::GetType() const {
return window_->type();
}
int WmWindow::GetAppType() const {
return window_->GetProperty(aura::client::kAppType);
}
void WmWindow::SetAppType(int app_type) const {
window_->SetProperty(aura::client::kAppType, app_type);
}
ui::Layer* WmWindow::GetLayer() {
return window_->layer();
}
bool WmWindow::GetLayerTargetVisibility() {
return GetLayer()->GetTargetVisibility();
}
bool WmWindow::GetLayerVisible() {
return GetLayer()->visible();
}
display::Display WmWindow::GetDisplayNearestWindow() {
return display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
}
bool WmWindow::HasNonClientArea() {
return window_->delegate() ? true : false;
}
int WmWindow::GetNonClientComponent(const gfx::Point& location) {
return window_->delegate()
? window_->delegate()->GetNonClientComponent(location)
: HTNOWHERE;
}
gfx::Point WmWindow::ConvertPointToTarget(const WmWindow* target,
const gfx::Point& point) const {
gfx::Point result(point);
aura::Window::ConvertPointToTarget(window_, GetAuraWindow(target), &result);
return result;
}
gfx::Point WmWindow::ConvertPointToScreen(const gfx::Point& point) const {
gfx::Point result(point);
::wm::ConvertPointToScreen(window_, &result);
return result;
}
gfx::Point WmWindow::ConvertPointFromScreen(const gfx::Point& point) const {
gfx::Point result(point);
::wm::ConvertPointFromScreen(window_, &result);
return result;
}
gfx::Rect WmWindow::ConvertRectToScreen(const gfx::Rect& rect) const {
gfx::Rect result(rect);
::wm::ConvertRectToScreen(window_, &result);
return result;
}
gfx::Rect WmWindow::ConvertRectFromScreen(const gfx::Rect& rect) const {
gfx::Rect result(rect);
::wm::ConvertRectFromScreen(window_, &result);
return result;
}
gfx::Size WmWindow::GetMinimumSize() const {
return window_->delegate() && !use_empty_minimum_size_for_testing_
? window_->delegate()->GetMinimumSize()
: gfx::Size();
}
gfx::Size WmWindow::GetMaximumSize() const {
return window_->delegate() ? window_->delegate()->GetMaximumSize()
: gfx::Size();
}
bool WmWindow::GetTargetVisibility() const {
return window_->TargetVisibility();
}
bool WmWindow::IsVisible() const {
return window_->IsVisible();
}
void WmWindow::SetOpacity(float opacity) {
window_->layer()->SetOpacity(opacity);
}
float WmWindow::GetTargetOpacity() const {
return window_->layer()->GetTargetOpacity();
}
gfx::Rect WmWindow::GetMinimizeAnimationTargetBoundsInScreen() const {
return ash::GetMinimizeAnimationTargetBoundsInScreen(window_);
}
void WmWindow::SetTransform(const gfx::Transform& transform) {
window_->SetTransform(transform);
}
gfx::Transform WmWindow::GetTargetTransform() const {
return window_->layer()->GetTargetTransform();
}
bool WmWindow::IsSystemModal() const {
return window_->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM;
}
const wm::WindowState* WmWindow::GetWindowState() const {
return ash::wm::GetWindowState(window_);
}
WmWindow* WmWindow::GetToplevelWindow() {
return Get(window_->GetToplevelWindow());
}
WmWindow* WmWindow::GetToplevelWindowForFocus() {
return Get(::wm::GetToplevelWindow(window_));
}
void WmWindow::SetParentUsingContext(WmWindow* context,
const gfx::Rect& screen_bounds) {
aura::client::ParentWindowWithContext(window_, GetAuraWindow(context),
screen_bounds);
}
void WmWindow::AddChild(WmWindow* window) {
window_->AddChild(GetAuraWindow(window));
}
void WmWindow::RemoveChild(WmWindow* child) {
window_->RemoveChild(GetAuraWindow(child));
}
const WmWindow* WmWindow::GetParent() const {
return Get(window_->parent());
}
const WmWindow* WmWindow::GetTransientParent() const {
return Get(::wm::GetTransientParent(window_));
}
std::vector<WmWindow*> WmWindow::GetTransientChildren() {
return FromAuraWindows(::wm::GetTransientChildren(window_));
}
bool WmWindow::MoveToEventRoot(const ui::Event& event) {
return ash::wm::MoveWindowToEventRoot(window_, event);
}
void WmWindow::SetVisibilityChangesAnimated() {
::wm::SetWindowVisibilityChangesAnimated(window_);
}
void WmWindow::SetVisibilityAnimationType(int type) {
::wm::SetWindowVisibilityAnimationType(window_, type);
}
void WmWindow::SetVisibilityAnimationDuration(base::TimeDelta delta) {
::wm::SetWindowVisibilityAnimationDuration(window_, delta);
}
void WmWindow::SetVisibilityAnimationTransition(
::wm::WindowVisibilityAnimationTransition transition) {
::wm::SetWindowVisibilityAnimationTransition(window_, transition);
}
void WmWindow::Animate(::wm::WindowAnimationType type) {
::wm::AnimateWindow(window_, type);
}
void WmWindow::StopAnimatingProperty(
ui::LayerAnimationElement::AnimatableProperty property) {
window_->layer()->GetAnimator()->StopAnimatingProperty(property);
}
void WmWindow::SetChildWindowVisibilityChangesAnimated() {
::wm::SetChildWindowVisibilityChangesAnimated(window_);
}
void WmWindow::SetMasksToBounds(bool value) {
window_->layer()->SetMasksToBounds(value);
}
void WmWindow::SetBounds(const gfx::Rect& bounds) {
window_->SetBounds(bounds);
}
void WmWindow::SetBoundsWithTransitionDelay(const gfx::Rect& bounds,
base::TimeDelta delta) {
if (::wm::WindowAnimationsDisabled(window_)) {
window_->SetBounds(bounds);
return;
}
ui::ScopedLayerAnimationSettings settings(window_->layer()->GetAnimator());
settings.SetTransitionDuration(delta);
window_->SetBounds(bounds);
}
void WmWindow::SetBoundsDirect(const gfx::Rect& bounds) {
BoundsSetter().SetBounds(window_, bounds);
wm::SnapWindowToPixelBoundary(window_);
}
void WmWindow::SetBoundsDirectAnimated(const gfx::Rect& bounds) {
const int kBoundsChangeSlideDurationMs = 120;
ui::Layer* layer = window_->layer();
ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
slide_settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
slide_settings.SetTransitionDuration(
base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs));
SetBoundsDirect(bounds);
}
void WmWindow::SetBoundsDirectCrossFade(const gfx::Rect& bounds) {
const gfx::Rect old_bounds = window_->bounds();
// Create fresh layers for the window and all its children to paint into.
// Takes ownership of the old layer and all its children, which will be
// cleaned up after the animation completes.
// Specify |set_bounds| to true here to keep the old bounds in the child
// windows of |window|.
std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
::wm::RecreateLayers(window_);
ui::Layer* old_layer = old_layer_owner->root();
DCHECK(old_layer);
ui::Layer* new_layer = window_->layer();
// Resize the window to the new size, which will force a layout and paint.
SetBoundsDirect(bounds);
// Ensure the higher-resolution layer is on top.
bool old_on_top = (old_bounds.width() > bounds.width());
if (old_on_top)
old_layer->parent()->StackBelow(new_layer, old_layer);
else
old_layer->parent()->StackAbove(new_layer, old_layer);
CrossFadeAnimation(window_, std::move(old_layer_owner), gfx::Tween::EASE_OUT);
}
void WmWindow::SetBoundsInScreen(const gfx::Rect& bounds_in_screen,
const display::Display& dst_display) {
window_->SetBoundsInScreen(bounds_in_screen, dst_display);
}
gfx::Rect WmWindow::GetBoundsInScreen() const {
return window_->GetBoundsInScreen();
}
const gfx::Rect& WmWindow::GetBounds() const {
return window_->bounds();
}
gfx::Rect WmWindow::GetTargetBounds() {
return window_->GetTargetBounds();
}
void WmWindow::ClearRestoreBounds() {
window_->ClearProperty(aura::client::kRestoreBoundsKey);
window_->ClearProperty(::wm::kVirtualKeyboardRestoreBoundsKey);
}
void WmWindow::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
}
gfx::Rect WmWindow::GetRestoreBoundsInScreen() const {
gfx::Rect* bounds = window_->GetProperty(aura::client::kRestoreBoundsKey);
return bounds ? *bounds : gfx::Rect();
}
bool WmWindow::Contains(const WmWindow* other) const {
return other ? window_->Contains(static_cast<const WmWindow*>(other)->window_)
: false;
}
void WmWindow::SetShowState(ui::WindowShowState show_state) {
window_->SetProperty(aura::client::kShowStateKey, show_state);
}
ui::WindowShowState WmWindow::GetShowState() const {
return window_->GetProperty(aura::client::kShowStateKey);
}
void WmWindow::SetPreMinimizedShowState(ui::WindowShowState show_state) {
window_->SetProperty(aura::client::kPreMinimizedShowStateKey, show_state);
}
ui::WindowShowState WmWindow::GetPreMinimizedShowState() const {
return window_->GetProperty(aura::client::kPreMinimizedShowStateKey);
}
void WmWindow::SetPreFullscreenShowState(ui::WindowShowState show_state) {
// We should never store the ui::SHOW_STATE_MINIMIZED as the show state before
// fullscreen.
DCHECK_NE(show_state, ui::SHOW_STATE_MINIMIZED);
window_->SetProperty(aura::client::kPreFullscreenShowStateKey, show_state);
}
void WmWindow::SetRestoreOverrides(const gfx::Rect& bounds_override,
ui::WindowShowState window_state_override) {
if (bounds_override.IsEmpty()) {
window_->ClearProperty(kRestoreShowStateOverrideKey);
window_->ClearProperty(kRestoreBoundsOverrideKey);
return;
}
window_->SetProperty(kRestoreShowStateOverrideKey, window_state_override);
window_->SetProperty(kRestoreBoundsOverrideKey,
new gfx::Rect(bounds_override));
}
void WmWindow::SetLockedToRoot(bool value) {
window_->SetProperty(kLockedToRootKey, value);
}
bool WmWindow::IsLockedToRoot() const {
return window_->GetProperty(kLockedToRootKey);
}
void WmWindow::SetCapture() {
window_->SetCapture();
}
bool WmWindow::HasCapture() {
return window_->HasCapture();
}
void WmWindow::ReleaseCapture() {
window_->ReleaseCapture();
}
bool WmWindow::HasRestoreBounds() const {
return window_->GetProperty(aura::client::kRestoreBoundsKey) != nullptr;
}
bool WmWindow::CanMaximize() const {
return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
ui::mojom::kResizeBehaviorCanMaximize) != 0;
}
bool WmWindow::CanMinimize() const {
return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
ui::mojom::kResizeBehaviorCanMinimize) != 0;
}
bool WmWindow::CanResize() const {
return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
ui::mojom::kResizeBehaviorCanResize) != 0;
}
bool WmWindow::CanActivate() const {
// TODO(sky): for aura-mus need to key off CanFocus() as well, which is not
// currently mirrored to ash.
return ::wm::CanActivateWindow(window_);
}
void WmWindow::StackChildAtTop(WmWindow* child) {
window_->StackChildAtTop(GetAuraWindow(child));
}
void WmWindow::StackChildAtBottom(WmWindow* child) {
window_->StackChildAtBottom(GetAuraWindow(child));
}
void WmWindow::StackChildAbove(WmWindow* child, WmWindow* target) {
window_->StackChildAbove(GetAuraWindow(child), GetAuraWindow(target));
}
void WmWindow::StackChildBelow(WmWindow* child, WmWindow* target) {
window_->StackChildBelow(GetAuraWindow(child), GetAuraWindow(target));
}
void WmWindow::SetAlwaysOnTop(bool value) {
window_->SetProperty(aura::client::kAlwaysOnTopKey, value);
}
bool WmWindow::IsAlwaysOnTop() const {
return window_->GetProperty(aura::client::kAlwaysOnTopKey);
}
void WmWindow::Hide() {
window_->Hide();
}
void WmWindow::Show() {
window_->Show();
}
void WmWindow::CloseWidget() {
if (Shell::GetAshConfig() == Config::MASH &&
aura_window()->GetProperty(kWidgetCreationTypeKey) ==
WidgetCreationType::FOR_CLIENT) {
// NOTE: in the FOR_CLIENT case there is not necessarily a widget associated
// with the window. Mash only creates widgets for top level windows if mash
// renders the non-client frame.
DCHECK(Shell::window_manager_client());
Shell::window_manager_client()->RequestClose(aura_window());
return;
}
views::Widget* widget = GetInternalWidgetForWindow(window_);
DCHECK(widget);
widget->Close();
}
void WmWindow::SetFocused() {
aura::client::GetFocusClient(window_)->FocusWindow(window_);
}
bool WmWindow::IsFocused() const {
return window_->HasFocus();
}
bool WmWindow::IsActive() const {
return wm::IsActiveWindow(window_);
}
void WmWindow::Activate() {
wm::ActivateWindow(window_);
}
void WmWindow::Deactivate() {
wm::DeactivateWindow(window_);
}
void WmWindow::SetFullscreen(bool fullscreen) {
::wm::SetWindowFullscreen(window_, fullscreen);
}
void WmWindow::Maximize() {
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
}
void WmWindow::Minimize() {
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
}
void WmWindow::Unminimize() {
window_->SetProperty(
aura::client::kShowStateKey,
window_->GetProperty(aura::client::kPreMinimizedShowStateKey));
window_->ClearProperty(aura::client::kPreMinimizedShowStateKey);
}
std::vector<WmWindow*> WmWindow::GetChildren() {
return FromAuraWindows(window_->children());
}
WmWindow* WmWindow::GetChildByShellWindowId(int id) {
return Get(window_->GetChildById(id));
}
void WmWindow::ShowResizeShadow(int component) {
if (Shell::GetAshConfig() == Config::MASH) {
// TODO: http://crbug.com/640773.
return;
}
ResizeShadowController* resize_shadow_controller =
Shell::Get()->resize_shadow_controller();
if (resize_shadow_controller)
resize_shadow_controller->ShowShadow(window_, component);
}
void WmWindow::HideResizeShadow() {
if (Shell::GetAshConfig() == Config::MASH) {
// TODO: http://crbug.com/640773.
return;
}
ResizeShadowController* resize_shadow_controller =
Shell::Get()->resize_shadow_controller();
if (resize_shadow_controller)
resize_shadow_controller->HideShadow(window_);
}
void WmWindow::InstallResizeHandleWindowTargeter(
ImmersiveFullscreenController* immersive_fullscreen_controller) {
window_->SetEventTargeter(base::MakeUnique<ResizeHandleWindowTargeter>(
window_, immersive_fullscreen_controller));
}
void WmWindow::SetBoundsInScreenBehaviorForChildren(
BoundsInScreenBehavior behavior) {
window_->SetProperty(
kUsesScreenCoordinatesKey,
behavior == BoundsInScreenBehavior::USE_SCREEN_COORDINATES);
}
void WmWindow::SetSnapsChildrenToPhysicalPixelBoundary() {
wm::SetSnapsChildrenToPhysicalPixelBoundary(window_);
}
void WmWindow::SnapToPixelBoundaryIfNecessary() {
wm::SnapWindowToPixelBoundary(window_);
}
void WmWindow::SetChildrenUseExtendedHitRegion() {
children_use_extended_hit_region_ = true;
gfx::Insets mouse_extend(-kResizeOutsideBoundsSize, -kResizeOutsideBoundsSize,
-kResizeOutsideBoundsSize,
-kResizeOutsideBoundsSize);
gfx::Insets touch_extend =
mouse_extend.Scale(kResizeOutsideBoundsScaleForTouch);
// TODO: EasyResizeWindowTargeter makes it so children get events outside
// their bounds. This only works in mash when mash is providing the non-client
// frame. Mus needs to support an api for the WindowManager that enables
// events to be dispatched to windows outside the windows bounds that this
// function calls into. http://crbug.com/679056.
window_->SetEventTargeter(base::MakeUnique<::wm::EasyResizeWindowTargeter>(
window_, mouse_extend, touch_extend));
}
std::unique_ptr<views::View> WmWindow::CreateViewWithRecreatedLayers() {
return base::MakeUnique<wm::WindowMirrorView>(this);
}
void WmWindow::AddTransientWindowObserver(WmTransientWindowObserver* observer) {
if (!added_transient_observer_) {
added_transient_observer_ = true;
::wm::TransientWindowManager::Get(window_)->AddObserver(this);
}
transient_observers_.AddObserver(observer);
}
void WmWindow::RemoveTransientWindowObserver(
WmTransientWindowObserver* observer) {
transient_observers_.RemoveObserver(observer);
if (added_transient_observer_ &&
!transient_observers_.might_have_observers()) {
added_transient_observer_ = false;
::wm::TransientWindowManager::Get(window_)->RemoveObserver(this);
}
}
void WmWindow::AddLimitedPreTargetHandler(ui::EventHandler* handler) {
// In mus AddPreTargetHandler() only works for windows created by this client.
DCHECK(Shell::GetAshConfig() != Config::MASH ||
Shell::window_tree_client()->WasCreatedByThisClient(
aura::WindowMus::Get(window_)));
window_->AddPreTargetHandler(handler);
}
void WmWindow::RemoveLimitedPreTargetHandler(ui::EventHandler* handler) {
window_->RemovePreTargetHandler(handler);
}
WmWindow::WmWindow(aura::Window* window)
: window_(window),
use_empty_minimum_size_for_testing_(
default_use_empty_minimum_size_for_testing_) {
window_->AddObserver(this);
window_->SetProperty(kWmWindowKey, this);
}
void WmWindow::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
if (key == aura::client::kShowStateKey) {
ash::wm::GetWindowState(window_)->OnWindowShowStateChanged();
return;
}
if (key == aura::client::kImmersiveFullscreenKey) {
bool enable = window_->GetProperty(aura::client::kImmersiveFullscreenKey);
GetWindowState()->set_in_immersive_fullscreen(enable);
return;
}
if (key == kWindowPinTypeKey) {
ash::wm::GetWindowState(window_)->OnWindowPinTypeChanged();
return;
}
}
void WmWindow::OnTransientChildAdded(aura::Window* window,
aura::Window* transient) {
for (auto& observer : transient_observers_)
observer.OnTransientChildAdded(this, Get(transient));
}
void WmWindow::OnTransientChildRemoved(aura::Window* window,
aura::Window* transient) {
for (auto& observer : transient_observers_)
observer.OnTransientChildRemoved(this, Get(transient));
}
} // namespace ash