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

Side by Side Diff: ash/wm/overview/scoped_transform_overview_window.cc

Issue 2087153003: Moves common code in ash/wm/overview to ash/common/wm/overview (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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
« no previous file with comments | « ash/wm/overview/scoped_transform_overview_window.h ('k') | ash/wm/overview/window_grid.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 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/overview/scoped_transform_overview_window.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "ash/common/material_design/material_design_controller.h"
11 #include "ash/common/wm/window_state.h"
12 #include "ash/common/wm_window.h"
13 #include "ash/common/wm_window_property.h"
14 #include "ash/wm/overview/scoped_overview_animation_settings.h"
15 #include "ash/wm/overview/scoped_overview_animation_settings_factory.h"
16 #include "ash/wm/overview/window_selector_item.h"
17 #include "base/macros.h"
18 #include "third_party/skia/include/core/SkPaint.h"
19 #include "third_party/skia/include/core/SkPath.h"
20 #include "third_party/skia/include/core/SkRect.h"
21 #include "ui/compositor/layer.h"
22 #include "ui/compositor/layer_delegate.h"
23 #include "ui/compositor/paint_recorder.h"
24 #include "ui/gfx/geometry/rect.h"
25 #include "ui/gfx/geometry/safe_integer_conversions.h"
26 #include "ui/gfx/transform_util.h"
27
28 using WmWindows = std::vector<ash::WmWindow*>;
29
30 namespace ash {
31
32 namespace {
33
34 // The opacity level that windows will be set to when they are restored.
35 const float kRestoreWindowOpacity = 1.0f;
36
37 // Alpha value used to paint mask layer that masks the original window header.
38 const int kOverviewContentMaskAlpha = 255;
39
40 WmWindow* GetTransientRoot(WmWindow* window) {
41 while (window->GetTransientParent())
42 window = window->GetTransientParent();
43 return window;
44 }
45
46 std::unique_ptr<ScopedOverviewAnimationSettings>
47 CreateScopedOverviewAnimationSettings(OverviewAnimationType animation_type,
48 WmWindow* window) {
49 return ScopedOverviewAnimationSettingsFactory::Get()
50 ->CreateOverviewAnimationSettings(animation_type, window);
51 }
52
53 // An iterator class that traverses a WmWindow and all of its transient
54 // descendants.
55 class TransientDescendantIterator {
56 public:
57 // Creates an empty iterator.
58 TransientDescendantIterator();
59
60 // Copy constructor required for iterator purposes.
61 TransientDescendantIterator(
62 const TransientDescendantIterator& other) = default;
63
64 // Iterates over |root_window| and all of its transient descendants.
65 // Note |root_window| must not have a transient parent.
66 explicit TransientDescendantIterator(WmWindow* root_window);
67
68 // Prefix increment operator. This assumes there are more items (i.e.
69 // *this != TransientDescendantIterator()).
70 const TransientDescendantIterator& operator++();
71
72 // Comparison for STL-based loops.
73 bool operator!=(const TransientDescendantIterator& other) const;
74
75 // Dereference operator for STL-compatible iterators.
76 WmWindow* operator*() const;
77
78 private:
79 // Explicit assignment operator defined because an explicit copy constructor
80 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
81 TransientDescendantIterator& operator=(
82 const TransientDescendantIterator& other) = default;
83
84 // The current window that |this| refers to. A null |current_window_| denotes
85 // an empty iterator and is used as the last possible value in the traversal.
86 WmWindow* current_window_;
87 };
88
89 // Provides a virtual container implementing begin() and end() for a sequence of
90 // TransientDescendantIterators. This can be used in range-based for loops.
91 class TransientDescendantIteratorRange {
92 public:
93 explicit TransientDescendantIteratorRange(
94 const TransientDescendantIterator& begin);
95
96 // Copy constructor required for iterator purposes.
97 TransientDescendantIteratorRange(
98 const TransientDescendantIteratorRange& other) = default;
99
100 const TransientDescendantIterator& begin() const { return begin_; }
101 const TransientDescendantIterator& end() const { return end_; }
102
103 private:
104 // Explicit assignment operator defined because an explicit copy constructor
105 // is needed and therefore the DISALLOW_COPY_AND_ASSIGN macro cannot be used.
106 TransientDescendantIteratorRange& operator=(
107 const TransientDescendantIteratorRange& other) = default;
108
109 TransientDescendantIterator begin_;
110 TransientDescendantIterator end_;
111 };
112
113 TransientDescendantIterator::TransientDescendantIterator()
114 : current_window_(nullptr) {
115 }
116
117 TransientDescendantIterator::TransientDescendantIterator(WmWindow* root_window)
118 : current_window_(root_window) {
119 DCHECK(!root_window->GetTransientParent());
120 }
121
122 // Performs a pre-order traversal of the transient descendants.
123 const TransientDescendantIterator&
124 TransientDescendantIterator::operator++() {
125 DCHECK(current_window_);
126
127 const WmWindows transient_children = current_window_->GetTransientChildren();
128
129 if (!transient_children.empty()) {
130 current_window_ = transient_children.front();
131 } else {
132 while (current_window_) {
133 WmWindow* parent = current_window_->GetTransientParent();
134 if (!parent) {
135 current_window_ = nullptr;
136 break;
137 }
138 const WmWindows transient_siblings = parent->GetTransientChildren();
139 auto iter = std::find(transient_siblings.begin(),
140 transient_siblings.end(), current_window_);
141 ++iter;
142 if (iter != transient_siblings.end()) {
143 current_window_ = *iter;
144 break;
145 }
146 current_window_ = current_window_->GetTransientParent();
147 }
148 }
149 return *this;
150 }
151
152 bool TransientDescendantIterator::operator!=(
153 const TransientDescendantIterator& other) const {
154 return current_window_ != other.current_window_;
155 }
156
157 WmWindow* TransientDescendantIterator::operator*() const {
158 return current_window_;
159 }
160
161 TransientDescendantIteratorRange::TransientDescendantIteratorRange(
162 const TransientDescendantIterator& begin)
163 : begin_(begin) {
164 }
165
166 TransientDescendantIteratorRange GetTransientTreeIterator(WmWindow* window) {
167 return TransientDescendantIteratorRange(
168 TransientDescendantIterator(GetTransientRoot(window)));
169 }
170
171 } // namespace
172
173 // Mask layer that clips the window's original header in overview mode.
174 // Only used with Material Design.
175 class ScopedTransformOverviewWindow::OverviewContentMask
176 : public ui::LayerDelegate {
177 public:
178 OverviewContentMask(int inset, int radius);
179 ~OverviewContentMask() override;
180
181 ui::Layer* layer() { return &layer_; }
182
183 // Overridden from LayerDelegate.
184 void OnPaintLayer(const ui::PaintContext& context) override;
185 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
186 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
187 base::Closure PrepareForLayerBoundsChange() override;
188
189 private:
190 ui::Layer layer_;
191 int inset_;
192 int radius_;
193
194 DISALLOW_COPY_AND_ASSIGN(OverviewContentMask);
195 };
196
197 ScopedTransformOverviewWindow::OverviewContentMask::OverviewContentMask(
198 int inset,
199 int radius)
200 : layer_(ui::LAYER_TEXTURED), inset_(inset), radius_(radius) {
201 layer_.set_delegate(this);
202 }
203
204 ScopedTransformOverviewWindow::OverviewContentMask::~OverviewContentMask() {
205 layer_.set_delegate(nullptr);
206 }
207
208 void ScopedTransformOverviewWindow::OverviewContentMask::OnPaintLayer(
209 const ui::PaintContext& context) {
210 ui::PaintRecorder recorder(context, layer()->size());
211 gfx::Rect bounds(layer()->bounds().size());
212 bounds.Inset(0, inset_, 0, 0);
213
214 // Tile a window into an area, rounding the bottom corners.
215 const SkRect rect = gfx::RectToSkRect(bounds);
216 const SkScalar corner_radius_scalar = SkIntToScalar(radius_);
217 SkScalar radii[8] = {0,
218 0, // top-left
219 0,
220 0, // top-right
221 corner_radius_scalar,
222 corner_radius_scalar, // bottom-right
223 corner_radius_scalar,
224 corner_radius_scalar}; // bottom-left
225 SkPath path;
226 path.addRoundRect(rect, radii, SkPath::kCW_Direction);
227
228 // Set a mask.
229 SkPaint paint;
230 paint.setAlpha(kOverviewContentMaskAlpha);
231 paint.setStyle(SkPaint::kFill_Style);
232 paint.setAntiAlias(true);
233 recorder.canvas()->DrawPath(path, paint);
234 }
235
236 void ScopedTransformOverviewWindow::OverviewContentMask::
237 OnDeviceScaleFactorChanged(float device_scale_factor) {
238 // Redrawing will take care of scale factor change.
239 }
240
241 base::Closure ScopedTransformOverviewWindow::OverviewContentMask::
242 PrepareForLayerBoundsChange() {
243 return base::Closure();
244 }
245
246 ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(WmWindow* window)
247 : window_(window),
248 minimized_(window->GetShowState() == ui::SHOW_STATE_MINIMIZED),
249 ignored_by_shelf_(window->GetWindowState()->ignored_by_shelf()),
250 overview_started_(false),
251 original_transform_(window->GetTargetTransform()),
252 original_opacity_(window->GetTargetOpacity()) {}
253
254 ScopedTransformOverviewWindow::~ScopedTransformOverviewWindow() {
255 }
256
257 void ScopedTransformOverviewWindow::RestoreWindow() {
258 if (ash::MaterialDesignController::IsOverviewMaterial()) {
259 window()->GetLayer()->SetMaskLayer(nullptr);
260 mask_.reset();
261 }
262
263 ScopedAnimationSettings animation_settings_list;
264 BeginScopedAnimation(
265 OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW,
266 &animation_settings_list);
267 SetTransform(window()->GetRootWindow(), original_transform_, 0);
268
269 std::unique_ptr<ScopedOverviewAnimationSettings> animation_settings =
270 CreateScopedOverviewAnimationSettings(
271 OverviewAnimationType::OVERVIEW_ANIMATION_LAY_OUT_SELECTOR_ITEMS,
272 window_);
273 gfx::Transform transform;
274 if (minimized_ && window_->GetShowState() != ui::SHOW_STATE_MINIMIZED) {
275 // Setting opacity 0 and visible false ensures that the property change
276 // to SHOW_STATE_MINIMIZED will not animate the window from its original
277 // bounds to the minimized position.
278 // Hiding the window needs to be done before the target opacity is 0,
279 // otherwise the layer's visibility will not be updated
280 // (See VisibilityController::UpdateLayerVisibility).
281 window_->Hide();
282 window_->SetOpacity(0);
283 window_->SetShowState(ui::SHOW_STATE_MINIMIZED);
284 }
285 window_->GetWindowState()->set_ignored_by_shelf(ignored_by_shelf_);
286 SetOpacity(original_opacity_);
287 }
288
289 void ScopedTransformOverviewWindow::BeginScopedAnimation(
290 OverviewAnimationType animation_type,
291 ScopedAnimationSettings* animation_settings) {
292 for (const auto& window : GetTransientTreeIterator(window_)) {
293 animation_settings->push_back(
294 CreateScopedOverviewAnimationSettings(animation_type, window));
295 }
296 }
297
298 bool ScopedTransformOverviewWindow::Contains(const WmWindow* target) const {
299 for (const auto& window : GetTransientTreeIterator(window_)) {
300 if (window->Contains(target))
301 return true;
302 }
303 return false;
304 }
305
306 gfx::Rect ScopedTransformOverviewWindow::GetTargetBoundsInScreen() const {
307 gfx::Rect bounds;
308 for (const auto& window : GetTransientTreeIterator(window_)) {
309 // Ignore other window types when computing bounding box of window
310 // selector target item.
311 if (window != window_ && window->GetType() != ui::wm::WINDOW_TYPE_NORMAL &&
312 window->GetType() != ui::wm::WINDOW_TYPE_PANEL) {
313 continue;
314 }
315 bounds.Union(
316 window->GetParent()->ConvertRectToScreen(window->GetTargetBounds()));
317 }
318 return bounds;
319 }
320
321 void ScopedTransformOverviewWindow::ShowWindowIfMinimized() {
322 if (minimized_ && window_->GetShowState() == ui::SHOW_STATE_MINIMIZED)
323 window_->Show();
324 }
325
326 void ScopedTransformOverviewWindow::ShowWindowOnExit() {
327 if (minimized_) {
328 minimized_ = false;
329 original_transform_ = gfx::Transform();
330 original_opacity_ = kRestoreWindowOpacity;
331 }
332 }
333
334 void ScopedTransformOverviewWindow::OnWindowDestroyed() {
335 window_ = nullptr;
336 }
337
338 float ScopedTransformOverviewWindow::GetItemScale(const gfx::Size& source,
339 const gfx::Size& target,
340 int top_view_inset,
341 int title_height) {
342 if (ash::MaterialDesignController::IsOverviewMaterial()) {
343 return std::min(2.0f, static_cast<float>((target.height() - title_height)) /
344 (source.height() - top_view_inset));
345 }
346 return std::min(
347 1.0f, std::min(static_cast<float>(target.width()) / source.width(),
348 static_cast<float>(target.height()) / source.height()));
349 }
350
351 gfx::Rect ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
352 const gfx::Rect& rect,
353 const gfx::Rect& bounds,
354 int top_view_inset,
355 int title_height) {
356 DCHECK(!rect.IsEmpty());
357 DCHECK_LE(top_view_inset, rect.height());
358 const float scale =
359 GetItemScale(rect.size(), bounds.size(), top_view_inset, title_height);
360 if (!ash::MaterialDesignController::IsOverviewMaterial()) {
361 return gfx::Rect(
362 bounds.x() + 0.5 * (bounds.width() - scale * rect.width()),
363 bounds.y() + title_height - scale * top_view_inset +
364 0.5 * (bounds.height() -
365 (title_height + scale * (rect.height() - top_view_inset))),
366 rect.width() * scale, rect.height() * scale);
367 }
368 const int horizontal_offset = gfx::ToFlooredInt(
369 0.5 * (bounds.width() - gfx::ToFlooredInt(scale * rect.width())));
370 const int width = bounds.width() - 2 * horizontal_offset;
371 const int vertical_offset =
372 title_height - gfx::ToCeiledInt(scale * top_view_inset);
373 const int height = std::min(gfx::ToCeiledInt(scale * rect.height()),
374 bounds.height() - vertical_offset);
375 return gfx::Rect(bounds.x() + horizontal_offset, bounds.y() + vertical_offset,
376 width, height);
377 }
378
379 gfx::Transform ScopedTransformOverviewWindow::GetTransformForRect(
380 const gfx::Rect& src_rect,
381 const gfx::Rect& dst_rect) {
382 DCHECK(!src_rect.IsEmpty());
383 gfx::Transform transform;
384 transform.Translate(dst_rect.x() - src_rect.x(),
385 dst_rect.y() - src_rect.y());
386 transform.Scale(static_cast<float>(dst_rect.width()) / src_rect.width(),
387 static_cast<float>(dst_rect.height()) / src_rect.height());
388 return transform;
389 }
390
391 void ScopedTransformOverviewWindow::SetTransform(
392 WmWindow* root_window,
393 const gfx::Transform& transform,
394 int radius) {
395 DCHECK(overview_started_);
396
397 if (ash::MaterialDesignController::IsOverviewMaterial()) {
398 mask_.reset(new OverviewContentMask(
399 window()->GetIntProperty(WmWindowProperty::TOP_VIEW_INSET), radius));
400 mask_->layer()->SetBounds(GetTargetBoundsInScreen());
401 window()->GetLayer()->SetMaskLayer(mask_->layer());
402 }
403
404 gfx::Point target_origin(GetTargetBoundsInScreen().origin());
405
406 for (const auto& window : GetTransientTreeIterator(window_)) {
407 WmWindow* parent_window = window->GetParent();
408 gfx::Point original_origin =
409 parent_window->ConvertRectToScreen(window->GetTargetBounds()).origin();
410 gfx::Transform new_transform = TransformAboutPivot(
411 gfx::Point(target_origin.x() - original_origin.x(),
412 target_origin.y() - original_origin.y()),
413 transform);
414 window->SetTransform(new_transform);
415 }
416 }
417
418 void ScopedTransformOverviewWindow::SetOpacity(float opacity) {
419 for (const auto& window : GetTransientTreeIterator(window_)) {
420 window->SetOpacity(opacity);
421 }
422 }
423
424 void ScopedTransformOverviewWindow::Close() {
425 GetTransientRoot(window_)->CloseWidget();
426 }
427
428 void ScopedTransformOverviewWindow::PrepareForOverview() {
429 DCHECK(!overview_started_);
430 overview_started_ = true;
431 window_->GetWindowState()->set_ignored_by_shelf(true);
432 ShowWindowIfMinimized();
433 }
434
435 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/overview/scoped_transform_overview_window.h ('k') | ash/wm/overview/window_grid.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698