Chromium Code Reviews| 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 |
|
sky
2017/05/23 00:13:27
This comment comes from before I created WmWindow.
msw
2017/05/23 05:46:55
Acknowledged.
|
| + // 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 |