Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: ash/common/wm/maximize_mode/maximize_mode_window_state.cc

Issue 2734653002: chromeos: Move files in //ash/common to //ash (Closed)
Patch Set: fix a11y tests, fix docs Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/common/wm/maximize_mode/maximize_mode_window_state.h"
6
7 #include <utility>
8
9 #include "ash/common/wm/maximize_mode/maximize_mode_window_manager.h"
10 #include "ash/common/wm/window_animation_types.h"
11 #include "ash/common/wm/window_state_util.h"
12 #include "ash/common/wm/wm_event.h"
13 #include "ash/common/wm/wm_screen_util.h"
14 #include "ash/common/wm_shell.h"
15 #include "ash/common/wm_window.h"
16 #include "ash/public/cpp/shell_window_ids.h"
17 #include "ui/compositor/layer.h"
18 #include "ui/gfx/geometry/rect.h"
19
20 namespace ash {
21 namespace {
22
23 // Returns the biggest possible size for a window which is about to be
24 // maximized.
25 gfx::Size GetMaximumSizeOfWindow(wm::WindowState* window_state) {
26 DCHECK(window_state->CanMaximize() || window_state->CanResize());
27
28 gfx::Size workspace_size =
29 wm::GetMaximizedWindowBoundsInParent(window_state->window()).size();
30
31 gfx::Size size = window_state->window()->GetMaximumSize();
32 if (size.IsEmpty())
33 return workspace_size;
34
35 size.SetToMin(workspace_size);
36 return size;
37 }
38
39 // Returns the centered bounds of the given bounds in the work area.
40 gfx::Rect GetCenteredBounds(const gfx::Rect& bounds_in_parent,
41 wm::WindowState* state_object) {
42 gfx::Rect work_area_in_parent =
43 wm::GetDisplayWorkAreaBoundsInParent(state_object->window());
44 work_area_in_parent.ClampToCenteredSize(bounds_in_parent.size());
45 return work_area_in_parent;
46 }
47
48 // Returns the maximized/full screen and/or centered bounds of a window.
49 gfx::Rect GetBoundsInMaximizedMode(wm::WindowState* state_object) {
50 if (state_object->IsFullscreen() || state_object->IsPinned())
51 return wm::GetDisplayBoundsInParent(state_object->window());
52
53 gfx::Rect bounds_in_parent;
54 // Make the window as big as possible.
55 if (state_object->CanMaximize() || state_object->CanResize()) {
56 bounds_in_parent.set_size(GetMaximumSizeOfWindow(state_object));
57 } else {
58 // We prefer the user given window dimensions over the current windows
59 // dimensions since they are likely to be the result from some other state
60 // object logic.
61 if (state_object->HasRestoreBounds())
62 bounds_in_parent = state_object->GetRestoreBoundsInParent();
63 else
64 bounds_in_parent = state_object->window()->GetBounds();
65 }
66 return GetCenteredBounds(bounds_in_parent, state_object);
67 }
68
69 gfx::Rect GetRestoreBounds(wm::WindowState* window_state) {
70 if (window_state->IsMinimized() || window_state->IsMaximized() ||
71 window_state->IsFullscreen()) {
72 gfx::Rect restore_bounds = window_state->GetRestoreBoundsInScreen();
73 if (!restore_bounds.IsEmpty())
74 return restore_bounds;
75 }
76 gfx::Rect bounds = window_state->window()->GetBoundsInScreen();
77 if (window_state->IsDocked()) {
78 gfx::Rect restore_bounds = window_state->GetRestoreBoundsInScreen();
79 // Use current window horizontal offset origin in order to preserve docked
80 // alignment but preserve restored size and vertical offset for the time
81 // when the window gets undocked.
82 if (!restore_bounds.IsEmpty()) {
83 bounds.set_size(restore_bounds.size());
84 bounds.set_y(restore_bounds.y());
85 }
86 }
87 return bounds;
88 }
89
90 } // namespace
91
92 // static
93 void MaximizeModeWindowState::UpdateWindowPosition(
94 wm::WindowState* window_state) {
95 gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
96 if (bounds_in_parent == window_state->window()->GetBounds())
97 return;
98 window_state->SetBoundsDirect(bounds_in_parent);
99 }
100
101 MaximizeModeWindowState::MaximizeModeWindowState(
102 WmWindow* window,
103 MaximizeModeWindowManager* creator)
104 : window_(window),
105 creator_(creator),
106 current_state_type_(window->GetWindowState()->GetStateType()),
107 defer_bounds_updates_(false) {
108 old_state_.reset(window_->GetWindowState()
109 ->SetStateObject(std::unique_ptr<State>(this))
110 .release());
111 }
112
113 MaximizeModeWindowState::~MaximizeModeWindowState() {
114 creator_->WindowStateDestroyed(window_);
115 }
116
117 void MaximizeModeWindowState::LeaveMaximizeMode(wm::WindowState* window_state) {
118 // Note: When we return we will destroy ourselves with the |our_reference|.
119 std::unique_ptr<wm::WindowState::State> our_reference =
120 window_state->SetStateObject(std::move(old_state_));
121 }
122
123 void MaximizeModeWindowState::SetDeferBoundsUpdates(bool defer_bounds_updates) {
124 if (defer_bounds_updates_ == defer_bounds_updates)
125 return;
126
127 defer_bounds_updates_ = defer_bounds_updates;
128 if (!defer_bounds_updates_)
129 UpdateBounds(window_->GetWindowState(), true);
130 }
131
132 void MaximizeModeWindowState::OnWMEvent(wm::WindowState* window_state,
133 const wm::WMEvent* event) {
134 switch (event->type()) {
135 case wm::WM_EVENT_TOGGLE_FULLSCREEN:
136 ToggleFullScreen(window_state, window_state->delegate());
137 break;
138 case wm::WM_EVENT_FULLSCREEN:
139 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_FULLSCREEN, true);
140 break;
141 case wm::WM_EVENT_PIN:
142 if (!WmShell::Get()->IsPinned())
143 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_PINNED, true);
144 break;
145 case wm::WM_EVENT_TRUSTED_PIN:
146 if (!WmShell::Get()->IsPinned())
147 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_TRUSTED_PINNED, true);
148 break;
149 case wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
150 case wm::WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
151 case wm::WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
152 case wm::WM_EVENT_TOGGLE_MAXIMIZE:
153 case wm::WM_EVENT_CYCLE_SNAP_DOCK_LEFT:
154 case wm::WM_EVENT_CYCLE_SNAP_DOCK_RIGHT:
155 case wm::WM_EVENT_CENTER:
156 case wm::WM_EVENT_SNAP_LEFT:
157 case wm::WM_EVENT_SNAP_RIGHT:
158 case wm::WM_EVENT_NORMAL:
159 case wm::WM_EVENT_MAXIMIZE:
160 case wm::WM_EVENT_DOCK:
161 UpdateWindow(window_state, GetMaximizedOrCenteredWindowType(window_state),
162 true);
163 return;
164 case wm::WM_EVENT_MINIMIZE:
165 UpdateWindow(window_state, wm::WINDOW_STATE_TYPE_MINIMIZED, true);
166 return;
167 case wm::WM_EVENT_SHOW_INACTIVE:
168 return;
169 case wm::WM_EVENT_SET_BOUNDS:
170 if (window_state->allow_set_bounds_in_maximized()) {
171 window_state->SetBoundsConstrained(
172 static_cast<const wm::SetBoundsEvent*>(event)->requested_bounds());
173 } else if (current_state_type_ == wm::WINDOW_STATE_TYPE_MAXIMIZED) {
174 // Having a maximized window, it could have been created with an empty
175 // size and the caller should get his size upon leaving the maximized
176 // mode. As such we set the restore bounds to the requested bounds.
177 gfx::Rect bounds_in_parent =
178 (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
179 if (!bounds_in_parent.IsEmpty())
180 window_state->SetRestoreBoundsInParent(bounds_in_parent);
181 } else if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
182 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
183 current_state_type_ != wm::WINDOW_STATE_TYPE_PINNED &&
184 current_state_type_ != wm::WINDOW_STATE_TYPE_TRUSTED_PINNED) {
185 // In all other cases (except for minimized windows) we respect the
186 // requested bounds and center it to a fully visible area on the screen.
187 gfx::Rect bounds_in_parent =
188 (static_cast<const wm::SetBoundsEvent*>(event))->requested_bounds();
189 bounds_in_parent = GetCenteredBounds(bounds_in_parent, window_state);
190 if (bounds_in_parent != window_state->window()->GetBounds()) {
191 if (window_state->window()->IsVisible())
192 window_state->SetBoundsDirectAnimated(bounds_in_parent);
193 else
194 window_state->SetBoundsDirect(bounds_in_parent);
195 }
196 }
197 break;
198 case wm::WM_EVENT_ADDED_TO_WORKSPACE:
199 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
200 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
201 current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED) {
202 wm::WindowStateType new_state =
203 GetMaximizedOrCenteredWindowType(window_state);
204 UpdateWindow(window_state, new_state, true);
205 }
206 break;
207 case wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED:
208 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
209 UpdateBounds(window_state, true);
210 break;
211 case wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED:
212 // Don't animate on a screen rotation - just snap to new size.
213 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED)
214 UpdateBounds(window_state, false);
215 break;
216 }
217 }
218
219 wm::WindowStateType MaximizeModeWindowState::GetType() const {
220 return current_state_type_;
221 }
222
223 void MaximizeModeWindowState::AttachState(
224 wm::WindowState* window_state,
225 wm::WindowState::State* previous_state) {
226 current_state_type_ = previous_state->GetType();
227
228 gfx::Rect restore_bounds = GetRestoreBounds(window_state);
229 if (!restore_bounds.IsEmpty()) {
230 // We do not want to do a session restore to our window states. Therefore
231 // we tell the window to use the current default states instead.
232 window_state->window()->SetRestoreOverrides(restore_bounds,
233 window_state->GetShowState());
234 }
235
236 // Initialize the state to a good preset.
237 if (current_state_type_ != wm::WINDOW_STATE_TYPE_MAXIMIZED &&
238 current_state_type_ != wm::WINDOW_STATE_TYPE_MINIMIZED &&
239 current_state_type_ != wm::WINDOW_STATE_TYPE_FULLSCREEN &&
240 current_state_type_ != wm::WINDOW_STATE_TYPE_PINNED &&
241 current_state_type_ != wm::WINDOW_STATE_TYPE_TRUSTED_PINNED) {
242 UpdateWindow(window_state, GetMaximizedOrCenteredWindowType(window_state),
243 true);
244 }
245
246 window_state->set_can_be_dragged(false);
247 }
248
249 void MaximizeModeWindowState::DetachState(wm::WindowState* window_state) {
250 // From now on, we can use the default session restore mechanism again.
251 window_state->window()->SetRestoreOverrides(gfx::Rect(),
252 ui::SHOW_STATE_NORMAL);
253 window_state->set_can_be_dragged(true);
254 }
255
256 void MaximizeModeWindowState::UpdateWindow(wm::WindowState* window_state,
257 wm::WindowStateType target_state,
258 bool animated) {
259 DCHECK(target_state == wm::WINDOW_STATE_TYPE_MINIMIZED ||
260 target_state == wm::WINDOW_STATE_TYPE_MAXIMIZED ||
261 target_state == wm::WINDOW_STATE_TYPE_PINNED ||
262 target_state == wm::WINDOW_STATE_TYPE_TRUSTED_PINNED ||
263 (target_state == wm::WINDOW_STATE_TYPE_NORMAL &&
264 !window_state->CanMaximize()) ||
265 target_state == wm::WINDOW_STATE_TYPE_FULLSCREEN);
266
267 if (current_state_type_ == target_state) {
268 if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED)
269 return;
270 // If the state type did not change, update it accordingly.
271 UpdateBounds(window_state, animated);
272 return;
273 }
274
275 const wm::WindowStateType old_state_type = current_state_type_;
276 current_state_type_ = target_state;
277 window_state->UpdateWindowShowStateFromStateType();
278 window_state->NotifyPreStateTypeChange(old_state_type);
279
280 if (target_state == wm::WINDOW_STATE_TYPE_MINIMIZED) {
281 window_state->window()->SetVisibilityAnimationType(
282 wm::WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
283 window_state->window()->Hide();
284 if (window_state->IsActive())
285 window_state->Deactivate();
286 } else {
287 UpdateBounds(window_state, animated);
288 }
289
290 window_state->NotifyPostStateTypeChange(old_state_type);
291
292 if (old_state_type == wm::WINDOW_STATE_TYPE_PINNED ||
293 target_state == wm::WINDOW_STATE_TYPE_PINNED ||
294 old_state_type == wm::WINDOW_STATE_TYPE_TRUSTED_PINNED ||
295 target_state == wm::WINDOW_STATE_TYPE_TRUSTED_PINNED) {
296 WmShell::Get()->SetPinnedWindow(window_state->window());
297 }
298
299 if ((window_state->window()->GetTargetVisibility() ||
300 old_state_type == wm::WINDOW_STATE_TYPE_MINIMIZED) &&
301 !window_state->window()->GetLayer()->visible()) {
302 // The layer may be hidden if the window was previously minimized. Make
303 // sure it's visible.
304 window_state->window()->Show();
305 }
306 }
307
308 wm::WindowStateType MaximizeModeWindowState::GetMaximizedOrCenteredWindowType(
309 wm::WindowState* window_state) {
310 return window_state->CanMaximize() ? wm::WINDOW_STATE_TYPE_MAXIMIZED
311 : wm::WINDOW_STATE_TYPE_NORMAL;
312 }
313
314 void MaximizeModeWindowState::UpdateBounds(wm::WindowState* window_state,
315 bool animated) {
316 if (defer_bounds_updates_)
317 return;
318 gfx::Rect bounds_in_parent = GetBoundsInMaximizedMode(window_state);
319 // If we have a target bounds rectangle, we center it and set it
320 // accordingly.
321 if (!bounds_in_parent.IsEmpty() &&
322 bounds_in_parent != window_state->window()->GetBounds()) {
323 if (current_state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED ||
324 !window_state->window()->IsVisible() || !animated) {
325 window_state->SetBoundsDirect(bounds_in_parent);
326 } else {
327 // If we animate (to) maximized mode, we want to use the cross fade to
328 // avoid flashing.
329 if (window_state->IsMaximized())
330 window_state->SetBoundsDirectCrossFade(bounds_in_parent);
331 else
332 window_state->SetBoundsDirectAnimated(bounds_in_parent);
333 }
334 }
335 }
336
337 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698