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

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

Issue 22929034: Relocate and refactor overview mode files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove extra newline 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/overview/window_selector_window.h ('k') | ash/wm/window_selector.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/overview/window_selector_window.h"
6 6
7 #include <algorithm>
8
9 #include "ash/screen_ash.h"
10 #include "ash/shell.h" 7 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/window_selector_delegate.h"
13 #include "ash/wm/window_util.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" 8 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/client/screen_position_client.h" 9 #include "ui/aura/client/screen_position_client.h"
18 #include "ui/aura/root_window.h" 10 #include "ui/aura/root_window.h"
19 #include "ui/aura/window.h" 11 #include "ui/aura/window.h"
20 #include "ui/base/events/event.h"
21 #include "ui/compositor/layer_animation_observer.h" 12 #include "ui/compositor/layer_animation_observer.h"
22 #include "ui/compositor/scoped_layer_animation_settings.h" 13 #include "ui/compositor/scoped_layer_animation_settings.h"
23 #include "ui/gfx/display.h" 14 #include "ui/gfx/display.h"
24 #include "ui/gfx/interpolated_transform.h" 15 #include "ui/gfx/interpolated_transform.h"
25 #include "ui/gfx/transform_util.h" 16 #include "ui/gfx/transform_util.h"
26 #include "ui/views/corewm/shadow_types.h" 17 #include "ui/views/corewm/shadow_types.h"
27 #include "ui/views/corewm/window_animations.h" 18 #include "ui/views/corewm/window_animations.h"
28 #include "ui/views/corewm/window_util.h" 19 #include "ui/views/corewm/window_util.h"
29 #include "ui/views/widget/widget.h" 20 #include "ui/views/widget/widget.h"
30 21
31 namespace ash { 22 namespace ash {
32 23
33 namespace { 24 namespace {
34 25
35 const float kCardAspectRatio = 4.0f / 3.0f; 26 const int kOverviewWindowTransitionMilliseconds = 100;
36 const int kWindowMargin = 30;
37 const int kMinCardsMajor = 3;
38 const int kOverviewTransitionMilliseconds = 100;
39 const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK;
40 const float kWindowSelectorSelectionOpacity = 0.5f;
41 const int kWindowSelectorSelectionPadding = 15;
42 27
43 // Creates a copy of |window| with |recreated_layer| in the |target_root|. 28 // Creates a copy of |window| with |recreated_layer| in the |target_root|.
44 views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root, 29 views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root,
45 aura::Window* src_window, 30 aura::Window* src_window,
46 ui::Layer* recreated_layer) { 31 ui::Layer* recreated_layer) {
47 views::Widget* widget = new views::Widget; 32 views::Widget* widget = new views::Widget;
48 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 33 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
49 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 34 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
50 params.parent = src_window->parent(); 35 params.parent = src_window->parent();
51 params.can_activate = false; 36 params.can_activate = false;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 129 }
145 130
146 // The animation settings used for window selector animations. 131 // The animation settings used for window selector animations.
147 class WindowSelectorAnimationSettings 132 class WindowSelectorAnimationSettings
148 : public ui::ScopedLayerAnimationSettings { 133 : public ui::ScopedLayerAnimationSettings {
149 public: 134 public:
150 WindowSelectorAnimationSettings(aura::Window* window) : 135 WindowSelectorAnimationSettings(aura::Window* window) :
151 ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) { 136 ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
152 SetPreemptionStrategy( 137 SetPreemptionStrategy(
153 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 138 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
154 SetTransitionDuration( 139 SetTransitionDuration(base::TimeDelta::FromMilliseconds(
155 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds)); 140 kOverviewWindowTransitionMilliseconds));
156 } 141 }
157 142
158 virtual ~WindowSelectorAnimationSettings() { 143 virtual ~WindowSelectorAnimationSettings() {
159 } 144 }
160 }; 145 };
161 146
162 } // namespace 147 } // namespace
163 148
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) 149 WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
217 : window_(window), 150 : window_(window),
218 window_copy_(NULL), 151 window_copy_(NULL),
219 layer_(NULL), 152 layer_(NULL),
220 minimized_(window->GetProperty(aura::client::kShowStateKey) == 153 minimized_(window->GetProperty(aura::client::kShowStateKey) ==
221 ui::SHOW_STATE_MINIMIZED), 154 ui::SHOW_STATE_MINIMIZED),
222 original_transform_(window->layer()->GetTargetTransform()) { 155 original_transform_(window->layer()->GetTargetTransform()) {
223 if (minimized_) 156 if (minimized_)
224 window_->Show(); 157 window_->Show();
225 } 158 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 window_copy_ = CreateCopyOfWindow(root_window, window_, layer_); 229 window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
297 } 230 }
298 WindowSelectorAnimationSettings animation_settings( 231 WindowSelectorAnimationSettings animation_settings(
299 window_copy_->GetNativeWindow()); 232 window_copy_->GetNativeWindow());
300 window_copy_->GetNativeWindow()->SetTransform(transform); 233 window_copy_->GetNativeWindow()->SetTransform(transform);
301 } 234 }
302 WindowSelectorAnimationSettings animation_settings(window_); 235 WindowSelectorAnimationSettings animation_settings(window_);
303 window_->SetTransform(transform); 236 window_->SetTransform(transform);
304 } 237 }
305 238
306 // A comparator for locating a given target window.
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
320 WindowSelector::WindowSelector(const WindowList& windows,
321 WindowSelector::Mode mode,
322 WindowSelectorDelegate* delegate)
323 : mode_(mode),
324 delegate_(delegate),
325 selected_window_(0),
326 selection_root_(NULL) {
327 DCHECK(delegate_);
328 for (size_t i = 0; i < windows.size(); ++i) {
329 windows[i]->AddObserver(this);
330 windows_.push_back(new WindowSelectorWindow(windows[i]));
331 }
332 if (mode == WindowSelector::CYCLE)
333 selection_root_ = ash::Shell::GetActiveRootWindow();
334 PositionWindows();
335 ash::Shell::GetInstance()->AddPreTargetHandler(this);
336 }
337
338 WindowSelector::~WindowSelector() {
339 for (size_t i = 0; i < windows_.size(); i++) {
340 windows_[i]->window()->RemoveObserver(this);
341 }
342 ash::Shell::GetInstance()->RemovePreTargetHandler(this);
343 }
344
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) {
359 // If the event is targetted at any of the windows in the overview, then
360 // prevent it from propagating.
361 aura::Window* target = static_cast<aura::Window*>(event->target());
362 for (size_t i = 0; i < windows_.size(); ++i) {
363 if (windows_[i]->Contains(target)) {
364 // TODO(flackr): StopPropogation prevents generation of gesture events.
365 // We should find a better way to prevent events from being delivered to
366 // the window, perhaps a transparent window in front of the target window
367 // or using EventClientImpl::CanProcessEventsWithinSubtree.
368 event->StopPropagation();
369 break;
370 }
371 }
372
373 // This object may not be valid after this call as a selection event can
374 // trigger deletion of the window selector.
375 ui::EventHandler::OnEvent(event);
376 }
377
378 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
379 if (event->type() != ui::ET_MOUSE_RELEASED)
380 return;
381 WindowSelectorWindow* target = GetEventTarget(event);
382 if (!target)
383 return;
384
385 HandleSelectionEvent(target);
386 }
387
388 void WindowSelector::OnTouchEvent(ui::TouchEvent* event) {
389 if (event->type() != ui::ET_TOUCH_PRESSED)
390 return;
391 WindowSelectorWindow* target = GetEventTarget(event);
392 if (!target)
393 return;
394
395 HandleSelectionEvent(target);
396 }
397
398 void WindowSelector::OnWindowDestroyed(aura::Window* window) {
399 ScopedVector<WindowSelectorWindow>::iterator iter =
400 std::find_if(windows_.begin(), windows_.end(),
401 WindowSelectorWindowComparator(window));
402 DCHECK(iter != windows_.end());
403 size_t deleted_index = iter - windows_.begin();
404 (*iter)->OnWindowDestroyed();
405 windows_.erase(iter);
406 if (windows_.empty()) {
407 delegate_->OnSelectionCanceled();
408 return;
409 }
410 if (selected_window_ >= deleted_index) {
411 if (selected_window_ > deleted_index)
412 selected_window_--;
413 selected_window_ = selected_window_ % windows_.size();
414 UpdateSelectionLocation(true);
415 }
416
417 PositionWindows();
418 }
419
420 WindowSelectorWindow* WindowSelector::GetEventTarget(ui::LocatedEvent* event) {
421 aura::Window* target = static_cast<aura::Window*>(event->target());
422 // If the target window doesn't actually contain the event location (i.e.
423 // mouse down over the window and mouse up elsewhere) then do not select the
424 // window.
425 if (!target->HitTest(event->location()))
426 return NULL;
427
428 for (size_t i = 0; i < windows_.size(); i++) {
429 if (windows_[i]->Contains(target))
430 return windows_[i];
431 }
432 return NULL;
433 }
434
435 void WindowSelector::HandleSelectionEvent(WindowSelectorWindow* target) {
436 // The selected window should not be minimized when window selection is
437 // ended.
438 target->RestoreWindowOnExit();
439 delegate_->OnWindowSelected(target->window());
440 }
441
442 void WindowSelector::PositionWindows() {
443 if (selection_root_) {
444 DCHECK_EQ(mode_, CYCLE);
445 std::vector<WindowSelectorWindow*> windows;
446 for (size_t i = 0; i < windows_.size(); ++i)
447 windows.push_back(windows_[i]);
448 PositionWindowsOnRoot(selection_root_, windows);
449 } else {
450 DCHECK_EQ(mode_, OVERVIEW);
451 Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
452 for (size_t i = 0; i < root_window_list.size(); ++i)
453 PositionWindowsFromRoot(root_window_list[i]);
454 }
455 }
456
457 void WindowSelector::PositionWindowsFromRoot(aura::RootWindow* root_window) {
458 std::vector<WindowSelectorWindow*> windows;
459 for (size_t i = 0; i < windows_.size(); ++i) {
460 if (windows_[i]->window()->GetRootWindow() == root_window)
461 windows.push_back(windows_[i]);
462 }
463 PositionWindowsOnRoot(root_window, windows);
464 }
465
466 void WindowSelector::PositionWindowsOnRoot(
467 aura::RootWindow* root_window,
468 const std::vector<WindowSelectorWindow*>& windows) {
469 if (windows.empty())
470 return;
471
472 gfx::Size window_size;
473 gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window,
474 ScreenAsh::GetDisplayWorkAreaBoundsInParent(
475 Shell::GetContainer(root_window,
476 internal::kShellWindowId_DefaultContainer)));
477
478 // Find the minimum number of windows per row that will fit all of the
479 // windows on screen.
480 size_t columns = std::max(
481 total_bounds.width() > total_bounds.height() ? kMinCardsMajor : 1,
482 static_cast<int>(ceil(sqrt(total_bounds.width() * windows.size() /
483 (kCardAspectRatio * total_bounds.height())))));
484 size_t rows = ((windows.size() + columns - 1) / columns);
485 window_size.set_width(std::min(
486 static_cast<int>(total_bounds.width() / columns),
487 static_cast<int>(total_bounds.height() * kCardAspectRatio / rows)));
488 window_size.set_height(window_size.width() / kCardAspectRatio);
489
490 // Calculate the X and Y offsets necessary to center the grid.
491 int x_offset = total_bounds.x() + ((windows.size() >= columns ? 0 :
492 (columns - windows.size()) * window_size.width()) +
493 (total_bounds.width() - columns * window_size.width())) / 2;
494 int y_offset = total_bounds.y() + (total_bounds.height() -
495 rows * window_size.height()) / 2;
496 for (size_t i = 0; i < windows.size(); ++i) {
497 gfx::Transform transform;
498 int column = i % columns;
499 int row = i / columns;
500 gfx::Rect target_bounds(window_size.width() * column + x_offset,
501 window_size.height() * row + y_offset,
502 window_size.width(),
503 window_size.height());
504 target_bounds.Inset(kWindowMargin, kWindowMargin);
505 windows[i]->TransformToFitBounds(root_window, target_bounds);
506 }
507 }
508
509 void WindowSelector::InitializeSelectionWidget() {
510 selection_widget_.reset(new views::Widget);
511 views::Widget::InitParams params;
512 params.type = views::Widget::InitParams::TYPE_POPUP;
513 params.can_activate = false;
514 params.keep_on_top = false;
515 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
516 params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
517 params.parent = Shell::GetContainer(
518 selection_root_,
519 internal::kShellWindowId_DefaultContainer);
520 params.accept_events = false;
521 selection_widget_->set_focus_on_creation(false);
522 selection_widget_->Init(params);
523 views::View* content_view = new views::View;
524 content_view->set_background(
525 views::Background::CreateSolidBackground(kWindowSelectorSelectionColor));
526 selection_widget_->SetContentsView(content_view);
527 UpdateSelectionLocation(false);
528 selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
529 selection_widget_->GetNativeWindow());
530 selection_widget_->Show();
531 selection_widget_->GetNativeWindow()->layer()->SetOpacity(
532 kWindowSelectorSelectionOpacity);
533 }
534
535 void WindowSelector::UpdateSelectionLocation(bool animate) {
536 if (!selection_widget_)
537 return;
538 gfx::Rect target_bounds = windows_[selected_window_]->bounds();
539 target_bounds.Inset(-kWindowSelectorSelectionPadding,
540 -kWindowSelectorSelectionPadding);
541 if (animate) {
542 WindowSelectorAnimationSettings animation_settings(
543 selection_widget_->GetNativeWindow());
544 selection_widget_->SetBounds(target_bounds);
545 } else {
546 selection_widget_->SetBounds(target_bounds);
547 }
548 }
549
550 } // namespace ash 239 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/overview/window_selector_window.h ('k') | ash/wm/window_selector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698