Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / ash / wm / maximize_mode / maximize_mode_window_manager.cc
blob7adcc00177103b02b5f9242a2788bc21f1d8eef9
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.
5 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h"
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/shell.h"
10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/maximize_mode/maximize_mode_window_state.h"
12 #include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
13 #include "ash/wm/mru_window_tracker.h"
14 #include "ash/wm/overview/window_selector_controller.h"
15 #include "ash/wm/window_state.h"
16 #include "ash/wm/window_util.h"
17 #include "ash/wm/wm_event.h"
18 #include "ash/wm/workspace_controller.h"
19 #include "base/command_line.h"
20 #include "ui/aura/client/aura_constants.h"
21 #include "ui/aura/window.h"
22 #include "ui/gfx/screen.h"
24 namespace ash {
26 namespace {
28 // The height of the area in which a touch operation leads to exiting the
29 // full screen mode.
30 const int kLeaveFullScreenAreaHeightInPixel = 2;
32 // Exits overview mode if it is currently active.
33 void CancelOverview() {
34 WindowSelectorController* controller =
35 Shell::GetInstance()->window_selector_controller();
36 if (controller && controller->IsSelecting())
37 controller->OnSelectionEnded();
40 } // namespace
42 MaximizeModeWindowManager::~MaximizeModeWindowManager() {
43 // Overview mode needs to be ended before exiting maximize mode to prevent
44 // transforming windows which are currently in
45 // overview: http://crbug.com/366605
46 CancelOverview();
48 Shell::GetInstance()->RemovePreTargetHandler(this);
49 Shell::GetInstance()->RemoveShellObserver(this);
50 Shell::GetScreen()->RemoveObserver(this);
51 EnableBackdropBehindTopWindowOnEachDisplay(false);
52 RemoveWindowCreationObservers();
53 RestoreAllWindows();
56 int MaximizeModeWindowManager::GetNumberOfManagedWindows() {
57 return window_state_map_.size();
60 void MaximizeModeWindowManager::AddWindow(aura::Window* window) {
61 // Only add the window if it is a direct dependent of a container window
62 // and not yet tracked.
63 if (!ShouldHandleWindow(window) ||
64 window_state_map_.find(window) != window_state_map_.end() ||
65 !IsContainerWindow(window->parent())) {
66 return;
69 MaximizeAndTrackWindow(window);
72 void MaximizeModeWindowManager::WindowStateDestroyed(aura::Window* window) {
73 // At this time ForgetWindow() should already have been called. If not,
74 // someone else must have replaced the "window manager's state object".
75 DCHECK(!window->HasObserver(this));
77 WindowToState::iterator it = window_state_map_.find(window);
78 DCHECK(it != window_state_map_.end());
79 window_state_map_.erase(it);
82 void MaximizeModeWindowManager::OnOverviewModeStarting() {
83 if (backdrops_hidden_)
84 return;
86 EnableBackdropBehindTopWindowOnEachDisplay(false);
87 SetDeferBoundsUpdates(true);
88 backdrops_hidden_ = true;
91 void MaximizeModeWindowManager::OnOverviewModeEnded() {
92 if (!backdrops_hidden_)
93 return;
95 backdrops_hidden_ = false;
96 EnableBackdropBehindTopWindowOnEachDisplay(true);
97 SetDeferBoundsUpdates(false);
100 void MaximizeModeWindowManager::OnWindowDestroying(aura::Window* window) {
101 if (IsContainerWindow(window)) {
102 // container window can be removed on display destruction.
103 window->RemoveObserver(this);
104 observed_container_windows_.erase(window);
105 } else {
106 // If a known window gets destroyed we need to remove all knowledge about
107 // it.
108 ForgetWindow(window);
112 void MaximizeModeWindowManager::OnWindowAdded(aura::Window* window) {
113 // A window can get removed and then re-added by a drag and drop operation.
114 if (IsContainerWindow(window->parent()) &&
115 window_state_map_.find(window) == window_state_map_.end()) {
116 MaximizeAndTrackWindow(window);
117 // When the state got added, the "WM_EVENT_ADDED_TO_WORKSPACE" event got
118 // already sent and we have to notify our state again.
119 if (window_state_map_.find(window) != window_state_map_.end()) {
120 wm::WMEvent event(wm::WM_EVENT_ADDED_TO_WORKSPACE);
121 wm::GetWindowState(window)->OnWMEvent(&event);
126 void MaximizeModeWindowManager::OnWindowPropertyChanged(aura::Window* window,
127 const void* key,
128 intptr_t old) {
129 // Stop managing |window| if the always-on-top property is added.
130 if (key == aura::client::kAlwaysOnTopKey &&
131 window->GetProperty(aura::client::kAlwaysOnTopKey)) {
132 ForgetWindow(window);
136 void MaximizeModeWindowManager::OnWindowBoundsChanged(
137 aura::Window* window,
138 const gfx::Rect& old_bounds,
139 const gfx::Rect& new_bounds) {
140 if (!IsContainerWindow(window))
141 return;
142 // Reposition all non maximizeable windows.
143 for (WindowToState::iterator it = window_state_map_.begin();
144 it != window_state_map_.end();
145 ++it) {
146 it->second->UpdateWindowPosition(wm::GetWindowState(it->first));
150 void MaximizeModeWindowManager::OnDisplayAdded(const gfx::Display& display) {
151 DisplayConfigurationChanged();
154 void MaximizeModeWindowManager::OnDisplayRemoved(const gfx::Display& display) {
155 DisplayConfigurationChanged();
158 void MaximizeModeWindowManager::OnDisplayMetricsChanged(const gfx::Display&,
159 uint32_t) {
160 // Nothing to do here.
163 void MaximizeModeWindowManager::OnTouchEvent(ui::TouchEvent* event) {
164 if (event->type() != ui::ET_TOUCH_PRESSED)
165 return;
167 // Find the active window (from the primary screen) to un-fullscreen.
168 aura::Window* window = wm::GetActiveWindow();
169 if (!window)
170 return;
172 wm::WindowState* window_state = wm::GetWindowState(window);
173 if (!window_state->IsFullscreen() || window_state->in_immersive_fullscreen())
174 return;
176 // Test that the touch happened in the top or bottom lines.
177 int y = event->y();
178 if (y >= kLeaveFullScreenAreaHeightInPixel &&
179 y < (window->bounds().height() - kLeaveFullScreenAreaHeightInPixel)) {
180 return;
183 // Leave full screen mode.
184 event->StopPropagation();
185 wm::WMEvent toggle_fullscreen(wm::WM_EVENT_TOGGLE_FULLSCREEN);
186 window_state->OnWMEvent(&toggle_fullscreen);
189 MaximizeModeWindowManager::MaximizeModeWindowManager()
190 : backdrops_hidden_(false) {
191 // The overview mode needs to be ended before the maximize mode is started. To
192 // guarantee the proper order, it will be turned off from here.
193 CancelOverview();
195 MaximizeAllWindows();
196 AddWindowCreationObservers();
197 EnableBackdropBehindTopWindowOnEachDisplay(true);
198 Shell::GetScreen()->AddObserver(this);
199 Shell::GetInstance()->AddShellObserver(this);
200 Shell::GetInstance()->AddPreTargetHandler(this);
203 void MaximizeModeWindowManager::MaximizeAllWindows() {
204 MruWindowTracker::WindowList windows = ash::Shell::GetInstance()->
205 mru_window_tracker()->BuildWindowListIgnoreModal();
206 // Add all existing Mru windows.
207 for (MruWindowTracker::WindowList::iterator window = windows.begin();
208 window != windows.end(); ++window) {
209 MaximizeAndTrackWindow(*window);
213 void MaximizeModeWindowManager::RestoreAllWindows() {
214 while (window_state_map_.size())
215 ForgetWindow(window_state_map_.begin()->first);
218 void MaximizeModeWindowManager::SetDeferBoundsUpdates(
219 bool defer_bounds_updates) {
220 for (WindowToState::iterator it = window_state_map_.begin();
221 it != window_state_map_.end();
222 ++it) {
223 it->second->SetDeferBoundsUpdates(defer_bounds_updates);
227 void MaximizeModeWindowManager::MaximizeAndTrackWindow(
228 aura::Window* window) {
229 if (!ShouldHandleWindow(window))
230 return;
232 DCHECK(window_state_map_.find(window) == window_state_map_.end());
233 window->AddObserver(this);
235 // We create and remember a maximize mode state which will attach itself to
236 // the provided state object.
237 window_state_map_[window] = new MaximizeModeWindowState(window, this);
240 void MaximizeModeWindowManager::ForgetWindow(aura::Window* window) {
241 WindowToState::iterator it = window_state_map_.find(window);
243 // The following DCHECK could fail if our window state object was destroyed
244 // earlier by someone else. However - at this point there is no other client
245 // which replaces the state object and therefore this should not happen.
246 DCHECK(it != window_state_map_.end());
247 window->RemoveObserver(this);
249 // By telling the state object to revert, it will switch back the old
250 // State object and destroy itself, calling WindowStateDestroyed().
251 it->second->LeaveMaximizeMode(wm::GetWindowState(it->first));
252 DCHECK(window_state_map_.find(window) == window_state_map_.end());
255 bool MaximizeModeWindowManager::ShouldHandleWindow(aura::Window* window) {
256 DCHECK(window);
258 // Windows with the always-on-top property should be free-floating and thus
259 // not managed by us.
260 if (window->GetProperty(aura::client::kAlwaysOnTopKey))
261 return false;
263 // Windows in the dock should not be managed by us.
264 if (wm::GetWindowState(window)->IsDocked())
265 return false;
267 return window->type() == ui::wm::WINDOW_TYPE_NORMAL;
270 void MaximizeModeWindowManager::AddWindowCreationObservers() {
271 DCHECK(observed_container_windows_.empty());
272 // Observe window activations/creations in the default containers on all root
273 // windows.
274 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
275 for (aura::Window::Windows::const_iterator iter = root_windows.begin();
276 iter != root_windows.end(); ++iter) {
277 aura::Window* container =
278 Shell::GetContainer(*iter, kShellWindowId_DefaultContainer);
279 DCHECK(observed_container_windows_.find(container) ==
280 observed_container_windows_.end());
281 container->AddObserver(this);
282 observed_container_windows_.insert(container);
286 void MaximizeModeWindowManager::RemoveWindowCreationObservers() {
287 for (std::set<aura::Window*>::iterator iter =
288 observed_container_windows_.begin();
289 iter != observed_container_windows_.end(); ++iter) {
290 (*iter)->RemoveObserver(this);
292 observed_container_windows_.clear();
295 void MaximizeModeWindowManager::DisplayConfigurationChanged() {
296 EnableBackdropBehindTopWindowOnEachDisplay(false);
297 RemoveWindowCreationObservers();
298 AddWindowCreationObservers();
299 EnableBackdropBehindTopWindowOnEachDisplay(true);
302 bool MaximizeModeWindowManager::IsContainerWindow(aura::Window* window) {
303 return observed_container_windows_.find(window) !=
304 observed_container_windows_.end();
307 void MaximizeModeWindowManager::EnableBackdropBehindTopWindowOnEachDisplay(
308 bool enable) {
309 // This function should be a no-op if backdrops have been disabled.
310 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
311 switches::kAshDisableMaximizeModeWindowBackdrop)) {
312 return;
315 if (backdrops_hidden_)
316 return;
318 // Inform the WorkspaceLayoutManager that we want to show a backdrop behind
319 // the topmost window of its container.
320 Shell::RootWindowControllerList controllers =
321 Shell::GetAllRootWindowControllers();
322 for (Shell::RootWindowControllerList::iterator iter = controllers.begin();
323 iter != controllers.end(); ++iter) {
324 RootWindowController* controller = *iter;
325 aura::Window* container = Shell::GetContainer(
326 controller->GetRootWindow(), kShellWindowId_DefaultContainer);
327 controller->workspace_controller()->SetMaximizeBackdropDelegate(
328 scoped_ptr<WorkspaceLayoutManagerDelegate>(
329 enable ? new WorkspaceBackdropDelegate(container) : NULL));
333 } // namespace ash