168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_state.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/ash_switches.h"
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/root_window_controller.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/screen_util.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/shell_window_ids.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/default_state.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/window_animations.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_properties.h"
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ash/wm/window_state_delegate.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_state_observer.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_util.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/wm_event.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/auto_reset.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/layout_manager.h"
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window.h"
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window_delegate.h"
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer_tree_owner.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/display.h"
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/screen.h"
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace ash {
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace wm {
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A tentative class to set the bounds on the window.
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(oshima): Once all logic is cleaned up, move this to the real layout
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// manager with proper friendship.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BoundsSetter : public aura::LayoutManager {
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BoundsSetter() {}
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~BoundsSetter() {}
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // aura::LayoutManager overrides:
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWindowResized() OVERRIDE {}
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {}
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnChildWindowVisibilityChanged(
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      aura::Window* child, bool visible) OVERRIDE {}
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetChildBounds(
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE {}
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetBounds(aura::Window* window, const gfx::Rect& bounds) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetChildBoundsDirect(window, bounds);
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BoundsSetter);
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WMEventType WMEventTypeFromShowState(ui::WindowShowState requested_show_state) {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (requested_show_state) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_DEFAULT:
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_NORMAL:
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return WM_EVENT_NORMAL;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_MINIMIZED:
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return WM_EVENT_MINIMIZE;
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_MAXIMIZED:
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return WM_EVENT_MAXIMIZE;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_FULLSCREEN:
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return WM_EVENT_FULLSCREEN;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_INACTIVE:
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return WM_EVENT_SHOW_INACTIVE;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case ui::SHOW_STATE_END:
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED() << "No WMEvent defined for the show state:"
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   << requested_show_state;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return WM_EVENT_NORMAL;
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState::~WindowState() {
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // WindowState is registered as an owned property of |window_|, and window
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // unregisters all of its observers in its d'tor before destroying its
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // properties. As a result, window_->RemoveObserver() doesn't need to (and
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // shouldn't) be called here.
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool WindowState::HasDelegate() const {
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return delegate_;
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) {
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!delegate_.get());
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_ = delegate.Pass();
971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WindowStateType WindowState::GetStateType() const {
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return current_state_->GetType();
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMinimized() const {
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_MINIMIZED;
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximized() const {
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_MAXIMIZED;
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsFullscreen() const {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_FULLSCREEN;
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximizedOrFullscreen() const {
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_FULLSCREEN ||
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetStateType() == WINDOW_STATE_TYPE_MAXIMIZED;
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool WindowState::IsSnapped() const {
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_LEFT_SNAPPED ||
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetStateType() == WINDOW_STATE_TYPE_RIGHT_SNAPPED;
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool WindowState::IsNormalStateType() const {
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetStateType() == WINDOW_STATE_TYPE_NORMAL ||
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetStateType() == WINDOW_STATE_TYPE_DEFAULT;
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool WindowState::IsNormalOrSnapped() const {
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return IsNormalStateType() || IsSnapped();
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsActive() const {
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsActiveWindow(window_);
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool WindowState::IsDocked() const {
1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return window_->parent() &&
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         window_->parent()->id() == kShellWindowId_DockedContainer;
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMaximize() const {
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Window must have the kCanMaximizeKey and have no maximum width or height.
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!window()->GetProperty(aura::client::kCanMaximizeKey))
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!window()->delegate())
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size max_size = window_->delegate()->GetMaximumSize();
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return !max_size.width() && !max_size.height();
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMinimize() const {
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RootWindowController* controller = RootWindowController::ForWindow(window_);
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!controller)
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  aura::Window* lockscreen =
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      controller->GetContainer(kShellWindowId_LockScreenContainersContainer);
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (lockscreen->Contains(window_))
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanResize() const {
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kCanResizeKey);
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanActivate() const {
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return ::wm::CanActivateWindow(window_);
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanSnap() const {
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!CanResize() || window_->type() == ui::wm::WINDOW_TYPE_PANEL ||
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ::wm::GetTransientParent(window_))
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If a window cannot be maximized, assume it cannot snap either.
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(oshima): We should probably snap if the maximum size is greater than
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the snapped size.
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return CanMaximize();
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::HasRestoreBounds() const {
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL;
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Maximize() {
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Minimize() {
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Unminimize() {
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      aura::client::kShowStateKey,
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      window_->GetProperty(aura::client::kRestoreShowStateKey));
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreShowStateKey);
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Activate() {
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ActivateWindow(window_);
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Deactivate() {
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DeactivateWindow(window_);
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Restore() {
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!IsNormalStateType()) {
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const WMEvent event(WM_EVENT_NORMAL);
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OnWMEvent(&event);
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::OnWMEvent(const WMEvent* event) {
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  current_state_->OnWMEvent(this, event);
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SaveCurrentBoundsForRestore() {
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_screen =
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScreenUtil::ConvertRectToScreen(window_->parent(),
22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                      window_->bounds());
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(bounds_in_screen);
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInScreen() const {
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return *window_->GetProperty(aura::client::kRestoreBoundsKey);
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInParent() const {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ScreenUtil::ConvertRectFromScreen(window_->parent(),
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                          GetRestoreBoundsInScreen());
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) {
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScreenUtil::ConvertRectToScreen(window_->parent(), bounds));
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::ClearRestoreBounds() {
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreBoundsKey);
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)scoped_ptr<WindowState::State> WindowState::SetStateObject(
25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    scoped_ptr<WindowState::State> new_state) {
25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_state_->DetachState(this);
25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<WindowState::State> old_object = current_state_.Pass();
25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_state_ = new_state.Pass();
25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_state_->AttachState(this, old_object.get());
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return old_object.Pass();
25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetPreAutoManageWindowBounds(
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const gfx::Rect& bounds) {
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds));
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::AddObserver(WindowStateObserver* observer) {
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.AddObserver(observer);
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::RemoveObserver(WindowStateObserver* observer) {
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid WindowState::set_bounds_changed_by_user(bool bounds_changed_by_user) {
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bounds_changed_by_user_ = bounds_changed_by_user;
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (bounds_changed_by_user)
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    pre_auto_manage_window_bounds_.reset();
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::CreateDragDetails(aura::Window* window,
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const gfx::Point& point_in_parent,
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int window_component,
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    aura::client::WindowMoveSource source) {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_details_.reset(
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new DragDetails(window, point_in_parent, window_component, source));
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::DeleteDragDetails() {
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  drag_details_.reset();
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::SetAndClearRestoreBounds() {
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(HasRestoreBounds());
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBoundsInScreen(GetRestoreBoundsInScreen());
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ClearRestoreBounds();
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::OnWindowPropertyChanged(aura::Window* window,
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const void* key,
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          intptr_t old) {
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(window, window_);
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (key == aura::client::kShowStateKey && !ignore_property_change_) {
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WMEvent event(WMEventTypeFromShowState(GetShowState()));
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OnWMEvent(&event);
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)WindowState::WindowState(aura::Window* window)
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : window_(window),
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      window_position_managed_(false),
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      bounds_changed_by_user_(false),
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      panel_attached_(true),
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ignored_by_shelf_(false),
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      can_consume_system_keys_(false),
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      top_row_keys_are_function_keys_(false),
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      unminimize_to_restore_bounds_(false),
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      in_immersive_fullscreen_(false),
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      hide_shelf_when_fullscreen_(true),
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      minimum_visibility_(false),
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      can_be_dragged_(true),
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ignore_property_change_(false),
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      current_state_(new DefaultState(ToWindowStateType(GetShowState()))) {
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  window_->AddObserver(this);
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)ui::WindowShowState WindowState::GetShowState() const {
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return window_->GetProperty(aura::client::kShowStateKey);
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::SetBoundsInScreen(
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Rect& bounds_in_screen) {
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect bounds_in_parent =
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ScreenUtil::ConvertRectFromScreen(window_->parent(),
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                       bounds_in_screen);
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_->SetBounds(bounds_in_parent);
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::AdjustSnappedBounds(gfx::Rect* bounds) {
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_dragged() || !IsSnapped())
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect maximized_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent(
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_);
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (GetStateType() == WINDOW_STATE_TYPE_LEFT_SNAPPED)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bounds->set_x(maximized_bounds.x());
345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else if (GetStateType() == WINDOW_STATE_TYPE_RIGHT_SNAPPED)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bounds->set_x(maximized_bounds.right() - bounds->width());
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds->set_y(maximized_bounds.y());
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds->set_height(maximized_bounds.height());
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::UpdateWindowShowStateFromStateType() {
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::WindowShowState new_window_state =
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ToWindowShowState(current_state_->GetType());
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (new_window_state != GetShowState()) {
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::AutoReset<bool> resetter(&ignore_property_change_, true);
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window_->SetProperty(aura::client::kShowStateKey, new_window_state);
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::NotifyPreStateTypeChange(
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WindowStateType old_window_state_type) {
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    OnPreWindowStateTypeChange(this, old_window_state_type));
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::NotifyPostStateTypeChange(
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WindowStateType old_window_state_type) {
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    OnPostWindowStateTypeChange(this, old_window_state_type));
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::SetBoundsDirect(const gfx::Rect& bounds) {
3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect actual_new_bounds(bounds);
3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Ensure we don't go smaller than our minimum bounds in "normal" window
3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // modes
3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (window_->delegate() && !IsMaximized() && !IsFullscreen()) {
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Get the minimum usable size of the minimum size and the screen size.
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    gfx::Size min_size = window_->delegate()->GetMinimumSize();
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    min_size.SetToMin(gfx::Screen::GetScreenFor(
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        window_)->GetDisplayNearestWindow(window_).work_area().size());
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    actual_new_bounds.set_width(
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        std::max(min_size.width(), actual_new_bounds.width()));
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    actual_new_bounds.set_height(
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        std::max(min_size.height(), actual_new_bounds.height()));
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BoundsSetter().SetBounds(window_, actual_new_bounds);
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SnapWindowToPixelBoundary(window_);
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::SetBoundsConstrained(const gfx::Rect& bounds) {
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect work_area_in_parent =
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_);
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect child_bounds(bounds);
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds);
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetBoundsDirect(child_bounds);
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds) {
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kBoundsChangeSlideDurationMs = 120;
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::Layer* layer = window_->layer();
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  slide_settings.SetPreemptionStrategy(
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  slide_settings.SetTransitionDuration(
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs));
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBoundsDirect(bounds);
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WindowState::SetBoundsDirectCrossFade(const gfx::Rect& new_bounds) {
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Some test results in invoking CrossFadeToBounds when window is not visible.
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // No animation is necessary in that case, thus just change the bounds and
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // quit.
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!window_->TargetVisibility()) {
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SetBoundsConstrained(new_bounds);
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect old_bounds = window_->bounds();
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Create fresh layers for the window and all its children to paint into.
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Takes ownership of the old layer and all its children, which will be
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // cleaned up after the animation completes.
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Specify |set_bounds| to true here to keep the old bounds in the child
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // windows of |window|.
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<ui::LayerTreeOwner> old_layer_owner =
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ::wm::RecreateLayers(window_);
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::Layer* old_layer = old_layer_owner->root();
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(old_layer);
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ui::Layer* new_layer = window_->layer();
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Resize the window to the new size, which will force a layout and paint.
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SetBoundsDirect(new_bounds);
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Ensure the higher-resolution layer is on top.
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool old_on_top = (old_bounds.width() > new_bounds.width());
438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (old_on_top)
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    old_layer->parent()->StackBelow(new_layer, old_layer);
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    old_layer->parent()->StackAbove(new_layer, old_layer);
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  CrossFadeAnimation(window_, old_layer_owner.Pass(), gfx::Tween::EASE_OUT);
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetActiveWindowState() {
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* active = GetActiveWindow();
44868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return active ? GetWindowState(active) : NULL;
44968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
45068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
45168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetWindowState(aura::Window* window) {
45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!window)
45368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
454c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WindowState* settings = window->GetProperty(kWindowStateKey);
45568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if(!settings) {
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    settings = new WindowState(window);
457c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    window->SetProperty(kWindowStateKey, settings);
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return settings;
46068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
46168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const WindowState* GetWindowState(const aura::Window* window) {
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetWindowState(const_cast<aura::Window*>(window));
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace wm
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace ash
468