1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/wm/lock_window_state.h" 6 7#include "ash/screen_util.h" 8#include "ash/shell.h" 9#include "ash/wm/lock_layout_manager.h" 10#include "ash/wm/window_animations.h" 11#include "ash/wm/window_state.h" 12#include "ash/wm/window_state_delegate.h" 13#include "ash/wm/window_state_util.h" 14#include "ash/wm/window_util.h" 15#include "ash/wm/wm_event.h" 16#include "ui/aura/window.h" 17#include "ui/aura/window_delegate.h" 18#include "ui/gfx/rect.h" 19#include "ui/keyboard/keyboard_controller.h" 20#include "ui/keyboard/keyboard_util.h" 21#include "ui/wm/core/window_animations.h" 22 23namespace ash { 24 25LockWindowState::LockWindowState(aura::Window* window) 26 : current_state_type_(wm::GetWindowState(window)->GetStateType()) { 27} 28 29LockWindowState::~LockWindowState() { 30} 31 32void LockWindowState::OnWMEvent(wm::WindowState* window_state, 33 const wm::WMEvent* event) { 34 aura::Window* window = window_state->window(); 35 gfx::Rect bounds = window->bounds(); 36 37 switch (event->type()) { 38 case wm::WM_EVENT_TOGGLE_FULLSCREEN: 39 ToggleFullScreen(window_state, window_state->delegate()); 40 break; 41 case wm::WM_EVENT_FULLSCREEN: 42 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN); 43 break; 44 case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION: 45 case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE: 46 case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE: 47 case wm::WM_EVENT_TOGGLE_MAXIMIZE: 48 case wm::WM_EVENT_CENTER: 49 case wm::WM_EVENT_SNAP_LEFT: 50 case wm::WM_EVENT_SNAP_RIGHT: 51 case wm::WM_EVENT_NORMAL: 52 case wm::WM_EVENT_MAXIMIZE: 53 UpdateWindow(window_state, 54 GetMaximizedOrCenteredWindowType(window_state)); 55 return; 56 case wm::WM_EVENT_MINIMIZE: 57 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED); 58 return; 59 case wm::WM_EVENT_SHOW_INACTIVE: 60 return; 61 case wm::WM_EVENT_SET_BOUNDS: 62 if (window_state->IsMaximized() || window_state->IsFullscreen()) { 63 UpdateBounds(window_state); 64 } else { 65 const ash::wm::SetBoundsEvent* bounds_event = 66 static_cast<const ash::wm::SetBoundsEvent*>(event); 67 window_state->SetBoundsConstrained(bounds_event->requested_bounds()); 68 } 69 break; 70 case wm::WM_EVENT_ADDED_TO_WORKSPACE: 71 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED && 72 current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED && 73 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) { 74 UpdateWindow(window_state, 75 GetMaximizedOrCenteredWindowType(window_state)); 76 } 77 break; 78 case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED: 79 case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED: 80 UpdateBounds(window_state); 81 break; 82 } 83} 84 85wm::WindowStateType LockWindowState::GetType() const { 86 return current_state_type_; 87} 88 89void LockWindowState::AttachState(wm::WindowState* window_state, 90 wm::WindowState::State* previous_state) { 91 current_state_type_ = previous_state->GetType(); 92 93 // Initialize the state to a good preset. 94 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED && 95 current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED && 96 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) { 97 UpdateWindow(window_state, 98 GetMaximizedOrCenteredWindowType(window_state)); 99 } 100} 101 102void LockWindowState::DetachState(wm::WindowState* window_state) { 103} 104 105// static 106wm::WindowState* LockWindowState::SetLockWindowState(aura::Window* window) { 107 scoped_ptr<wm::WindowState::State> lock_state(new LockWindowState(window)); 108 scoped_ptr<wm::WindowState::State> old_state( 109 wm::GetWindowState(window)->SetStateObject(lock_state.Pass())); 110 return wm::GetWindowState(window); 111} 112 113void LockWindowState::UpdateWindow(wm::WindowState* window_state, 114 wm::WindowStateType target_state) { 115 DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED || 116 target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED || 117 (target_state == wm::WINDOW_STATE_TYPE_NORMAL && 118 !window_state->CanMaximize()) || 119 target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN); 120 121 if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) { 122 if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED) 123 return; 124 125 current_state_type_ = target_state; 126 ::wm::SetWindowVisibilityAnimationType( 127 window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); 128 window_state->window()->Hide(); 129 if (window_state->IsActive()) 130 window_state->Deactivate(); 131 return; 132 } 133 134 if (current_state_type_ == target_state) { 135 // If the state type did not change, update it accordingly. 136 UpdateBounds(window_state); 137 return; 138 } 139 140 const wm::WindowStateType old_state_type = current_state_type_; 141 current_state_type_ = target_state; 142 window_state->UpdateWindowShowStateFromStateType(); 143 window_state->NotifyPreStateTypeChange(old_state_type); 144 UpdateBounds(window_state); 145 window_state->NotifyPostStateTypeChange(old_state_type); 146 147 if ((window_state->window()->TargetVisibility() || 148 old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) && 149 !window_state->window()->layer()->visible()) { 150 // The layer may be hidden if the window was previously minimized. Make 151 // sure it's visible. 152 window_state->window()->Show(); 153 } 154} 155 156wm::WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType( 157 wm::WindowState* window_state) { 158 return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED : 159 wm::WINDOW_STATE_TYPE_NORMAL; 160} 161 162void LockWindowState::UpdateBounds(wm::WindowState* window_state) { 163 if (!window_state->IsMaximized() && !window_state->IsFullscreen()) 164 return; 165 166 keyboard::KeyboardController* keyboard_controller = 167 keyboard::KeyboardController::GetInstance(); 168 gfx::Rect keyboard_bounds; 169 170 if (keyboard_controller && 171 !keyboard::IsKeyboardOverscrollEnabled() && 172 keyboard_controller->keyboard_visible()) { 173 keyboard_bounds = keyboard_controller->current_keyboard_bounds(); 174 } 175 176 gfx::Rect bounds = 177 ScreenUtil::GetDisplayBoundsInParent(window_state->window()); 178 bounds.set_height(bounds.height() - keyboard_bounds.height()); 179 180 VLOG(1) << "Updating window bounds to: " << bounds.ToString(); 181 window_state->SetBoundsDirect(bounds); 182} 183 184} // namespace ash 185