diff options
Diffstat (limited to 'ash/wm/window_state.cc')
-rw-r--r-- | ash/wm/window_state.cc | 134 |
1 files changed, 104 insertions, 30 deletions
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index 81f23fe..db9a321 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc @@ -17,14 +17,66 @@ #include "base/auto_reset.h" #include "base/command_line.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/scoped_layer_animation_settings.h" #include "ui/gfx/display.h" #include "ui/views/corewm/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() {} + virtual ~BoundsSetter() {} + + // aura::LayoutManager overrides: + virtual void OnWindowResized() OVERRIDE {} + virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {} + virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} + virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {} + virtual void OnChildWindowVisibilityChanged( + aura::Window* child, bool visible) OVERRIDE {} + virtual 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); +}; + +WMEvent WMEventFromShowState(ui::WindowShowState requested_show_state) { + switch (requested_show_state) { + case ui::SHOW_STATE_DEFAULT: + case ui::SHOW_STATE_NORMAL: + return NORMAL; + case ui::SHOW_STATE_MINIMIZED: + return MINIMIZE; + case ui::SHOW_STATE_MAXIMIZED: + return MAXIMIZE; + case ui::SHOW_STATE_FULLSCREEN: + return FULLSCREEN; + case ui::SHOW_STATE_INACTIVE: + case ui::SHOW_STATE_DETACHED: + case ui::SHOW_STATE_END: + NOTREACHED() << "No WMEvent defined for the show type:" + << requested_show_state; + } + return NORMAL; +} + +} // namespace + WindowState::WindowState(aura::Window* window) : window_(window), window_position_managed_(false), @@ -38,11 +90,10 @@ WindowState::WindowState(aura::Window* window) hide_shelf_when_fullscreen_(true), animate_to_fullscreen_(true), minimum_visibility_(false), - in_set_window_show_type_(false), + ignore_property_change_(false), window_show_type_(ToWindowShowType(GetShowState())), current_state_(new DefaultState) { window_->AddObserver(this); - #if defined(OS_CHROMEOS) // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When // switches::UseImmersiveFullscreenForAllWindows() returns true, most windows @@ -182,23 +233,11 @@ void WindowState::Deactivate() { void WindowState::Restore() { if (!IsNormalShowType()) - SetWindowShowType(SHOW_TYPE_NORMAL); + OnWMEvent(NORMAL); } void WindowState::ToggleFullscreen() { - // Window which cannot be maximized should not be fullscreened. - // It can, however, be restored if it was fullscreened. - bool is_fullscreen = IsFullscreen(); - if (!is_fullscreen && !CanMaximize()) - return; - if (delegate_ && delegate_->ToggleFullscreen(this)) - return; - if (is_fullscreen) { - Restore(); - } else { - window_->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - } + OnWMEvent(TOGGLE_FULLSCREEN); } void WindowState::OnWMEvent(WMEvent event) { @@ -273,12 +312,25 @@ void WindowState::SetAndClearRestoreBounds() { ClearRestoreBounds(); } +void WindowState::AdjustSnappedBounds(gfx::Rect* bounds) { + if (is_dragged() || !IsSnapped()) + return; + gfx::Rect maximized_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent( + window_); + if (window_show_type() == SHOW_TYPE_LEFT_SNAPPED) + bounds->set_x(maximized_bounds.x()); + else if (window_show_type() == SHOW_TYPE_RIGHT_SNAPPED) + bounds->set_x(maximized_bounds.right() - bounds->width()); + bounds->set_y(maximized_bounds.y()); + bounds->set_height(maximized_bounds.height()); +} + void WindowState::OnWindowPropertyChanged(aura::Window* window, const void* key, intptr_t old) { DCHECK_EQ(window, window_); - if (key == aura::client::kShowStateKey) - SetWindowShowType(ToWindowShowType(GetShowState())); + if (key == aura::client::kShowStateKey && !ignore_property_change_) + OnWMEvent(WMEventFromShowState(GetShowState())); } void WindowState::SnapWindow(WindowShowType left_or_right, @@ -299,7 +351,9 @@ void WindowState::SnapWindow(WindowShowType left_or_right, DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || left_or_right == SHOW_TYPE_RIGHT_SNAPPED); - SetWindowShowType(left_or_right); + OnWMEvent(left_or_right == SHOW_TYPE_LEFT_SNAPPED ? + SNAP_LEFT : SNAP_RIGHT); + // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon // observing the WindowShowType change. // If the window is a child of kShellWindowId_DockedContainer such as during @@ -312,21 +366,41 @@ void WindowState::SnapWindow(WindowShowType left_or_right, SetRestoreBoundsInScreen(restore_bounds_in_screen); } -void WindowState::SetWindowShowType(WindowShowType new_window_show_type) { - if (in_set_window_show_type_) - return; - base::AutoReset<bool> resetter(&in_set_window_show_type_, true); - +void WindowState::UpdateWindowShowType(WindowShowType new_window_show_type) { ui::WindowShowState new_window_state = ToWindowShowState(new_window_show_type); - if (new_window_state != GetShowState()) + if (new_window_state != GetShowState()) { + base::AutoReset<bool> resetter(&ignore_property_change_, true); window_->SetProperty(aura::client::kShowStateKey, new_window_state); - WindowShowType old_window_show_type = window_show_type_; - window_show_type_ = new_window_show_type; - if (old_window_show_type != window_show_type_) { - FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, - OnWindowShowTypeChanged(this, old_window_show_type)); } + window_show_type_ = new_window_show_type; +} + +void WindowState::NotifyPreShowTypeChange(WindowShowType old_window_show_type) { + FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, + OnPreWindowShowTypeChange(this, old_window_show_type)); +} + +void WindowState::NotifyPostShowTypeChange( + WindowShowType old_window_show_type) { + FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, + OnPostWindowShowTypeChange(this, old_window_show_type)); +} + +void WindowState::SetBoundsDirect(const gfx::Rect& bounds) { + BoundsSetter().SetBounds(window_, bounds); +} + +void WindowState::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); } WindowState* GetActiveWindowState() { |