123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file.
423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/maximize_mode/maximize_mode_window_state.h"
623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/display/display_controller.h"
823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/screen_util.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/shell.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/shell_window_ids.h"
1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/window_animations.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ash/wm/window_properties.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/window_state_delegate.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/wm/window_state_util.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/window_util.h"
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/wm_event.h"
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ash/wm/workspace/workspace_window_resizer.h"
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/client/aura_constants.h"
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window.h"
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_delegate.h"
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/gfx/display.h"
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/gfx/rect.h"
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/view_constants_aura.h"
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/widget/widget.h"
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace ash {
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace {
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Returns the biggest possible size for a window which is about to be
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// maximized.
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)gfx::Size GetMaximumSizeOfWindow(wm::WindowState* window_state) {
34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(window_state->CanMaximize() || window_state->CanResize());
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gfx::Size workspace_size = ScreenUtil::GetMaximizedWindowBoundsInParent(
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      window_state->window()).size();
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  aura::WindowDelegate* delegate = window_state->window()->delegate();
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!delegate)
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return workspace_size;
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gfx::Size size = delegate->GetMaximumSize();
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (size.IsEmpty())
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return workspace_size;
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size.SetToMin(workspace_size);
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return size;
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Returns the centered bounds of the given bounds in the work area.
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liugfx::Rect GetCenteredBounds(const gfx::Rect& bounds_in_parent,
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            wm::WindowState* state_object) {
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect work_area_in_parent =
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ScreenUtil::GetDisplayWorkAreaBoundsInParent(state_object->window());
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  work_area_in_parent.ClampToCenteredSize(bounds_in_parent.size());
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return work_area_in_parent;
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Returns the maximized/full screen and/or centered bounds of a window.
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liugfx::Rect GetBoundsInMaximizedMode(wm::WindowState* state_object) {
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (state_object->IsFullscreen())
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return ScreenUtil::GetDisplayBoundsInParent(state_object->window());
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gfx::Rect bounds_in_parent;
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Make the window as big as possible.
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (state_object->CanMaximize() || state_object->CanResize()) {
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    bounds_in_parent.set_size(GetMaximumSizeOfWindow(state_object));
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else {
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // We prefer the user given window dimensions over the current windows
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // dimensions since they are likely to be the result from some other state
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // object logic.
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (state_object->HasRestoreBounds())
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      bounds_in_parent = state_object->GetRestoreBoundsInParent();
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    else
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      bounds_in_parent = state_object->window()->bounds();
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return GetCenteredBounds(bounds_in_parent, state_object);
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void MaximizeModeWindowState::UpdateWindowPosition(
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    wm::WindowState* window_state, bool animated) {
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (bounds_in_parent == window_state->window()->bounds())
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (animated)
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window_state->SetBoundsDirect(bounds_in_parent);
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  else
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window_state->SetBoundsDirectAnimated(bounds_in_parent);
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)MaximizeModeWindowState::MaximizeModeWindowState(
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    aura::Window* window, MaximizeModeWindowManager* creator)
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : window_(window),
10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      creator_(creator),
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      current_state_type_(wm::GetWindowState(window)->GetStateType()) {
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  old_state_.reset(
10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      wm::GetWindowState(window)->SetStateObject(
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          scoped_ptr<State>(this).Pass()).release());
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)MaximizeModeWindowState::~MaximizeModeWindowState() {
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  creator_->WindowStateDestroyed(window_);
10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void MaximizeModeWindowState::LeaveMaximizeMode(wm::WindowState* window_state) {
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Note: When we return we will destroy ourselves with the |our_reference|.
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<wm::WindowState::State> our_reference =
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      window_state->SetStateObject(old_state_.Pass());
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void MaximizeModeWindowState::OnWMEvent(wm::WindowState* window_state,
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                        const wm::WMEvent* event) {
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  switch (event->type()) {
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case wm::WM_EVENT_TOGGLE_FULLSCREEN:
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ToggleFullScreen(window_state, window_state->delegate());
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      break;
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    case wm::WM_EVENT_FULLSCREEN:
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN, true);
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      break;
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_TOGGLE_MAXIMIZE:
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_CENTER:
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_SNAP_LEFT:
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_SNAP_RIGHT:
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_NORMAL:
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_MAXIMIZE:
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      UpdateWindow(window_state,
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   GetMaximizedOrCenteredWindowType(window_state),
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                   true);
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return;
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_MINIMIZE:
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED, true);
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return;
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_SHOW_INACTIVE:
14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      return;
14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_SET_BOUNDS:
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (current_state_type_ == wm::WINDOW_STATE_TYPE_MAXIMIZED) {
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // Having a maximized window, it could have been created with an empty
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // size and the caller should get his size upon leaving the maximized
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        // mode. As such we set the restore bounds to the requested bounds.
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        gfx::Rect bounds_in_parent =
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)            (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        if (!bounds_in_parent.IsEmpty())
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          window_state->SetRestoreBoundsInParent(bounds_in_parent);
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      } else if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // In all other cases (except for minimized windows) we respect the
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        // requested bounds and center it to a fully visible area on the screen.
15823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        gfx::Rect bounds_in_parent =
15923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        bounds_in_parent = GetCenteredBounds(bounds_in_parent, window_state);
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (bounds_in_parent != window_state->window()->bounds()) {
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          if (window_state->window()->IsVisible())
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            window_state->SetBoundsDirectAnimated(bounds_in_parent);
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          else
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            window_state->SetBoundsDirect(bounds_in_parent);
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        }
16723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      }
16823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
16923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_ADDED_TO_WORKSPACE:
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED) {
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        wm::WindowStateType new_state =
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            GetMaximizedOrCenteredWindowType(window_state);
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        UpdateWindow(window_state, new_state, true);
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
17723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
17823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
17923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        UpdateBounds(window_state, true);
18123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      break;
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Don't animate on a screen rotation - just snap to new size.
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        UpdateBounds(window_state, false);
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)wm::WindowStateType MaximizeModeWindowState::GetType() const {
19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return current_state_type_;
19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void MaximizeModeWindowState::AttachState(
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    wm::WindowState* window_state,
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    wm::WindowState::State* previous_state) {
19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  current_state_type_ = previous_state->GetType();
19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  views::Widget* widget =
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      views::Widget::GetWidgetForNativeWindow(window_state->window());
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (widget) {
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    gfx::Rect bounds = widget->GetRestoredBounds();
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!bounds.IsEmpty()) {
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // We do not want to do a session restore to our window states. Therefore
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // we tell the window to use the current default states instead.
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      window_state->window()->SetProperty(ash::kRestoreShowStateOverrideKey,
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          window_state->GetShowState());
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      window_state->window()->SetProperty(ash::kRestoreBoundsOverrideKey,
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          new gfx::Rect(widget->GetRestoredBounds()));
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
21323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Initialize the state to a good preset.
21423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    UpdateWindow(window_state,
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 GetMaximizedOrCenteredWindowType(window_state),
2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 true);
22023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_state->set_can_be_dragged(false);
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void MaximizeModeWindowState::DetachState(wm::WindowState* window_state) {
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // From now on, we can use the default session restore mechanism again.
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  window_state->window()->ClearProperty(ash::kRestoreBoundsOverrideKey);
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_state->set_can_be_dragged(true);
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid MaximizeModeWindowState::UpdateWindow(wm::WindowState* window_state,
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                           wm::WindowStateType target_state,
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                           bool animated) {
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              !window_state->CanMaximize()) ||
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
24323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    current_state_type_ = target_state;
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ::wm::SetWindowVisibilityAnimationType(
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    window_state->window()->Hide();
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (window_state->IsActive())
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      window_state->Deactivate();
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (current_state_type_ == target_state) {
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If the state type did not change, update it accordingly.
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    UpdateBounds(window_state, animated);
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const wm::WindowStateType old_state_type = current_state_type_;
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  current_state_type_ = target_state;
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window_state->UpdateWindowShowStateFromStateType();
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window_state->NotifyPreStateTypeChange(old_state_type);
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UpdateBounds(window_state, animated);
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  window_state->NotifyPostStateTypeChange(old_state_type);
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if ((window_state->window()->TargetVisibility() ||
26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
26823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      !window_state->window()->layer()->visible()) {
26923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // The layer may be hidden if the window was previously minimized. Make
27023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // sure it's visible.
27123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    window_state->window()->Show();
27223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
27323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
27423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuwm::WindowStateType MaximizeModeWindowState::GetMaximizedOrCenteredWindowType(
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      wm::WindowState* window_state) {
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                       wm::WINDOW_STATE_TYPE_NORMAL;
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid MaximizeModeWindowState::UpdateBounds(wm::WindowState* window_state,
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                           bool animated) {
2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If we have a target bounds rectangle, we center it and set it
2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // accordingly.
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!bounds_in_parent.IsEmpty() &&
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bounds_in_parent != window_state->window()->bounds()) {
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED ||
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        !window_state->window()->IsVisible() ||
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        !animated) {
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      window_state->SetBoundsDirect(bounds_in_parent);
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
293010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // If we animate (to) maximized mode, we want to use the cross fade to
294010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      // avoid flashing.
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (window_state->IsMaximized())
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        window_state->SetBoundsDirectCrossFade(bounds_in_parent);
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      else
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        window_state->SetBoundsDirectAnimated(bounds_in_parent);
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
301c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
302c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
30323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace ash
304