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
23 namespace ash {
24
LockWindowState(aura::Window * window)25 LockWindowState::LockWindowState(aura::Window* window)
26 : current_state_type_(wm::GetWindowState(window)->GetStateType()) {
27 }
28
~LockWindowState()29 LockWindowState::~LockWindowState() {
30 }
31
OnWMEvent(wm::WindowState * window_state,const wm::WMEvent * event)32 void 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
GetType() const85 wm::WindowStateType LockWindowState::GetType() const {
86 return current_state_type_;
87 }
88
AttachState(wm::WindowState * window_state,wm::WindowState::State * previous_state)89 void 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
DetachState(wm::WindowState * window_state)102 void LockWindowState::DetachState(wm::WindowState* window_state) {
103 }
104
105 // static
SetLockWindowState(aura::Window * window)106 wm::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
UpdateWindow(wm::WindowState * window_state,wm::WindowStateType target_state)113 void 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
GetMaximizedOrCenteredWindowType(wm::WindowState * window_state)156 wm::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
UpdateBounds(wm::WindowState * window_state)162 void 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 && !keyboard::IsKeyboardOverscrollEnabled())
171 keyboard_bounds = keyboard_controller->current_keyboard_bounds();
172
173 gfx::Rect bounds =
174 ScreenUtil::GetDisplayBoundsInParent(window_state->window());
175 bounds.set_height(bounds.height() - keyboard_bounds.height());
176 window_state->SetBoundsDirect(bounds);
177 }
178
179 } // namespace ash
180