window_state.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/root_window_controller.h"
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/screen_ash.h"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/shell_window_ids.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_properties.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ash/wm/window_state_delegate.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_state_observer.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ash/wm/window_util.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/wm_types.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/client/aura_constants.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/aura/window_delegate.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/display.h"
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/corewm/window_util.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace ash {
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace wm {
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// static
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) {
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return show_state == ui::SHOW_STATE_FULLSCREEN ||
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      show_state == ui::SHOW_STATE_MAXIMIZED;
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState::WindowState(aura::Window* window)
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : window_(window),
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      tracked_by_workspace_(true),
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      window_position_managed_(false),
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      bounds_changed_by_user_(false),
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      panel_attached_(true),
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue_drag_after_reparent_(false),
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ignored_by_shelf_(false),
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      can_consume_system_keys_(false),
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      top_row_keys_are_function_keys_(false),
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      window_resizer_(NULL),
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      always_restores_to_restore_bounds_(false),
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      hide_shelf_when_fullscreen_(true),
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      animate_to_fullscreen_(true),
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_show_type_(ToWindowShowType(GetShowState())) {
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  window_->AddObserver(this);
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState::~WindowState() {
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) {
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!delegate_.get());
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  delegate_ = delegate.Pass();
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)ui::WindowShowState WindowState::GetShowState() const {
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kShowStateKey);
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMinimized() const {
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_MINIMIZED;
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximized() const {
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_MAXIMIZED;
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsFullscreen() const {
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetShowState() == ui::SHOW_STATE_FULLSCREEN;
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsMaximizedOrFullscreen() const {
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsMaximizedOrFullscreenState(GetShowState());
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsNormalShowState() const {
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey);
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT;
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::IsActive() const {
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return IsActiveWindow(window_);
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool WindowState::IsDocked() const {
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return window_->parent() &&
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      window_->parent()->id() == internal::kShellWindowId_DockedContainer;
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMaximize() const {
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kCanMaximizeKey);
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanMinimize() const {
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  internal::RootWindowController* controller =
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      internal::RootWindowController::ForWindow(window_);
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!controller)
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* lockscreen = controller->GetContainer(
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      internal::kShellWindowId_LockScreenContainersContainer);
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (lockscreen->Contains(window_))
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanResize() const {
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kCanResizeKey);
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanActivate() const {
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return views::corewm::CanActivateWindow(window_);
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::CanSnap() const {
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!CanResize() ||
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_->type() == aura::client::WINDOW_TYPE_PANEL ||
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      window_->transient_parent())
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If a window has a maximum size defined, snapping may make it too big.
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() :
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                              true;
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WindowState::HasRestoreBounds() const {
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL;
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Maximize() {
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapLeft(const gfx::Rect& bounds) {
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds);
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapRight(const gfx::Rect& bounds) {
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds);
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Minimize() {
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Unminimize() {
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      aura::client::kShowStateKey,
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      window_->GetProperty(aura::client::kRestoreShowStateKey));
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreShowStateKey);
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Activate() {
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ActivateWindow(window_);
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Deactivate() {
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DeactivateWindow(window_);
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::Restore() {
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::ToggleMaximized() {
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (IsMaximized())
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Restore();
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else if (CanMaximize())
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Maximize();
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void WindowState::ToggleFullscreen() {
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Window which cannot be maximized should not be fullscreened.
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // It can, however, be restored if it was fullscreened.
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bool is_fullscreen = IsFullscreen();
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!is_fullscreen && !CanMaximize())
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (delegate_ && delegate_->ToggleFullscreen(this))
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (is_fullscreen) {
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Restore();
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  } else {
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    window_->SetProperty(aura::client::kShowStateKey,
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         ui::SHOW_STATE_FULLSCREEN);
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetBoundsInScreen(
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const gfx::Rect& bounds_in_screen) {
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_parent =
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectFromScreen(window_->parent(),
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       bounds_in_screen);
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetBounds(bounds_in_parent);
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SaveCurrentBoundsForRestore() {
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Rect bounds_in_screen =
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectToScreen(window_->parent(),
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     window_->bounds());
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(bounds_in_screen);
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInScreen() const {
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return *window_->GetProperty(aura::client::kRestoreBoundsKey);
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::Rect WindowState::GetRestoreBoundsInParent() const {
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return ScreenAsh::ConvertRectFromScreen(window_->parent(),
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                          GetRestoreBoundsInScreen());
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) {
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) {
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SetRestoreBoundsInScreen(
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ScreenAsh::ConvertRectToScreen(window_->parent(), bounds));
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::ClearRestoreBounds() {
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  window_->ClearProperty(aura::client::kRestoreBoundsKey);
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetPreAutoManageWindowBounds(
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const gfx::Rect& bounds) {
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds));
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::AddObserver(WindowStateObserver* observer) {
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.AddObserver(observer);
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::RemoveObserver(WindowStateObserver* observer) {
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  observer_list_.RemoveObserver(observer);
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void WindowState::SetTrackedByWorkspace(bool tracked_by_workspace) {
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (tracked_by_workspace_ == tracked_by_workspace)
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool old = tracked_by_workspace_;
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  tracked_by_workspace_ = tracked_by_workspace;
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FOR_EACH_OBSERVER(WindowStateObserver, observer_list_,
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                    OnTrackedByWorkspaceChanged(this, old));
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::OnWindowPropertyChanged(aura::Window* window,
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          const void* key,
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          intptr_t old) {
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(window, window_);
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (key == aura::client::kShowStateKey) {
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    window_show_type_ = ToWindowShowType(GetShowState());
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ui::WindowShowState old_state = static_cast<ui::WindowShowState>(old);
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // TODO(oshima): Notify only when the state has changed.
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Doing so break a few tests now.
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FOR_EACH_OBSERVER(
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        WindowStateObserver, observer_list_,
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        OnWindowShowTypeChanged(this, ToWindowShowType(old_state)));
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::OnWindowDestroying(aura::Window* window) {
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  window_->RemoveObserver(this);
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowState::SnapWindow(WindowShowType left_or_right,
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             const gfx::Rect& bounds) {
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (IsMaximizedOrFullscreen()) {
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Before we can set the bounds we need to restore the window.
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Restoring the window will set the window to its restored bounds.
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // To avoid an unnecessary bounds changes (which may have side effects)
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // we set the restore bounds to the bounds we want, restore the window,
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // then reset the restore bounds. This way no unnecessary bounds
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // changes occurs and the original restore bounds is remembered.
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    gfx::Rect restore_bounds_in_screen =
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        GetRestoreBoundsInScreen();
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SetRestoreBoundsInParent(bounds);
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Restore();
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SetRestoreBoundsInScreen(restore_bounds_in_screen);
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    window_->SetBounds(bounds);
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED ||
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)         left_or_right == SHOW_TYPE_RIGHT_SNAPPED);
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  window_show_type_ = left_or_right;
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetActiveWindowState() {
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  aura::Window* active = GetActiveWindow();
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return active ? GetWindowState(active) : NULL;
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)WindowState* GetWindowState(aura::Window* window) {
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!window)
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  WindowState* settings = window->GetProperty(internal::kWindowStateKey);
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if(!settings) {
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    settings = new WindowState(window);
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    window->SetProperty(internal::kWindowStateKey, settings);
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return settings;
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const WindowState* GetWindowState(const aura::Window* window) {
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return GetWindowState(const_cast<aura::Window*>(window));
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace wm
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace ash
309