lock_window_state.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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      UpdateBounds(window_state);
63      break;
64    case wm::WM_EVENT_ADDED_TO_WORKSPACE:
65      if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
66          current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
67          current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
68        UpdateWindow(window_state,
69                     GetMaximizedOrCenteredWindowType(window_state));
70      }
71      break;
72    case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
73    case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
74      UpdateBounds(window_state);
75      break;
76  }
77}
78
79wm::WindowStateType LockWindowState::GetType() const {
80  return current_state_type_;
81}
82
83void LockWindowState::AttachState(wm::WindowState* window_state,
84                                  wm::WindowState::State* previous_state) {
85  current_state_type_ = previous_state->GetType();
86
87  // Initialize the state to a good preset.
88  if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
89      current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
90      current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN) {
91    UpdateWindow(window_state,
92                 GetMaximizedOrCenteredWindowType(window_state));
93  }
94}
95
96void LockWindowState::DetachState(wm::WindowState* window_state) {
97}
98
99// static
100wm::WindowState* LockWindowState::SetLockWindowState(aura::Window* window) {
101  scoped_ptr<wm::WindowState::State> lock_state(new LockWindowState(window));
102  scoped_ptr<wm::WindowState::State> old_state(
103      wm::GetWindowState(window)->SetStateObject(lock_state.Pass()));
104  return wm::GetWindowState(window);
105}
106
107void LockWindowState::UpdateWindow(wm::WindowState* window_state,
108                                   wm::WindowStateType target_state) {
109  DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
110         target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
111         (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
112              !window_state->CanMaximize()) ||
113         target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);
114
115  if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
116    if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
117      return;
118
119    current_state_type_ = target_state;
120    ::wm::SetWindowVisibilityAnimationType(
121        window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
122    window_state->window()->Hide();
123    if (window_state->IsActive())
124      window_state->Deactivate();
125    return;
126  }
127
128  if (current_state_type_ == target_state) {
129    // If the state type did not change, update it accordingly.
130    UpdateBounds(window_state);
131    return;
132  }
133
134  const wm::WindowStateType old_state_type = current_state_type_;
135  current_state_type_ = target_state;
136  window_state->UpdateWindowShowStateFromStateType();
137  window_state->NotifyPreStateTypeChange(old_state_type);
138  UpdateBounds(window_state);
139  window_state->NotifyPostStateTypeChange(old_state_type);
140
141  if ((window_state->window()->TargetVisibility() ||
142      old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
143      !window_state->window()->layer()->visible()) {
144    // The layer may be hidden if the window was previously minimized. Make
145    // sure it's visible.
146    window_state->window()->Show();
147  }
148}
149
150wm::WindowStateType LockWindowState::GetMaximizedOrCenteredWindowType(
151      wm::WindowState* window_state) {
152  return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED :
153                                       wm::WINDOW_STATE_TYPE_NORMAL;
154}
155
156void LockWindowState::UpdateBounds(wm::WindowState* window_state) {
157  keyboard::KeyboardController* keyboard_controller =
158      keyboard::KeyboardController::GetInstance();
159  gfx::Rect keyboard_bounds;
160
161  if (keyboard_controller && !keyboard::IsKeyboardOverscrollEnabled())
162    keyboard_bounds = keyboard_controller->current_keyboard_bounds();
163
164  gfx::Rect bounds =
165      ScreenUtil::GetDisplayBoundsInParent(window_state->window());
166  bounds.set_height(bounds.height() - keyboard_bounds.height());
167  window_state->SetBoundsDirect(bounds);
168}
169
170}  // namespace ash
171