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

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

Issue 22715005: Use overview mode for alt-tab cycling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/wm/window_selector.h" 5 #include "ash/wm/window_selector.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ash/screen_ash.h" 9 #include "ash/screen_ash.h"
10 #include "ash/shell.h" 10 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h" 11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/window_selector_delegate.h" 12 #include "ash/wm/window_selector_delegate.h"
13 #include "ash/wm/window_util.h" 13 #include "ash/wm/window_util.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "third_party/skia/include/core/SkColor.h"
15 #include "ui/aura/client/aura_constants.h" 16 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/client/screen_position_client.h"
16 #include "ui/aura/root_window.h" 18 #include "ui/aura/root_window.h"
17 #include "ui/aura/window.h" 19 #include "ui/aura/window.h"
18 #include "ui/base/events/event.h" 20 #include "ui/base/events/event.h"
21 #include "ui/compositor/layer_animation_observer.h"
19 #include "ui/compositor/scoped_layer_animation_settings.h" 22 #include "ui/compositor/scoped_layer_animation_settings.h"
23 #include "ui/gfx/display.h"
20 #include "ui/gfx/interpolated_transform.h" 24 #include "ui/gfx/interpolated_transform.h"
21 #include "ui/gfx/transform_util.h" 25 #include "ui/gfx/transform_util.h"
26 #include "ui/views/corewm/shadow_types.h"
22 #include "ui/views/corewm/window_animations.h" 27 #include "ui/views/corewm/window_animations.h"
28 #include "ui/views/corewm/window_util.h"
29 #include "ui/views/widget/widget.h"
23 30
24 namespace ash { 31 namespace ash {
25 32
26 namespace { 33 namespace {
27 34
28 const float kCardAspectRatio = 4.0f / 3.0f; 35 const float kCardAspectRatio = 4.0f / 3.0f;
29 const int kWindowMargin = 20; 36 const int kWindowMargin = 30;
30 const int kMinCardsMajor = 3; 37 const int kMinCardsMajor = 3;
31 const int kOverviewTransitionMilliseconds = 100; 38 const int kOverviewTransitionMilliseconds = 100;
32 39 const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK;
33 // Applies a transform to |window| to fit within |target_bounds| while 40 const float kWindowSelectorSelectionOpacity = 0.5f;
34 // maintaining its aspect ratio. 41 const int kWindowSelectorSelectionPadding = 15;
35 void TransformWindowToFitBounds(aura::Window* window, 42
36 const gfx::Rect& target_bounds) { 43 // Creates a copy of |window| with |recreated_layer| in the |target_root|.
37 const gfx::Rect bounds = window->bounds(); 44 views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root,
45 aura::Window* src_window,
46 ui::Layer* recreated_layer) {
47 views::Widget* widget = new views::Widget;
48 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
49 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
50 params.parent = src_window->parent();
51 params.can_activate = false;
52 params.keep_on_top = true;
53 widget->set_focus_on_creation(false);
54 widget->Init(params);
55 widget->SetVisibilityChangedAnimationsEnabled(false);
56 widget->GetNativeWindow()->SetName("OverviewWindowCopy");
Daniel Erat 2013/08/09 20:54:35 nit: include |src_window|'s id and/or name here?
flackr 2013/08/09 22:15:36 Done.
57 views::corewm::SetShadowType(widget->GetNativeWindow(),
58 views::corewm::SHADOW_TYPE_RECTANGULAR);
59
60 // Set the bounds in the target root window.
61 gfx::Display target_display =
62 Shell::GetScreen()->GetDisplayNearestWindow(target_root);
63 aura::client::ScreenPositionClient* screen_position_client =
64 aura::client::GetScreenPositionClient(src_window->GetRootWindow());
65 if (screen_position_client && target_display.is_valid()) {
66 screen_position_client->SetBounds(widget->GetNativeWindow(),
67 src_window->GetBoundsInScreen(), target_display);
68 } else {
69 widget->SetBounds(src_window->GetBoundsInScreen());
70 }
71 widget->StackAbove(src_window);
72
73 // Move the |recreated_layer| to the newly created window.
74 recreated_layer->set_delegate(src_window->layer()->delegate());
75 gfx::Rect layer_bounds = recreated_layer->bounds();
76 layer_bounds.set_origin(gfx::Point(0, 0));
77 recreated_layer->SetBounds(layer_bounds);
78 recreated_layer->SetVisible(false);
79 recreated_layer->parent()->Remove(recreated_layer);
80
81 aura::Window* window = widget->GetNativeWindow();
82 recreated_layer->SetVisible(true);
83 window->layer()->Add(recreated_layer);
84 window->layer()->StackAtTop(recreated_layer);
85 window->layer()->SetOpacity(1);
86 window->Show();
87 return widget;
88 }
89
90 // An observer which closes the widget and deletes the layer after an
91 // animation finishes.
92 class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver {
93 public:
94 CleanupWidgetAfterAnimationObserver(views::Widget* widget, ui::Layer* layer);
95
96 virtual void OnLayerAnimationEnded(
97 ui::LayerAnimationSequence* sequence) OVERRIDE;
98 virtual void OnLayerAnimationAborted(
99 ui::LayerAnimationSequence* sequence) OVERRIDE;
100 virtual void OnLayerAnimationScheduled(
101 ui::LayerAnimationSequence* sequence) OVERRIDE;
102
103 protected:
104 virtual ~CleanupWidgetAfterAnimationObserver();
105
106 private:
107 views::Widget* widget_;
108 ui::Layer* layer_;
109
110 DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
111 };
112
113 CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
114 views::Widget* widget,
115 ui::Layer* layer)
116 : widget_(widget),
117 layer_(layer) {
118 widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
119 }
120
121 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
122 ui::LayerAnimationSequence* sequence) {
123 delete this;
124 }
125
126 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
127 ui::LayerAnimationSequence* sequence) {
128 delete this;
129 }
130
131 void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
132 ui::LayerAnimationSequence* sequence) {
133 }
134
135 CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
136 widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
137 widget_->Close();
138 widget_ = NULL;
139 if (layer_) {
140 views::corewm::DeepDeleteLayers(layer_);
141 layer_ = NULL;
142 }
143 }
144
145 // The animation settings used for window selector animations.
146 class WindowSelectorAnimationSettings
147 : public ui::ScopedLayerAnimationSettings {
148 public:
149 WindowSelectorAnimationSettings(aura::Window* window) :
150 ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
151 SetPreemptionStrategy(
152 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
153 SetTransitionDuration(
154 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
155 }
156
157 virtual ~WindowSelectorAnimationSettings() {
158 }
159 };
160
161 } // namespace
162
163 class WindowSelectorWindow {
164 public:
165 explicit WindowSelectorWindow(aura::Window* window);
166 virtual ~WindowSelectorWindow();
167
168 aura::Window* window() { return window_; }
169 const aura::Window* window() const { return window_; }
170
171 // Returns true if this window selector window contains the |target|. This is
172 // used to determine if an event targetted this window.
173 bool Contains(const aura::Window* target) const;
174
175 // Restores this window on exit rather than returning it to a minimized state
176 // if it was minimized on entering overview mode.
177 void RestoreWindowOnExit();
178
179 // Informs the WindowSelectorWindow that the window being watched was
180 // destroyed. This resets the internal window pointer to avoid calling
181 // anything on the window at destruction time.
182 void OnWindowDestroyed();
183
184 // Applies a transform to the window to fit within |target_bounds| while
185 // maintaining its aspect ratio.
186 void TransformToFitBounds(aura::RootWindow* root_window,
187 const gfx::Rect& target_bounds);
188
189 gfx::Rect bounds() { return fit_bounds_; }
190
191 private:
192 // A weak pointer to the real window in the overview.
193 aura::Window* window_;
194
195 // A copy of the window used to transition the window to another root.
196 views::Widget* window_copy_;
197
198 // A weak pointer to a deep copy of the window's layers.
199 ui::Layer* layer_;
200
201 // If true, the window was minimized and should be restored if the window
202 // was not selected.
203 bool minimized_;
204
205 // The original transform of the window before entering overview mode.
206 gfx::Transform original_transform_;
207
208 // The bounds this window is fit to.
209 gfx::Rect fit_bounds_;
210
211 DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow);
212 };
213
214 WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
Daniel Erat 2013/08/09 20:54:35 doesn't need to happen here, but it'd probably be
flackr 2013/08/09 22:15:36 Added TODO.
215 : window_(window),
216 window_copy_(NULL),
217 layer_(NULL),
218 minimized_(window->GetProperty(aura::client::kShowStateKey) ==
219 ui::SHOW_STATE_MINIMIZED),
220 original_transform_(window->layer()->transform()) {
221 if (minimized_)
222 window_->Show();
223 }
224
225 WindowSelectorWindow::~WindowSelectorWindow() {
226 if (window_) {
227 WindowSelectorAnimationSettings animation_settings(window_);
228 gfx::Transform transform;
229 window_->SetTransform(original_transform_);
230 if (minimized_) {
231 // Setting opacity 0 and visible false ensures that the property change
232 // to SHOW_STATE_MINIMIZED will not animate the window from its original
233 // bounds to the minimized position.
234 window_->layer()->SetOpacity(0);
235 window_->layer()->SetVisible(false);
236 window_->SetProperty(aura::client::kShowStateKey,
237 ui::SHOW_STATE_MINIMIZED);
238 }
239 }
240 // If a copy of the window was created, clean it up.
241 if (window_copy_) {
242 if (window_) {
243 // If the initial window wasn't destroyed, the copy needs to be animated
244 // out. CleanupWidgetAfterAnimationObserver will destroy the widget and
245 // layer after the animation is complete.
246 new CleanupWidgetAfterAnimationObserver(window_copy_, layer_);
247 WindowSelectorAnimationSettings animation_settings(
248 window_copy_->GetNativeWindow());
249 window_copy_->GetNativeWindow()->SetTransform(original_transform_);
250 } else {
251 window_copy_->Close();
252 if (layer_)
253 views::corewm::DeepDeleteLayers(layer_);
254 }
255 window_copy_ = NULL;
256 layer_ = NULL;
257 }
258 }
259
260 bool WindowSelectorWindow::Contains(const aura::Window* window) const {
261 if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
262 return true;
263 return window_->Contains(window);
264 }
265
266 void WindowSelectorWindow::RestoreWindowOnExit() {
267 minimized_ = false;
268 original_transform_ = gfx::Transform();
269 }
270
271 void WindowSelectorWindow::OnWindowDestroyed() {
272 window_ = NULL;
273 }
274
275 void WindowSelectorWindow::TransformToFitBounds(
276 aura::RootWindow* root_window,
277 const gfx::Rect& target_bounds) {
278 fit_bounds_ = target_bounds;
279 const gfx::Rect bounds = window_->GetBoundsInScreen();
38 float scale = std::min(1.0f, 280 float scale = std::min(1.0f,
39 std::min(static_cast<float>(target_bounds.width()) / bounds.width(), 281 std::min(static_cast<float>(target_bounds.width()) / bounds.width(),
40 static_cast<float>(target_bounds.height()) / bounds.height())); 282 static_cast<float>(target_bounds.height()) / bounds.height()));
41 gfx::Transform transform; 283 gfx::Transform transform;
42 gfx::Vector2d offset( 284 gfx::Vector2d offset(
43 0.5 * (target_bounds.width() - scale * bounds.width()), 285 0.5 * (target_bounds.width() - scale * bounds.width()),
44 0.5 * (target_bounds.height() - scale * bounds.height())); 286 0.5 * (target_bounds.height() - scale * bounds.height()));
45 transform.Translate(target_bounds.x() - bounds.x() + offset.x(), 287 transform.Translate(target_bounds.x() - bounds.x() + offset.x(),
46 target_bounds.y() - bounds.y() + offset.y()); 288 target_bounds.y() - bounds.y() + offset.y());
47 transform.Scale(scale, scale); 289 transform.Scale(scale, scale);
48 // TODO(flackr): The window bounds or transform could change during overview 290 if (root_window != window_->GetRootWindow()) {
49 // mode. WindowSelector should create a copy of the window so that the 291 if (!window_copy_) {
50 // displayed windows are not affected by changes happening in the background. 292 layer_ = views::corewm::RecreateWindowLayers(window_, true);
Daniel Erat 2013/08/09 20:54:35 nit: can you DCHECK(!layer_) and DCHECK(!window_co
flackr 2013/08/09 22:15:36 Added DCHECK(!layer_), I'm not sure I follow the D
Daniel Erat 2013/08/09 22:19:01 whoops, sorry -- forget that part
51 // This will be necessary for alt-tab cycling as well, as some windows will 293 window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
52 // be coming from other displays: http://crbug.com/263481. 294 }
53 window->SetTransform(transform); 295 WindowSelectorAnimationSettings animation_settings(
296 window_copy_->GetNativeWindow());
297 window_copy_->GetNativeWindow()->SetTransform(transform);
298 }
299 WindowSelectorAnimationSettings animation_settings(window_);
300 window_->SetTransform(transform);
54 } 301 }
55 302
56 } // namespace 303 // A comparator for locating a given target window.
304 struct WindowSelectorWindowComparator
305 : public std::unary_function<WindowSelectorWindow*, bool> {
306 explicit WindowSelectorWindowComparator(const aura::Window* target_window)
307 : target(target_window) {
308 }
309
310 bool operator() (const WindowSelectorWindow* window) const {
Daniel Erat 2013/08/09 20:54:35 nit: remove space after operator()
flackr 2013/08/09 22:15:36 Done.
311 return target == window->window();
312 }
313
314 const aura::Window* target;
315 };
57 316
58 WindowSelector::WindowSelector(const WindowList& windows, 317 WindowSelector::WindowSelector(const WindowList& windows,
318 WindowSelector::Mode mode,
59 WindowSelectorDelegate* delegate) 319 WindowSelectorDelegate* delegate)
60 : delegate_(delegate) { 320 : mode_(mode),
321 delegate_(delegate),
322 selected_window_(0),
323 selection_root_(NULL) {
61 DCHECK(delegate_); 324 DCHECK(delegate_);
62 for (size_t i = 0; i < windows.size(); ++i) { 325 for (size_t i = 0; i < windows.size(); ++i) {
63 windows[i]->AddObserver(this); 326 windows[i]->AddObserver(this);
64 WindowDetails details; 327 windows_.push_back(new WindowSelectorWindow(windows[i]));
65 details.window = windows[i];
66 details.minimized = windows[i]->GetProperty(aura::client::kShowStateKey) ==
67 ui::SHOW_STATE_MINIMIZED;
68 details.original_transform = windows[i]->layer()->transform();
69 if (details.minimized) {
70 windows[i]->Show();
71 }
72 windows_.push_back(details);
73 } 328 }
329 if (mode == WindowSelector::CYCLE)
330 selection_root_ = ash::Shell::GetActiveRootWindow();
74 PositionWindows(); 331 PositionWindows();
75 ash::Shell::GetInstance()->AddPreTargetHandler(this); 332 ash::Shell::GetInstance()->AddPreTargetHandler(this);
76 } 333 }
77 334
78 WindowSelector::~WindowSelector() { 335 WindowSelector::~WindowSelector() {
79 for (size_t i = 0; i < windows_.size(); i++) { 336 for (size_t i = 0; i < windows_.size(); i++) {
80 ui::ScopedLayerAnimationSettings animation_settings( 337 windows_[i]->window()->RemoveObserver(this);
81 windows_[i].window->layer()->GetAnimator());
82 animation_settings.SetPreemptionStrategy(
83 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
84 animation_settings.SetTransitionDuration(
85 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
86 windows_[i].window->RemoveObserver(this);
87 gfx::Transform transform;
88 windows_[i].window->SetTransform(windows_[i].original_transform);
89 if (windows_[i].minimized) {
90 // Setting opacity 0 and visible false ensures that the property change
91 // to SHOW_STATE_MINIMIZED will not animate the window from its original
92 // bounds to the minimized position.
93 windows_[i].window->layer()->SetOpacity(0);
94 windows_[i].window->layer()->SetVisible(false);
95 windows_[i].window->SetProperty(aura::client::kShowStateKey,
96 ui::SHOW_STATE_MINIMIZED);
97 }
98 } 338 }
99 ash::Shell::GetInstance()->RemovePreTargetHandler(this); 339 ash::Shell::GetInstance()->RemovePreTargetHandler(this);
100 } 340 }
101 341
342 void WindowSelector::Step(WindowSelector::Direction direction) {
343 DCHECK(windows_.size() > 0);
344 if (!selection_widget_)
345 InitializeSelectionWidget();
346 selected_window_ = (selected_window_ + windows_.size() +
347 (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size();
348 UpdateSelectionLocation(true);
349 }
350
351 void WindowSelector::SelectWindow() {
352 delegate_->OnWindowSelected(windows_[selected_window_]->window());
353 }
354
102 void WindowSelector::OnEvent(ui::Event* event) { 355 void WindowSelector::OnEvent(ui::Event* event) {
103 // TODO(flackr): This will prevent anything else from working while overview 356 ui::EventHandler::OnEvent(event);
104 // mode is active. This should only stop events from being sent to the windows 357
105 // in the overview but still allow interaction with the launcher / tray and 358 // If the event is targetted at any of the windows in the overview, then
106 // hotkeys http://crbug.com/264289. 359 // prevent it from propagating.
107 EventHandler::OnEvent(event); 360 aura::Window* target = static_cast<aura::Window*>(event->target());
108 event->StopPropagation(); 361 for (size_t i = 0; i < windows_.size(); ++i) {
362 if (windows_[i]->Contains(target)) {
363 event->StopPropagation();
364 break;
365 }
366 }
109 } 367 }
110 368
111 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) { 369 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
112 if (event->type() != ui::ET_MOUSE_RELEASED) 370 if (event->type() != ui::ET_MOUSE_RELEASED)
113 return; 371 return;
114 aura::Window* target = static_cast<aura::Window*>(event->target()); 372 WindowSelectorWindow* target = GetEventTarget(event);
115 if (!target->HitTest(event->location())) 373 if (!target)
116 return; 374 return;
117 375
118 HandleSelectionEvent(event); 376 HandleSelectionEvent(target);
119 } 377 }
120 378
121 void WindowSelector::OnGestureEvent(ui::GestureEvent* event) { 379 void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
122 if (event->type() != ui::ET_GESTURE_TAP) 380 if (event->type() != ui::ET_GESTURE_TAP)
123 return; 381 return;
124 HandleSelectionEvent(event); 382 WindowSelectorWindow* target = GetEventTarget(event);
383 if (!target)
384 return;
385
386 HandleSelectionEvent(target);
125 } 387 }
126 388
127 void WindowSelector::OnWindowDestroyed(aura::Window* window) { 389 void WindowSelector::OnWindowDestroyed(aura::Window* window) {
128 std::vector<WindowDetails>::iterator iter = 390 ScopedVector<WindowSelectorWindow>::iterator iter =
129 std::find(windows_.begin(), windows_.end(), window); 391 std::find_if(windows_.begin(), windows_.end(),
392 WindowSelectorWindowComparator(window));
130 DCHECK(iter != windows_.end()); 393 DCHECK(iter != windows_.end());
394 size_t deleted_index = iter - windows_.begin();
395 (*iter)->OnWindowDestroyed();
131 windows_.erase(iter); 396 windows_.erase(iter);
132 if (windows_.empty()) { 397 if (windows_.empty()) {
133 delegate_->OnSelectionCanceled(); 398 delegate_->OnSelectionCanceled();
134 return; 399 return;
135 } 400 }
401 if (selected_window_ >= deleted_index) {
402 if (selected_window_ > deleted_index)
403 selected_window_--;
404 selected_window_ = selected_window_ % windows_.size();
405 UpdateSelectionLocation(true);
406 }
136 407
137 PositionWindows(); 408 PositionWindows();
138 } 409 }
139 410
140 void WindowSelector::HandleSelectionEvent(ui::Event* event) { 411 WindowSelectorWindow* WindowSelector::GetEventTarget(ui::LocatedEvent* event) {
141 aura::Window* target = static_cast<aura::Window*>(event->target()); 412 aura::Window* target = static_cast<aura::Window*>(event->target());
413 // If the target window doesn't actually contain the event location (i.e.
414 // mouse down over the window and mouse up elsewhere) then do not select the
415 // window.
416 if (!target->HitTest(event->location()))
417 return NULL;
142 418
143 for (size_t i = 0; i < windows_.size(); i++) { 419 for (size_t i = 0; i < windows_.size(); i++) {
144 if (windows_[i].window->Contains(target)) { 420 if (windows_[i]->Contains(target))
145 // The selected window should not be minimized when window selection is 421 return windows_[i];
146 // ended. 422 }
147 windows_[i].minimized = false; 423 return NULL;
148 windows_[i].original_transform = gfx::Transform(); 424 }
149 425
150 // The delegate may delete the WindowSelector, assume the object may no 426 void WindowSelector::HandleSelectionEvent(WindowSelectorWindow* target) {
151 // longer valid after calling this. 427 // The selected window should not be minimized when window selection is
152 delegate_->OnWindowSelected(windows_[i].window); 428 // ended.
153 return; 429 target->RestoreWindowOnExit();
430 delegate_->OnWindowSelected(target->window());
431 }
432
433 void WindowSelector::PositionWindows() {
434 if (selection_root_) { // mode == CYCLE
Daniel Erat 2013/08/09 20:54:35 nit: is it worthwhile to add DCHECK_EQ(mode_, CYCL
flackr 2013/08/09 22:15:36 Done.
435 std::vector<WindowSelectorWindow*> windows;
436 for (size_t i = 0; i < windows_.size(); ++i) {
Daniel Erat 2013/08/09 20:54:35 nit: don't need curly braces here
flackr 2013/08/09 22:15:36 Done.
437 windows.push_back(windows_[i]);
438 }
439 PositionWindowsOnRoot(selection_root_, windows);
440 } else { // mode == OVERVIEW
441 Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
442 for (size_t i = 0; i < root_window_list.size(); ++i) {
Daniel Erat 2013/08/09 20:54:35 nit: or here
flackr 2013/08/09 22:15:36 Done.
443 PositionWindowsFromRoot(root_window_list[i]);
154 } 444 }
155 } 445 }
156 } 446 }
157 447
158 void WindowSelector::PositionWindows() { 448 void WindowSelector::PositionWindowsFromRoot(aura::RootWindow* root_window) {
159 Shell::RootWindowList root_window_list = Shell::GetAllRootWindows(); 449 std::vector<WindowSelectorWindow*> windows;
160 for (size_t i = 0; i < root_window_list.size(); ++i) { 450 for (size_t i = 0; i < windows_.size(); ++i) {
161 PositionWindowsOnRoot(root_window_list[i]); 451 if (windows_[i]->window()->GetRootWindow() == root_window)
452 windows.push_back(windows_[i]);
162 } 453 }
454 PositionWindowsOnRoot(root_window, windows);
163 } 455 }
164 456
165 void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) { 457 void WindowSelector::PositionWindowsOnRoot(
166 gfx::Size window_size; 458 aura::RootWindow* root_window,
167 gfx::Rect total_bounds = ScreenAsh::GetDisplayWorkAreaBoundsInParent( 459 const std::vector<WindowSelectorWindow*>& windows) {
168 Shell::GetContainer(root_window,
169 internal::kShellWindowId_DefaultContainer));
170
171 std::vector<WindowDetails> windows;
172 for (size_t i = 0; i < windows_.size(); ++i) {
173 if (windows_[i].window->GetRootWindow() == root_window)
174 windows.push_back(windows_[i]);
175 }
176 if (windows.empty()) 460 if (windows.empty())
177 return; 461 return;
178 462
463 gfx::Size window_size;
464 gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window,
465 ScreenAsh::GetDisplayWorkAreaBoundsInParent(
466 Shell::GetContainer(root_window,
467 internal::kShellWindowId_DefaultContainer)));
468
179 // Find the minimum number of windows per row that will fit all of the 469 // Find the minimum number of windows per row that will fit all of the
180 // windows on screen. 470 // windows on screen.
181 size_t columns = std::max( 471 size_t columns = std::max(
182 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1, 472 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1,
183 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() / 473 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() /
184 (kCardAspectRatio * total_bounds.height()))))); 474 (kCardAspectRatio * total_bounds.height())))));
185 size_t rows = ((windows.size() + columns - 1) / columns); 475 size_t rows = ((windows.size() + columns - 1) / columns);
186 window_size.set_width(std::min( 476 window_size.set_width(std::min(
187 static_cast<int>(total_bounds.width() / columns), 477 static_cast<int>(total_bounds.width() / columns),
188 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows))); 478 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows)));
189 window_size.set_height(window_size.width() / kCardAspectRatio); 479 window_size.set_height(window_size.width() / kCardAspectRatio);
190 480
191 // Calculate the X and Y offsets necessary to center the grid. 481 // Calculate the X and Y offsets necessary to center the grid.
192 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 : 482 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 :
193 (columns - windows.size()) * window_size.width()) + 483 (columns - windows.size()) * window_size.width()) +
194 (total_bounds.width() - columns * window_size.width())) / 2; 484 (total_bounds.width() - columns * window_size.width())) / 2;
195 int y_offset = total_bounds.y() + (total_bounds.height() - 485 int y_offset = total_bounds.y() + (total_bounds.height() -
196 rows * window_size.height()) / 2; 486 rows * window_size.height()) / 2;
197 for (size_t i = 0; i < windows.size(); ++i) { 487 for (size_t i = 0; i < windows.size(); ++i) {
198 ui::ScopedLayerAnimationSettings animation_settings(
199 windows[i].window->layer()->GetAnimator());
200 animation_settings.SetPreemptionStrategy(
201 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
202 animation_settings.SetTransitionDuration(
203 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
204 gfx::Transform transform; 488 gfx::Transform transform;
205 int column = i % columns; 489 int column = i % columns;
206 int row = i / columns; 490 int row = i / columns;
207 gfx::Rect target_bounds(window_size.width() * column + x_offset, 491 gfx::Rect target_bounds(window_size.width() * column + x_offset,
208 window_size.height() * row + y_offset, 492 window_size.height() * row + y_offset,
209 window_size.width(), 493 window_size.width(),
210 window_size.height()); 494 window_size.height());
211 target_bounds.Inset(kWindowMargin, kWindowMargin); 495 target_bounds.Inset(kWindowMargin, kWindowMargin);
212 TransformWindowToFitBounds(windows[i].window, target_bounds); 496 windows[i]->TransformToFitBounds(root_window, target_bounds);
213 } 497 }
214 } 498 }
215 499
500 void WindowSelector::InitializeSelectionWidget() {
501 selection_widget_.reset(new views::Widget);
502 views::Widget::InitParams params;
503 params.type = views::Widget::InitParams::TYPE_POPUP;
504 params.can_activate = false;
505 params.keep_on_top = false;
506 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
507 params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
508 params.parent = Shell::GetContainer(
509 selection_root_,
510 internal::kShellWindowId_DefaultContainer);
511 params.accept_events = false;
512 selection_widget_->set_focus_on_creation(false);
513 selection_widget_->Init(params);
514 views::View* content_view = new views::View;
515 content_view->set_background(
516 views::Background::CreateSolidBackground(kWindowSelectorSelectionColor));
517 selection_widget_->SetContentsView(content_view);
518 UpdateSelectionLocation(false);
519 selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
520 selection_widget_->GetNativeWindow());
521 selection_widget_->Show();
522 selection_widget_->GetNativeWindow()->layer()->SetOpacity(
523 kWindowSelectorSelectionOpacity);
524 }
525
526 void WindowSelector::UpdateSelectionLocation(bool animate) {
527 if (!selection_widget_)
528 return;
529 gfx::Rect target_bounds = windows_[selected_window_]->bounds();
530 target_bounds.Inset(-kWindowSelectorSelectionPadding,
531 -kWindowSelectorSelectionPadding);
532 if (animate) {
533 WindowSelectorAnimationSettings animation_settings(
534 selection_widget_->GetNativeWindow());
535 selection_widget_->SetBounds(target_bounds);
536 } else {
537 selection_widget_->SetBounds(target_bounds);
538 }
539 }
540
216 } // namespace ash 541 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698