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

Side by Side Diff: ash/common/wm/system_modal_container_layout_manager.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 (c) 2012 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/system_modal_container_layout_manager.h"
6
7 #include <cmath>
8
9 #include "ash/common/session/session_state_delegate.h"
10 #include "ash/common/wm/window_dimmer.h"
11 #include "ash/common/wm_shell.h"
12 #include "ash/common/wm_window.h"
13 #include "ash/public/cpp/shell_window_ids.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/stl_util.h"
16 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/window.h"
18 #include "ui/keyboard/keyboard_controller.h"
19
20 namespace ash {
21 namespace {
22
23 // The center point of the window can diverge this much from the center point
24 // of the container to be kept centered upon resizing operations.
25 const int kCenterPixelDelta = 32;
26
27 ui::ModalType GetModalType(WmWindow* window) {
28 return static_cast<ui::ModalType>(
29 window->aura_window()->GetProperty(aura::client::kModalKey));
30 }
31
32 bool HasTransientAncestor(const WmWindow* window, const WmWindow* ancestor) {
33 const WmWindow* transient_parent = window->GetTransientParent();
34 if (transient_parent == ancestor)
35 return true;
36 return transient_parent ? HasTransientAncestor(transient_parent, ancestor)
37 : false;
38 }
39 }
40
41 ////////////////////////////////////////////////////////////////////////////////
42 // SystemModalContainerLayoutManager, public:
43
44 SystemModalContainerLayoutManager::SystemModalContainerLayoutManager(
45 WmWindow* container)
46 : container_(container) {}
47
48 SystemModalContainerLayoutManager::~SystemModalContainerLayoutManager() {
49 if (keyboard::KeyboardController::GetInstance())
50 keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
51 }
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // SystemModalContainerLayoutManager, WmLayoutManager implementation:
55
56 void SystemModalContainerLayoutManager::OnChildWindowVisibilityChanged(
57 WmWindow* window,
58 bool visible) {
59 if (GetModalType(window) != ui::MODAL_TYPE_SYSTEM)
60 return;
61
62 if (window->IsVisible()) {
63 DCHECK(!base::ContainsValue(modal_windows_, window));
64 AddModalWindow(window);
65 } else {
66 if (RemoveModalWindow(window))
67 WmShell::Get()->OnModalWindowRemoved(window);
68 }
69 }
70
71 void SystemModalContainerLayoutManager::OnWindowResized() {
72 PositionDialogsAfterWorkAreaResize();
73 }
74
75 void SystemModalContainerLayoutManager::OnWindowAddedToLayout(WmWindow* child) {
76 DCHECK(child->GetType() == ui::wm::WINDOW_TYPE_NORMAL ||
77 child->GetType() == ui::wm::WINDOW_TYPE_POPUP);
78 // TODO(mash): IsUserSessionBlocked() depends on knowing the login state. We
79 // need a non-stub version of SessionStateDelegate. crbug.com/648964
80 if (!WmShell::Get()->IsRunningInMash()) {
81 DCHECK(container_->GetShellWindowId() !=
82 kShellWindowId_LockSystemModalContainer ||
83 WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked());
84 }
85 // Since this is for SystemModal, there is no good reason to add windows
86 // other than MODAL_TYPE_NONE or MODAL_TYPE_SYSTEM. DCHECK to avoid simple
87 // mistake.
88 DCHECK_NE(GetModalType(child), ui::MODAL_TYPE_CHILD);
89 DCHECK_NE(GetModalType(child), ui::MODAL_TYPE_WINDOW);
90
91 child->aura_window()->AddObserver(this);
92 if (GetModalType(child) == ui::MODAL_TYPE_SYSTEM && child->IsVisible())
93 AddModalWindow(child);
94 }
95
96 void SystemModalContainerLayoutManager::OnWillRemoveWindowFromLayout(
97 WmWindow* child) {
98 child->aura_window()->RemoveObserver(this);
99 windows_to_center_.erase(child);
100 if (GetModalType(child) == ui::MODAL_TYPE_SYSTEM)
101 RemoveModalWindow(child);
102 }
103
104 void SystemModalContainerLayoutManager::SetChildBounds(
105 WmWindow* child,
106 const gfx::Rect& requested_bounds) {
107 WmSnapToPixelLayoutManager::SetChildBounds(child, requested_bounds);
108 if (IsBoundsCentered(requested_bounds))
109 windows_to_center_.insert(child);
110 else
111 windows_to_center_.erase(child);
112 }
113
114 ////////////////////////////////////////////////////////////////////////////////
115 // SystemModalContainerLayoutManager, aura::WindowObserver implementation:
116
117 void SystemModalContainerLayoutManager::OnWindowPropertyChanged(
118 aura::Window* window,
119 const void* key,
120 intptr_t old) {
121 if (key != aura::client::kModalKey || !window->IsVisible())
122 return;
123
124 WmWindow* wm_window = WmWindow::Get(window);
125 if (window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM) {
126 if (base::ContainsValue(modal_windows_, wm_window))
127 return;
128 AddModalWindow(wm_window);
129 } else {
130 if (RemoveModalWindow(wm_window))
131 WmShell::Get()->OnModalWindowRemoved(wm_window);
132 }
133 }
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // SystemModalContainerLayoutManager, Keyboard::KeybaordControllerObserver
137 // implementation:
138
139 void SystemModalContainerLayoutManager::OnKeyboardBoundsChanging(
140 const gfx::Rect& new_bounds) {
141 PositionDialogsAfterWorkAreaResize();
142 }
143
144 void SystemModalContainerLayoutManager::OnKeyboardClosed() {}
145
146 bool SystemModalContainerLayoutManager::IsPartOfActiveModalWindow(
147 WmWindow* window) {
148 return modal_window() &&
149 (modal_window()->Contains(window) ||
150 HasTransientAncestor(window->GetToplevelWindowForFocus(),
151 modal_window()));
152 }
153
154 bool SystemModalContainerLayoutManager::ActivateNextModalWindow() {
155 if (modal_windows_.empty())
156 return false;
157 modal_window()->Activate();
158 return true;
159 }
160
161 void SystemModalContainerLayoutManager::CreateModalBackground() {
162 if (!window_dimmer_) {
163 window_dimmer_ = base::MakeUnique<WindowDimmer>(container_);
164 window_dimmer_->window()->SetName(
165 "SystemModalContainerLayoutManager.ModalBackground");
166 // There isn't always a keyboard controller.
167 if (keyboard::KeyboardController::GetInstance())
168 keyboard::KeyboardController::GetInstance()->AddObserver(this);
169 }
170 window_dimmer_->window()->Show();
171 }
172
173 void SystemModalContainerLayoutManager::DestroyModalBackground() {
174 if (!window_dimmer_)
175 return;
176
177 if (keyboard::KeyboardController::GetInstance())
178 keyboard::KeyboardController::GetInstance()->RemoveObserver(this);
179 window_dimmer_.reset();
180 }
181
182 // static
183 bool SystemModalContainerLayoutManager::IsModalBackground(WmWindow* window) {
184 int id = window->GetParent()->GetShellWindowId();
185 if (id != kShellWindowId_SystemModalContainer &&
186 id != kShellWindowId_LockSystemModalContainer)
187 return false;
188 SystemModalContainerLayoutManager* layout_manager =
189 static_cast<SystemModalContainerLayoutManager*>(
190 window->GetParent()->GetLayoutManager());
191 return layout_manager->window_dimmer_ &&
192 layout_manager->window_dimmer_->window() == window;
193 }
194
195 ////////////////////////////////////////////////////////////////////////////////
196 // SystemModalContainerLayoutManager, private:
197
198 void SystemModalContainerLayoutManager::AddModalWindow(WmWindow* window) {
199 if (modal_windows_.empty()) {
200 WmWindow* capture_window = WmShell::Get()->GetCaptureWindow();
201 if (capture_window)
202 capture_window->ReleaseCapture();
203 }
204 DCHECK(window->IsVisible());
205 DCHECK(!base::ContainsValue(modal_windows_, window));
206
207 modal_windows_.push_back(window);
208 WmShell::Get()->CreateModalBackground(window);
209 window->GetParent()->StackChildAtTop(window);
210
211 gfx::Rect target_bounds = window->GetBounds();
212 target_bounds.AdjustToFit(GetUsableDialogArea());
213 window->SetBounds(target_bounds);
214 }
215
216 bool SystemModalContainerLayoutManager::RemoveModalWindow(WmWindow* window) {
217 auto it = std::find(modal_windows_.begin(), modal_windows_.end(), window);
218 if (it == modal_windows_.end())
219 return false;
220 modal_windows_.erase(it);
221 return true;
222 }
223
224 void SystemModalContainerLayoutManager::PositionDialogsAfterWorkAreaResize() {
225 if (modal_windows_.empty())
226 return;
227
228 for (WmWindow* window : modal_windows_)
229 window->SetBounds(GetCenteredAndOrFittedBounds(window));
230 }
231
232 gfx::Rect SystemModalContainerLayoutManager::GetUsableDialogArea() const {
233 // Instead of resizing the system modal container, we move only the modal
234 // windows. This way we avoid flashing lines upon resize animation and if the
235 // keyboard will not fill left to right, the background is still covered.
236 gfx::Rect valid_bounds = container_->GetBounds();
237 keyboard::KeyboardController* keyboard_controller =
238 keyboard::KeyboardController::GetInstance();
239 if (keyboard_controller) {
240 gfx::Rect bounds = keyboard_controller->current_keyboard_bounds();
241 if (!bounds.IsEmpty()) {
242 valid_bounds.set_height(
243 std::max(0, valid_bounds.height() - bounds.height()));
244 }
245 }
246 return valid_bounds;
247 }
248
249 gfx::Rect SystemModalContainerLayoutManager::GetCenteredAndOrFittedBounds(
250 const WmWindow* window) {
251 gfx::Rect target_bounds;
252 gfx::Rect usable_area = GetUsableDialogArea();
253 if (windows_to_center_.count(window) > 0) {
254 // Keep the dialog centered if it was centered before.
255 target_bounds = usable_area;
256 target_bounds.ClampToCenteredSize(window->GetBounds().size());
257 } else {
258 // Keep the dialog within the usable area.
259 target_bounds = window->GetBounds();
260 target_bounds.AdjustToFit(usable_area);
261 }
262 if (usable_area != container_->GetBounds()) {
263 // Don't clamp the dialog for the keyboard. Keep the size as it is but make
264 // sure that the top remains visible.
265 // TODO(skuhne): M37 should add over scroll functionality to address this.
266 target_bounds.set_size(window->GetBounds().size());
267 }
268 return target_bounds;
269 }
270
271 bool SystemModalContainerLayoutManager::IsBoundsCentered(
272 const gfx::Rect& bounds) const {
273 gfx::Point window_center = bounds.CenterPoint();
274 gfx::Point container_center = GetUsableDialogArea().CenterPoint();
275 return std::abs(window_center.x() - container_center.x()) <
276 kCenterPixelDelta &&
277 std::abs(window_center.y() - container_center.y()) < kCenterPixelDelta;
278 }
279
280 } // namespace ash
OLDNEW
« no previous file with comments | « ash/common/wm/system_modal_container_layout_manager.h ('k') | ash/common/wm/window_animation_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698