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

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

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

Powered by Google App Engine
This is Rietveld 408576698