| Index: ash/wm/window_state.cc
|
| diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
|
| index a5488c1472f92689f4f040bdd198d76146b0ae3b..a64963d7a80b2b9200fc8307093750e455ccbab4 100644
|
| --- a/ash/wm/window_state.cc
|
| +++ b/ash/wm/window_state.cc
|
| @@ -10,21 +10,58 @@
|
| #include "ash/public/interfaces/window_pin_type.mojom.h"
|
| #include "ash/screen_util.h"
|
| #include "ash/wm/default_state.h"
|
| +#include "ash/wm/window_animations.h"
|
| #include "ash/wm/window_positioning_utils.h"
|
| #include "ash/wm/window_properties.h"
|
| #include "ash/wm/window_state_delegate.h"
|
| #include "ash/wm/window_state_observer.h"
|
| #include "ash/wm/window_util.h"
|
| #include "ash/wm/wm_event.h"
|
| -#include "ash/wm_window.h"
|
| #include "base/auto_reset.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/layout_manager.h"
|
| #include "ui/aura/window.h"
|
| +#include "ui/aura/window_delegate.h"
|
| +#include "ui/compositor/layer_tree_owner.h"
|
| +#include "ui/compositor/scoped_layer_animation_settings.h"
|
| +#include "ui/display/display.h"
|
| +#include "ui/display/screen.h"
|
| +#include "ui/wm/core/coordinate_conversion.h"
|
| +#include "ui/wm/core/ime_util_chromeos.h"
|
| +#include "ui/wm/core/window_util.h"
|
|
|
| namespace ash {
|
| namespace wm {
|
| -
|
| 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);
|
| +};
|
| +
|
| WMEventType WMEventTypeFromShowState(ui::WindowShowState requested_show_state) {
|
| switch (requested_show_state) {
|
| case ui::SHOW_STATE_DEFAULT:
|
| @@ -61,7 +98,12 @@ WMEventType WMEventTypeFromWindowPinType(ash::mojom::WindowPinType type) {
|
|
|
| } // namespace
|
|
|
| -WindowState::~WindowState() {}
|
| +WindowState::~WindowState() {
|
| + // WindowState is registered as an owned property of |window_|, and window
|
| + // unregisters all of its observers in its d'tor before destroying its
|
| + // properties. As a result, window_->RemoveObserver() doesn't need to (and
|
| + // shouldn't) be called here.
|
| +}
|
|
|
| bool WindowState::HasDelegate() const {
|
| return !!delegate_;
|
| @@ -117,41 +159,45 @@ bool WindowState::IsNormalOrSnapped() const {
|
| }
|
|
|
| bool WindowState::IsActive() const {
|
| - return window_->IsActive();
|
| + return ::wm::IsActiveWindow(window_);
|
| }
|
|
|
| bool WindowState::IsUserPositionable() const {
|
| - return (window_->GetType() == ui::wm::WINDOW_TYPE_NORMAL ||
|
| - window_->GetType() == ui::wm::WINDOW_TYPE_PANEL);
|
| + return (window_->type() == ui::wm::WINDOW_TYPE_NORMAL ||
|
| + window_->type() == ui::wm::WINDOW_TYPE_PANEL);
|
| }
|
|
|
| bool WindowState::CanMaximize() const {
|
| // Window must allow maximization and have no maximum width or height.
|
| - if (!window_->CanMaximize())
|
| + if ((window_->GetProperty(aura::client::kResizeBehaviorKey) &
|
| + ui::mojom::kResizeBehaviorCanMaximize) == 0) {
|
| return false;
|
| + }
|
|
|
| - if (!window_->HasNonClientArea())
|
| + if (!window_->delegate())
|
| return true;
|
|
|
| - gfx::Size max_size = window_->GetMaximumSize();
|
| + const gfx::Size max_size = window_->delegate()->GetMaximumSize();
|
| return !max_size.width() && !max_size.height();
|
| }
|
|
|
| bool WindowState::CanMinimize() const {
|
| - return window_->CanMinimize();
|
| + return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
|
| + ui::mojom::kResizeBehaviorCanMinimize) != 0;
|
| }
|
|
|
| bool WindowState::CanResize() const {
|
| - return window_->CanResize();
|
| + return (window_->GetProperty(aura::client::kResizeBehaviorKey) &
|
| + ui::mojom::kResizeBehaviorCanResize) != 0;
|
| }
|
|
|
| bool WindowState::CanActivate() const {
|
| - return window_->CanActivate();
|
| + return ::wm::CanActivateWindow(window_);
|
| }
|
|
|
| bool WindowState::CanSnap() const {
|
| - if (!CanResize() || window_->GetType() == ui::wm::WINDOW_TYPE_PANEL ||
|
| - window_->GetTransientParent()) {
|
| + if (!CanResize() || window_->type() == ui::wm::WINDOW_TYPE_PANEL ||
|
| + ::wm::GetTransientParent(window_)) {
|
| return false;
|
| }
|
| // If a window cannot be maximized, assume it cannot snap either.
|
| @@ -161,27 +207,30 @@ bool WindowState::CanSnap() const {
|
| }
|
|
|
| bool WindowState::HasRestoreBounds() const {
|
| - return window_->HasRestoreBounds();
|
| + return window_->GetProperty(aura::client::kRestoreBoundsKey) != nullptr;
|
| }
|
|
|
| void WindowState::Maximize() {
|
| - window_->Maximize();
|
| + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
|
| }
|
|
|
| void WindowState::Minimize() {
|
| - window_->Minimize();
|
| + window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
|
| }
|
|
|
| void WindowState::Unminimize() {
|
| - window_->Unminimize();
|
| + window_->SetProperty(
|
| + aura::client::kShowStateKey,
|
| + window_->GetProperty(aura::client::kPreMinimizedShowStateKey));
|
| + window_->ClearProperty(aura::client::kPreMinimizedShowStateKey);
|
| }
|
|
|
| void WindowState::Activate() {
|
| - window_->Activate();
|
| + wm::ActivateWindow(window_);
|
| }
|
|
|
| void WindowState::Deactivate() {
|
| - window_->Deactivate();
|
| + wm::DeactivateWindow(window_);
|
| }
|
|
|
| void WindowState::Restore() {
|
| @@ -191,7 +240,7 @@ void WindowState::Restore() {
|
| }
|
| }
|
|
|
| -void WindowState::DisableAlwaysOnTop(WmWindow* window_on_top) {
|
| +void WindowState::DisableAlwaysOnTop(aura::Window* window_on_top) {
|
| if (GetAlwaysOnTop()) {
|
| // |window_| is hidden first to avoid canceling fullscreen mode when it is
|
| // no longer always on top and gets added to default container. This avoids
|
| @@ -201,12 +250,12 @@ void WindowState::DisableAlwaysOnTop(WmWindow* window_on_top) {
|
| bool visible = window_->IsVisible();
|
| if (visible)
|
| window_->Hide();
|
| - window_->SetAlwaysOnTop(false);
|
| + window_->SetProperty(aura::client::kAlwaysOnTopKey, false);
|
| // Technically it is possible that a |window_| could make itself
|
| // always_on_top really quickly. This is probably not a realistic case but
|
| // check if the two windows are in the same container just in case.
|
| - if (window_on_top && window_on_top->GetParent() == window_->GetParent())
|
| - window_->GetParent()->StackChildAbove(window_on_top, window_);
|
| + if (window_on_top && window_on_top->parent() == window_->parent())
|
| + window_->parent()->StackChildAbove(window_on_top, window_);
|
| if (visible)
|
| window_->Show();
|
| cached_always_on_top_ = true;
|
| @@ -218,7 +267,7 @@ void WindowState::RestoreAlwaysOnTop() {
|
| return;
|
| if (cached_always_on_top_) {
|
| cached_always_on_top_ = false;
|
| - window_->SetAlwaysOnTop(true);
|
| + window_->SetProperty(aura::client::kAlwaysOnTopKey, true);
|
| }
|
| }
|
|
|
| @@ -227,30 +276,36 @@ void WindowState::OnWMEvent(const WMEvent* event) {
|
| }
|
|
|
| void WindowState::SaveCurrentBoundsForRestore() {
|
| - gfx::Rect bounds_in_screen =
|
| - window_->GetParent()->ConvertRectToScreen(window_->GetBounds());
|
| + gfx::Rect bounds_in_screen = window_->bounds();
|
| + ::wm::ConvertRectToScreen(window_->parent(), &bounds_in_screen);
|
| SetRestoreBoundsInScreen(bounds_in_screen);
|
| }
|
|
|
| gfx::Rect WindowState::GetRestoreBoundsInScreen() const {
|
| - return window_->GetRestoreBoundsInScreen();
|
| + gfx::Rect* restore_bounds =
|
| + window_->GetProperty(aura::client::kRestoreBoundsKey);
|
| + return restore_bounds ? *restore_bounds : gfx::Rect();
|
| }
|
|
|
| gfx::Rect WindowState::GetRestoreBoundsInParent() const {
|
| - return window_->GetParent()->ConvertRectFromScreen(
|
| - GetRestoreBoundsInScreen());
|
| + gfx::Rect result = GetRestoreBoundsInScreen();
|
| + ::wm::ConvertRectFromScreen(window_->parent(), &result);
|
| + return result;
|
| }
|
|
|
| void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
|
| - window_->SetRestoreBoundsInScreen(bounds);
|
| + window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
|
| }
|
|
|
| void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) {
|
| - SetRestoreBoundsInScreen(window_->GetParent()->ConvertRectToScreen(bounds));
|
| + gfx::Rect bounds_in_screen = bounds;
|
| + ::wm::ConvertRectToScreen(window_->parent(), &bounds_in_screen);
|
| + SetRestoreBoundsInScreen(bounds_in_screen);
|
| }
|
|
|
| void WindowState::ClearRestoreBounds() {
|
| - window_->ClearRestoreBounds();
|
| + window_->ClearProperty(aura::client::kRestoreBoundsKey);
|
| + window_->ClearProperty(::wm::kVirtualKeyboardRestoreBoundsKey);
|
| }
|
|
|
| std::unique_ptr<WindowState::State> WindowState::SetStateObject(
|
| @@ -283,8 +338,8 @@ void WindowState::set_bounds_changed_by_user(bool bounds_changed_by_user) {
|
| void WindowState::CreateDragDetails(const gfx::Point& point_in_parent,
|
| int window_component,
|
| aura::client::WindowMoveSource source) {
|
| - drag_details_.reset(
|
| - new DragDetails(window_, point_in_parent, window_component, source));
|
| + drag_details_ = base::MakeUnique<DragDetails>(window_, point_in_parent,
|
| + window_component, source);
|
| }
|
|
|
| void WindowState::DeleteDragDetails() {
|
| @@ -297,21 +352,7 @@ void WindowState::SetAndClearRestoreBounds() {
|
| ClearRestoreBounds();
|
| }
|
|
|
| -void WindowState::OnWindowShowStateChanged() {
|
| - if (!ignore_property_change_) {
|
| - WMEvent event(WMEventTypeFromShowState(GetShowState()));
|
| - OnWMEvent(&event);
|
| - }
|
| -}
|
| -
|
| -void WindowState::OnWindowPinTypeChanged() {
|
| - if (!ignore_property_change_) {
|
| - WMEvent event(WMEventTypeFromWindowPinType(GetPinType()));
|
| - OnWMEvent(&event);
|
| - }
|
| -}
|
| -
|
| -WindowState::WindowState(WmWindow* window)
|
| +WindowState::WindowState(aura::Window* window)
|
| : window_(window),
|
| window_position_managed_(false),
|
| bounds_changed_by_user_(false),
|
| @@ -325,23 +366,25 @@ WindowState::WindowState(WmWindow* window)
|
| can_be_dragged_(true),
|
| cached_always_on_top_(false),
|
| ignore_property_change_(false),
|
| - current_state_(new DefaultState(ToWindowStateType(GetShowState()))) {}
|
| + current_state_(new DefaultState(ToWindowStateType(GetShowState()))) {
|
| + window_->AddObserver(this);
|
| +}
|
|
|
| bool WindowState::GetAlwaysOnTop() const {
|
| - return window_->IsAlwaysOnTop();
|
| + return window_->GetProperty(aura::client::kAlwaysOnTopKey);
|
| }
|
|
|
| ui::WindowShowState WindowState::GetShowState() const {
|
| - return window_->GetShowState();
|
| + return window_->GetProperty(aura::client::kShowStateKey);
|
| }
|
|
|
| ash::mojom::WindowPinType WindowState::GetPinType() const {
|
| - return window_->aura_window()->GetProperty(kWindowPinTypeKey);
|
| + return window_->GetProperty(kWindowPinTypeKey);
|
| }
|
|
|
| void WindowState::SetBoundsInScreen(const gfx::Rect& bounds_in_screen) {
|
| - gfx::Rect bounds_in_parent =
|
| - window_->GetParent()->ConvertRectFromScreen(bounds_in_screen);
|
| + gfx::Rect bounds_in_parent = bounds_in_screen;
|
| + ::wm::ConvertRectFromScreen(window_->parent(), &bounds_in_parent);
|
| window_->SetBounds(bounds_in_parent);
|
| }
|
|
|
| @@ -349,7 +392,7 @@ void WindowState::AdjustSnappedBounds(gfx::Rect* bounds) {
|
| if (is_dragged() || !IsSnapped())
|
| return;
|
| gfx::Rect maximized_bounds =
|
| - ScreenUtil::GetMaximizedWindowBoundsInParent(window_->aura_window());
|
| + ScreenUtil::GetMaximizedWindowBoundsInParent(window_);
|
| if (GetStateType() == WINDOW_STATE_TYPE_LEFT_SNAPPED)
|
| bounds->set_x(maximized_bounds.x());
|
| else if (GetStateType() == WINDOW_STATE_TYPE_RIGHT_SNAPPED)
|
| @@ -363,7 +406,7 @@ void WindowState::UpdateWindowPropertiesFromStateType() {
|
| ToWindowShowState(current_state_->GetType());
|
| if (new_window_state != GetShowState()) {
|
| base::AutoReset<bool> resetter(&ignore_property_change_, true);
|
| - window_->SetShowState(new_window_state);
|
| + window_->SetProperty(aura::client::kShowStateKey, new_window_state);
|
| }
|
|
|
| // sync up current window show state with PinType property.
|
| @@ -374,7 +417,7 @@ void WindowState::UpdateWindowPropertiesFromStateType() {
|
| pin_type = ash::mojom::WindowPinType::TRUSTED_PINNED;
|
| if (pin_type != GetPinType()) {
|
| base::AutoReset<bool> resetter(&ignore_property_change_, true);
|
| - window_->aura_window()->SetProperty(kWindowPinTypeKey, pin_type);
|
| + window_->SetProperty(kWindowPinTypeKey, pin_type);
|
| }
|
| }
|
|
|
| @@ -394,41 +437,77 @@ void WindowState::SetBoundsDirect(const gfx::Rect& bounds) {
|
| gfx::Rect actual_new_bounds(bounds);
|
| // Ensure we don't go smaller than our minimum bounds in "normal" window
|
| // modes
|
| - if (window_->HasNonClientArea() && !IsMaximized() && !IsFullscreen()) {
|
| + if (window_->delegate() && !IsMaximized() && !IsFullscreen()) {
|
| // Get the minimum usable size of the minimum size and the screen size.
|
| - gfx::Size min_size = window_->GetMinimumSize();
|
| - min_size.SetToMin(window_->GetDisplayNearestWindow().work_area().size());
|
| + gfx::Size min_size = window_->delegate()
|
| + ? window_->delegate()->GetMinimumSize()
|
| + : gfx::Size();
|
| + const display::Display display =
|
| + display::Screen::GetScreen()->GetDisplayNearestWindow(window_);
|
| + min_size.SetToMin(display.work_area().size());
|
|
|
| actual_new_bounds.set_width(
|
| std::max(min_size.width(), actual_new_bounds.width()));
|
| actual_new_bounds.set_height(
|
| std::max(min_size.height(), actual_new_bounds.height()));
|
| }
|
| - window_->SetBoundsDirect(actual_new_bounds);
|
| + BoundsSetter().SetBounds(window_, actual_new_bounds);
|
| + wm::SnapWindowToPixelBoundary(window_);
|
| }
|
|
|
| void WindowState::SetBoundsConstrained(const gfx::Rect& bounds) {
|
| gfx::Rect work_area_in_parent =
|
| - ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_->aura_window());
|
| + ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_);
|
| gfx::Rect child_bounds(bounds);
|
| AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds);
|
| SetBoundsDirect(child_bounds);
|
| }
|
|
|
| void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds) {
|
| - window_->SetBoundsDirectAnimated(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 WindowState::SetBoundsDirectCrossFade(const gfx::Rect& new_bounds) {
|
| // Some test results in invoking CrossFadeToBounds when window is not visible.
|
| // No animation is necessary in that case, thus just change the bounds and
|
| // quit.
|
| - if (!window_->GetTargetVisibility()) {
|
| + if (!window_->TargetVisibility()) {
|
| SetBoundsConstrained(new_bounds);
|
| return;
|
| }
|
|
|
| - window_->SetBoundsDirectCrossFade(new_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(new_bounds);
|
| +
|
| + // Ensure the higher-resolution layer is on top.
|
| + bool old_on_top = (old_bounds.width() > new_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);
|
| }
|
|
|
| WindowState* GetActiveWindowState() {
|
| @@ -441,7 +520,7 @@ WindowState* GetWindowState(aura::Window* window) {
|
| return nullptr;
|
| WindowState* settings = window->GetProperty(kWindowStateKey);
|
| if (!settings) {
|
| - settings = new WindowState(WmWindow::Get(window));
|
| + settings = new WindowState(window);
|
| window->SetProperty(kWindowStateKey, settings);
|
| }
|
| return settings;
|
| @@ -451,5 +530,29 @@ const WindowState* GetWindowState(const aura::Window* window) {
|
| return GetWindowState(const_cast<aura::Window*>(window));
|
| }
|
|
|
| +void WindowState::OnWindowPropertyChanged(aura::Window* window,
|
| + const void* key,
|
| + intptr_t old) {
|
| + if (key == aura::client::kShowStateKey) {
|
| + if (!ignore_property_change_) {
|
| + WMEvent event(WMEventTypeFromShowState(GetShowState()));
|
| + OnWMEvent(&event);
|
| + }
|
| + return;
|
| + }
|
| + if (key == aura::client::kImmersiveFullscreenKey) {
|
| + in_immersive_fullscreen_ =
|
| + window_->GetProperty(aura::client::kImmersiveFullscreenKey);
|
| + return;
|
| + }
|
| + if (key == kWindowPinTypeKey) {
|
| + if (!ignore_property_change_) {
|
| + WMEvent event(WMEventTypeFromWindowPinType(GetPinType()));
|
| + OnWMEvent(&event);
|
| + }
|
| + return;
|
| + }
|
| +}
|
| +
|
| } // namespace wm
|
| } // namespace ash
|
|
|