default_state.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/default_state.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/display_controller.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ash/screen_util.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_window_ids.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/wm/window_animations.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/wm/window_state.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_state_delegate.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/window_util.h"
16a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "ash/wm/wm_event.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/workspace/workspace_window_resizer.h"
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/window.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/aura/window_delegate.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/display.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/rect.h"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace wm {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This specifies how much percent (30%) of a window rect
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// must be visible when the window is added to the workspace.
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst float kMinimumPercentOnScreenArea = 0.3f;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsPanel(aura::Window* window) {
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return window->parent() &&
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      window->parent()->id() == internal::kShellWindowId_DockedContainer;
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void MoveToDisplayForRestore(WindowState* window_state) {
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!window_state->HasRestoreBounds())
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen();
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Move only if the restore bounds is outside of
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // the display. There is no information about in which
44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // display it should be restored, so this is best guess.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(oshima): Restore information should contain the
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // work area information like WindowResizer does for the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // last window location.
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Rect display_area = Shell::GetScreen()->GetDisplayNearestWindow(
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_state->window()).bounds();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!display_area.Intersects(restore_bounds)) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Display& display =
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Shell::GetScreen()->GetDisplayMatching(restore_bounds);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DisplayController* display_controller =
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Shell::GetInstance()->display_controller();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aura::Window* new_root =
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        display_controller->GetRootWindowForDisplayId(display.id());
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (new_root != window_state->window()->GetRootWindow()) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aura::Window* new_container =
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Shell::GetContainer(new_root, window_state->window()->parent()->id());
61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new_container->AddChild(window_state->window());
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace;
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
68116680a4aac90f2aa7413d9095a592090648e557Ben MurdochDefaultState::DefaultState(WindowStateType initial_state_type)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : state_type_(initial_state_type) {}
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)DefaultState::~DefaultState() {}
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void DefaultState::OnWMEvent(WindowState* window_state,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const WMEvent* event) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ProcessWorkspaceEvents(window_state, event))
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (ProcessCompoundEvents(window_state, event))
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WindowStateType next_state_type = WINDOW_STATE_TYPE_NORMAL;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  switch (event->type()) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_EVENT_NORMAL:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_NORMAL;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_EVENT_MAXIMIZE:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_MAXIMIZED;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_MINIMIZE:
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_MINIMIZED;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_FULLSCREEN:
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_FULLSCREEN;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_SNAP_LEFT:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_LEFT_SNAPPED;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_SNAP_RIGHT:
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_state_type = WINDOW_STATE_TYPE_RIGHT_SNAPPED;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
100a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    case WM_EVENT_SET_BOUNDS:
101a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      SetBounds(window_state, static_cast<const SetBoundsEvent*>(event));
102a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return;
103a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    case WM_EVENT_SHOW_INACTIVE:
104a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      next_state_type = WINDOW_STATE_TYPE_INACTIVE;
105a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      break;
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE:
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_TOGGLE_FULLSCREEN:
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED() << "Compound event should not reach here:" << event;
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_ADDED_TO_WORKSPACE:
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_WORKAREA_BOUNDS_CHANGED:
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WM_EVENT_DISPLAY_BOUNDS_CHANGED:
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED() << "Workspace event should not reach here:" << event;
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WindowStateType current = window_state->GetStateType();
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (next_state_type == current && window_state->IsSnapped()) {
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::Rect snapped_bounds = event->type() == WM_EVENT_SNAP_LEFT ?
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        GetDefaultLeftSnappedWindowBoundsInParent(window_state->window()) :
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetDefaultRightSnappedWindowBoundsInParent(window_state->window());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_state->SetBoundsDirectAnimated(snapped_bounds);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current != next_state_type) {
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    state_type_ = next_state_type;
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    window_state->UpdateWindowShowStateFromStateType();
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    window_state->NotifyPreStateTypeChange(current);
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // TODO(oshima): Make docked window a state.
135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (window_state->IsSnapped() ||
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        (!window_state->IsDocked() && !IsPanel(window_state->window()))) {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      UpdateBounds(window_state, current, event);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window_state->NotifyPostStateTypeChange(current);
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)WindowStateType DefaultState::GetType() const {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return state_type_;
145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool DefaultState::ProcessCompoundEvents(WindowState* window_state,
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                         const WMEvent* event) {
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  aura::Window* window = window_state->window();
151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  switch (event->type()) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (window_state->IsFullscreen()) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->OnWMEvent(&event);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (window_state->IsMaximized()) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->Restore();
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (window_state->IsNormalOrSnapped()) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (window_state->CanMaximize())
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          window_state->Maximize();
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE:
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (window_state->IsFullscreen()) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const wm::WMEvent event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->OnWMEvent(&event);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else if (window_state->IsMaximized()) {
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        window_state->Restore();
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else if (window_state->CanMaximize()) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->Maximize();
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect work_area =
176a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          ScreenUtil::GetDisplayWorkAreaBoundsInParent(window);
177a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Maximize vertically if:
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // - The window does not have a max height defined.
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // - The window has the normal state type. Snapped windows are excluded
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      //   because they are already maximized vertically and reverting to the
182a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      //   restored bounds looks weird.
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window->delegate()->GetMaximumSize().height() != 0 ||
184a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          !window_state->IsNormalStateType()) {
185a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        return true;
186a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      }
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window_state->HasRestoreBounds() &&
188a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          (window->bounds().height() == work_area.height() &&
189a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch           window->bounds().y() == work_area.y())) {
190a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        window_state->SetAndClearRestoreBounds();
191a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      } else {
192a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        window_state->SaveCurrentBoundsForRestore();
193a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        window->SetBounds(gfx::Rect(window->bounds().x(),
194a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                    work_area.y(),
195a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                    window->bounds().width(),
196a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                                    work_area.height()));
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
199a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    }
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: {
201a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      // Maximize horizontally if:
202a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      // - The window does not have a max width defined.
203a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      // - The window is snapped or has the normal state type.
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window->delegate()->GetMaximumSize().width() != 0)
205a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        return true;
206a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if (!window_state->IsNormalOrSnapped())
207a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        return true;
208a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      gfx::Rect work_area =
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ScreenUtil::GetDisplayWorkAreaBoundsInParent(window);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (window_state->IsNormalStateType() &&
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          window_state->HasRestoreBounds() &&
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          (window->bounds().width() == work_area.width() &&
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           window->bounds().x() == work_area.x())) {
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        window_state->SetAndClearRestoreBounds();
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      } else {
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Rect new_bounds(work_area.x(),
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             window->bounds().y(),
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             work_area.width(),
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             window->bounds().height());
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Rect restore_bounds = window->bounds();
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (window_state->IsSnapped()) {
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          window_state->SetRestoreBoundsInParent(new_bounds);
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          window_state->Restore();
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          // The restore logic prevents a window from being restored to bounds
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          // which match the workspace bounds exactly so it is necessary to set
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          // the bounds again below.
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_state->SetRestoreBoundsInParent(restore_bounds);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window->SetBounds(new_bounds);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case WM_EVENT_TOGGLE_FULLSCREEN: {
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Window which cannot be maximized should not be fullscreened.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // It can, however, be restored if it was fullscreened.
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool is_fullscreen = window_state->IsFullscreen();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!is_fullscreen && !window_state->CanMaximize())
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (window_state->delegate() &&
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          window_state->delegate()->ToggleFullscreen(window_state)) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (is_fullscreen) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->Restore();
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      } else {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        //
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_state->window()->SetProperty(aura::client::kShowStateKey,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            ui::SHOW_STATE_FULLSCREEN);
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return true;
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case WM_EVENT_NORMAL:
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WM_EVENT_MAXIMIZE:
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case WM_EVENT_MINIMIZE:
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WM_EVENT_FULLSCREEN:
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case WM_EVENT_SNAP_LEFT:
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_SNAP_RIGHT:
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case WM_EVENT_SET_BOUNDS:
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case WM_EVENT_SHOW_INACTIVE:
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_EVENT_ADDED_TO_WORKSPACE:
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_WORKAREA_BOUNDS_CHANGED:
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case WM_EVENT_DISPLAY_BOUNDS_CHANGED:
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED() << "Workspace event should not reach here:" << event;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DefaultState::ProcessWorkspaceEvents(WindowState* window_state,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const WMEvent* event) {
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (event->type()) {
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case WM_EVENT_ADDED_TO_WORKSPACE: {
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // When a window is dragged and dropped onto a different
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // root window, the bounds will be updated after they are added
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // to the root window.
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // If a window is opened as maximized or fullscreen, its bounds may be
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // empty, so update the bounds now before checking empty.
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window_state->is_dragged() ||
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          SetMaximizedOrFullscreenBounds(window_state)) {
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return true;
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      aura::Window* window = window_state->window();
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      gfx::Rect bounds = window->bounds();
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      // Don't adjust window bounds if the bounds are empty as this
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // happens when a new views::Widget is created.
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (bounds.IsEmpty())
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Use entire display instead of workarea because the workarea can
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // be further shrunk by the docked area. The logic ensures 30%
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // visibility which should be enough to see where the window gets
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // moved.
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      gfx::Rect display_area = ScreenUtil::GetDisplayBoundsInParent(window);
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      int min_width = bounds.width() * kMinimumPercentOnScreenArea;
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      int min_height = bounds.height() * kMinimumPercentOnScreenArea;
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AdjustBoundsToEnsureWindowVisibility(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          display_area, min_width, min_height, &bounds);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_state->AdjustSnappedBounds(&bounds);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (window->bounds() != bounds)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        window_state->SetBoundsConstrained(bounds);
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return true;
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case WM_EVENT_DISPLAY_BOUNDS_CHANGED: {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (window_state->is_dragged() ||
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          SetMaximizedOrFullscreenBounds(window_state)) {
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return true;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect work_area_in_parent =
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Rect bounds = window_state->window()->bounds();
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // When display bounds has changed, make sure the entire window is fully
318e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch      // visible.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bounds.AdjustToFit(work_area_in_parent);
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_state->AdjustSnappedBounds(&bounds);
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (window_state->window()->bounds() != bounds)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        window_state->SetBoundsDirectAnimated(bounds);
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WM_EVENT_WORKAREA_BOUNDS_CHANGED: {
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (window_state->is_dragged() ||
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          SetMaximizedOrFullscreenBounds(window_state)) {
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Rect work_area_in_parent =
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Rect bounds = window_state->window()->bounds();
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AdjustBoundsToEnsureMinimumWindowVisibility(work_area_in_parent, &bounds);
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_state->AdjustSnappedBounds(&bounds);
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (window_state->window()->bounds() != bounds)
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        window_state->SetBoundsDirectAnimated(bounds);
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_TOGGLE_MAXIMIZE:
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_TOGGLE_FULLSCREEN:
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_NORMAL:
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_MAXIMIZE:
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_MINIMIZE:
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WM_EVENT_FULLSCREEN:
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case WM_EVENT_SNAP_LEFT:
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case WM_EVENT_SNAP_RIGHT:
350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case WM_EVENT_SET_BOUNDS:
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WM_EVENT_SHOW_INACTIVE:
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DefaultState::UpdateBounds(WindowState* window_state,
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                WindowStateType old_state_type,
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                const WMEvent* event) {
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* window = window_state->window();
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Do nothing If this is not yet added to the container.
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!window->parent())
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (old_state_type != WINDOW_STATE_TYPE_MINIMIZED &&
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !window_state->HasRestoreBounds() &&
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_state->IsMaximizedOrFullscreen() &&
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !IsMaximizedOrFullscreenWindowStateType(old_state_type)) {
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_state->SaveCurrentBoundsForRestore();
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // When restoring from a minimized state, we want to restore to the previous
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // bounds. However, we want to maintain the restore bounds. (The restore
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // bounds are set if a user maximized the window in one axis by double
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // clicking the window border for example).
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect restore_bounds_in_screen;
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_state->IsNormalOrSnapped() &&
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_state->HasRestoreBounds() &&
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !window_state->unminimize_to_restore_bounds()) {
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    restore_bounds_in_screen = window_state->GetRestoreBoundsInScreen();
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_state->SaveCurrentBoundsForRestore();
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (window_state->IsMaximizedOrFullscreen())
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MoveToDisplayForRestore(window_state);
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WindowStateType state_type = window_state->GetStateType();
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect bounds_in_parent;
39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (state_type) {
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WINDOW_STATE_TYPE_LEFT_SNAPPED:
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    case WINDOW_STATE_TYPE_RIGHT_SNAPPED: {
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // There is no transition from minimized to snapped state.
396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SnapWindow(window_state, event, old_state_type);
397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return;
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WINDOW_STATE_TYPE_DEFAULT:
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case WINDOW_STATE_TYPE_NORMAL: {
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      gfx::Rect work_area_in_parent =
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (window_state->HasRestoreBounds())
404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        bounds_in_parent = window_state->GetRestoreBoundsInParent();
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      else
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bounds_in_parent = window->bounds();
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Make sure that part of the window is always visible.
408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      AdjustBoundsToEnsureMinimumWindowVisibility(
409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          work_area_in_parent, &bounds_in_parent);
410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      break;
411010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
412010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case WINDOW_STATE_TYPE_MAXIMIZED:
413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      bounds_in_parent = ScreenUtil::GetMaximizedWindowBoundsInParent(window);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_STATE_TYPE_FULLSCREEN:
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bounds_in_parent = ScreenUtil::GetDisplayBoundsInParent(window);
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WINDOW_STATE_TYPE_MINIMIZED:
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case WINDOW_STATE_TYPE_INACTIVE:
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WINDOW_STATE_TYPE_DETACHED:
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WINDOW_STATE_TYPE_END:
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case WINDOW_STATE_TYPE_AUTO_POSITIONED:
4266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return;
4276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (state_type != WINDOW_STATE_TYPE_MINIMIZED) {
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED ||
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        window_state->IsFullscreen()) {
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      window_state->SetBoundsDirect(bounds_in_parent);
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (window_state->IsMaximizedOrFullscreen() ||
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               IsMaximizedOrFullscreenWindowStateType(old_state_type)) {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_state->SetBoundsDirectCrossFade(bounds_in_parent);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_state->SetBoundsDirectAnimated(bounds_in_parent);
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (window_state->IsMinimized()) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Save the previous show state so that we can correctly restore it.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_state->window()->SetProperty(aura::client::kRestoreShowStateKey,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        ToWindowShowState(old_state_type));
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::SetWindowVisibilityAnimationType(
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hide the window.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_state->window()->Hide();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Activate another window.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window_state->IsActive())
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window_state->Deactivate();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ((window_state->window()->TargetVisibility() ||
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              old_state_type == WINDOW_STATE_TYPE_MINIMIZED) &&
455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch             !window_state->window()->layer()->visible()) {
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // The layer may be hidden if the window was previously minimized. Make
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // sure it's visible.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_state->window()->Show();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        !window_state->IsMaximizedOrFullscreen()) {
461ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      window_state->set_unminimize_to_restore_bounds(false);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (window_state->IsNormalOrSnapped())
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window_state->ClearRestoreBounds();
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Set the restore rectangle to the previously set restore rectangle.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!restore_bounds_in_screen.IsEmpty())
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    window_state->SetRestoreBoundsInScreen(restore_bounds_in_screen);
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool DefaultState::SetMaximizedOrFullscreenBounds(WindowState* window_state) {
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(!window_state->is_dragged());
476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (window_state->IsMaximized()) {
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window_state->SetBoundsDirect(
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ScreenUtil::GetMaximizedWindowBoundsInParent(window_state->window()));
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (window_state->IsFullscreen()) {
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    window_state->SetBoundsDirect(
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ScreenUtil::GetDisplayBoundsInParent(window_state->window()));
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
48746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DefaultState::SnapWindow(WindowState* window_state,
49146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                              const WMEvent* event,
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              WindowStateType old_state_type) {
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Compute the bounds that the window will restore to. If the window does not
494a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // already have restore bounds, it will be restored (when un-snapped) to the
495a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // last bounds that it had before getting snapped.
496a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect restore_bounds_in_screen = window_state->HasRestoreBounds() ?
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      window_state->GetRestoreBoundsInScreen() :
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      window_state->window()->GetBoundsInScreen();
499f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Rect snapped_bounds = event->type() == WM_EVENT_SNAP_LEFT ?
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetDefaultLeftSnappedWindowBoundsInParent(window_state->window()) :
501f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GetDefaultRightSnappedWindowBoundsInParent(window_state->window());
502f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IsMaximizedOrFullscreenWindowStateType(old_state_type)) {
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window_state->SetBoundsDirectCrossFade(snapped_bounds);
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (window_state->is_dragged()) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // SetBoundsDirectAnimated does not work when the window gets reparented.
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(oshima): Consider fixing it and reenable the animation.
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window_state->SetBoundsDirect(snapped_bounds);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window_state->SetBoundsDirectAnimated(snapped_bounds);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  window_state->SetRestoreBoundsInScreen(restore_bounds_in_screen);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DefaultState::SetBounds(WindowState* window_state,
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const SetBoundsEvent* event) {
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (window_state->is_dragged()) {
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    window_state->SetBoundsDirect(event->requested_bounds());
5216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (window_state->IsSnapped()) {
5226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gfx::Rect work_area_in_parent =
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
524a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    gfx::Rect child_bounds(event->requested_bounds());
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds);
526a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    window_state->AdjustSnappedBounds(&child_bounds);
527a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    window_state->SetBoundsDirect(child_bounds);
528a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } else if (!SetMaximizedOrFullscreenBounds(window_state)) {
529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    window_state->SetBoundsConstrained(event->requested_bounds());
530a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
531a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
532a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
533a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}  // namespace wm
534a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}  // namespace ash
535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch