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

Side by Side Diff: ash/wm/system_modal_container_layout_manager.cc

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

Powered by Google App Engine
This is Rietveld 408576698