window_state.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/screen_ash.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/shell_window_ids.h"
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_properties.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ash/wm/window_state_delegate.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_state_observer.h"
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_util.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/wm_types.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/auto_reset.h"
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window_delegate.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/display.h"
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/corewm/window_util.h"
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace ash {
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace wm {
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// static
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) {
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return show_state == ui::SHOW_STATE_FULLSCREEN ||
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      show_state == ui::SHOW_STATE_MAXIMIZED;
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState::WindowState(aura::Window* window)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : window_(window),
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      window_position_managed_(false),
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bounds_changed_by_user_(false),
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      panel_attached_(true),
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue_drag_after_reparent_(false),
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ignored_by_shelf_(false),
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      can_consume_system_keys_(false),
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      top_row_keys_are_function_keys_(false),
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      window_resizer_(NULL),
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      always_restores_to_restore_bounds_(false),
441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      hide_shelf_when_fullscreen_(true),
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      animate_to_fullscreen_(true),
460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      minimum_visibility_(false),
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      in_set_window_show_type_(false),
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_show_type_(ToWindowShowType(GetShowState())) {
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  window_->AddObserver(this);
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(OS_CHROMEOS)
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the kAshEnableImmersiveFullscreenForAllWindows flag is set most windows
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // can be put into immersive fullscreen. It is not worth the added complexity
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // to only animate to fullscreen if the window is put into immersive
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // fullscreen.
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  animate_to_fullscreen_ = !CommandLine::ForCurrentProcess()->HasSwitch(
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      switches::kAshEnableImmersiveFullscreenForAllWindows);
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState::~WindowState() {
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool WindowState::HasDelegate() const {
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return delegate_;
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) {
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!delegate_.get());
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_ = delegate.Pass();
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ui::WindowShowState WindowState::GetShowState() const {
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kShowStateKey);
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMinimized() const {
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_MINIMIZED;
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximized() const {
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_MAXIMIZED;
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsFullscreen() const {
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_FULLSCREEN;
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximizedOrFullscreen() const {
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsMaximizedOrFullscreenState(GetShowState());
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsNormalShowState() const {
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey);
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT;
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsActive() const {
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsActiveWindow(window_);
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool WindowState::IsDocked() const {
1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return window_->parent() &&
1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      window_->parent()->id() == internal::kShellWindowId_DockedContainer;
1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool WindowState::IsSnapped() const {
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED ||
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED;
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMaximize() const {
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kCanMaximizeKey);
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMinimize() const {
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  internal::RootWindowController* controller =
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      internal::RootWindowController::ForWindow(window_);
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!controller)
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* lockscreen = controller->GetContainer(
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      internal::kShellWindowId_LockScreenContainersContainer);
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (lockscreen->Contains(window_))
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanResize() const {
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kCanResizeKey);
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanActivate() const {
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return views::corewm::CanActivateWindow(window_);
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanSnap() const {
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!CanResize() ||
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_->type() == aura::client::WINDOW_TYPE_PANEL ||
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_->transient_parent())
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If a window has a maximum size defined, snapping may make it too big.
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() :
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              true;
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::HasRestoreBounds() const {
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL;
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Maximize() {
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapLeft(const gfx::Rect& bounds) {
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds);
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapRight(const gfx::Rect& bounds) {
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SnapWindow(SHOW_TYPE_RIGHT_SNAPPED, bounds);
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Minimize() {
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Unminimize() {
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      aura::client::kShowStateKey,
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      window_->GetProperty(aura::client::kRestoreShowStateKey));
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreShowStateKey);
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Activate() {
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ActivateWindow(window_);
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Deactivate() {
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DeactivateWindow(window_);
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Restore() {
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::ToggleMaximized() {
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (IsMaximized())
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Restore();
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else if (CanMaximize())
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Maximize();
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WindowState::ToggleFullscreen() {
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Window which cannot be maximized should not be fullscreened.
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // It can, however, be restored if it was fullscreened.
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool is_fullscreen = IsFullscreen();
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!is_fullscreen && !CanMaximize())
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (delegate_ && delegate_->ToggleFullscreen(this))
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (is_fullscreen) {
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Restore();
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    window_->SetProperty(aura::client::kShowStateKey,
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         ui::SHOW_STATE_FULLSCREEN);
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetBoundsInScreen(
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const gfx::Rect& bounds_in_screen) {
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_parent =
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectFromScreen(window_->parent(),
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       bounds_in_screen);
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetBounds(bounds_in_parent);
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SaveCurrentBoundsForRestore() {
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_screen =
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectToScreen(window_->parent(),
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     window_->bounds());
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(bounds_in_screen);
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInScreen() const {
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return *window_->GetProperty(aura::client::kRestoreBoundsKey);
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInParent() const {
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return ScreenAsh::ConvertRectFromScreen(window_->parent(),
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                          GetRestoreBoundsInScreen());
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) {
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectToScreen(window_->parent(), bounds));
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::ClearRestoreBounds() {
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreBoundsKey);
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetPreAutoManageWindowBounds(
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const gfx::Rect& bounds) {
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds));
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::AddObserver(WindowStateObserver* observer) {
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.AddObserver(observer);
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::RemoveObserver(WindowStateObserver* observer) {
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::OnWindowPropertyChanged(aura::Window* window,
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          const void* key,
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          intptr_t old) {
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(window, window_);
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (key == aura::client::kShowStateKey)
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetWindowShowType(ToWindowShowType(GetShowState()));
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapWindow(WindowShowType left_or_right,
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             const gfx::Rect& bounds) {
270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (window_show_type_ == left_or_right) {
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    window_->SetBounds(bounds);
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Compute the bounds that the window will restore to. If the window does not
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // already have restore bounds, it will be restored (when un-snapped) to the
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // last bounds that it had before getting snapped.
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ?
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      GetRestoreBoundsInScreen() : window_->GetBoundsInScreen());
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Set the window's restore bounds so that WorkspaceLayoutManager knows
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // which width to use when the snapped window is moved to the edge.
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetRestoreBoundsInParent(bounds);
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool was_maximized = IsMaximizedOrFullscreen();
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Before we can set the bounds we need to restore the window.
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Restoring the window will set the window to its restored bounds set above.
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Restore will cause OnWindowPropertyChanged() so it needs to be done
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // before notifying that the WindowShowType has changed to |left_or_right|.
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (was_maximized)
290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Restore();
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED ||
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         left_or_right == SHOW_TYPE_RIGHT_SNAPPED);
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetWindowShowType(left_or_right);
294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon
295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // observing the WindowShowType change.
296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // If the window is a child of kShellWindowId_DockedContainer such as during
297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // a drag, the window's bounds are not set in
298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // setting the bounds otherwise to avoid stopping the slide animation which
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // was started as a result of OnWindowShowTypeChanged().
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsDocked())
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window_->SetBounds(bounds);
303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetRestoreBoundsInScreen(restore_bounds_in_screen);
304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WindowState::SetWindowShowType(WindowShowType new_window_show_type) {
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (in_set_window_show_type_)
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::AutoReset<bool> resetter(&in_set_window_show_type_, true);
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ui::WindowShowState new_window_state =
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ToWindowShowState(new_window_show_type);
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (new_window_state != GetShowState())
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    window_->SetProperty(aura::client::kShowStateKey, new_window_state);
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  WindowShowType old_window_show_type = window_show_type_;
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  window_show_type_ = new_window_show_type;
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (old_window_show_type != window_show_type_) {
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      OnWindowShowTypeChanged(this, old_window_show_type));
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetActiveWindowState() {
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* active = GetActiveWindow();
32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return active ? GetWindowState(active) : NULL;
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetWindowState(aura::Window* window) {
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!window)
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WindowState* settings = window->GetProperty(internal::kWindowStateKey);
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if(!settings) {
33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    settings = new WindowState(window);
33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    window->SetProperty(internal::kWindowStateKey, settings);
33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return settings;
33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const WindowState* GetWindowState(const aura::Window* window) {
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetWindowState(const_cast<aura::Window*>(window));
34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace wm
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace ash
345