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

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

Issue 20415002: Add window overview mode behind --ash-enable-overview-mode flag to F5 key. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Remove MRU window tracking refactoring from CL. 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
OLDNEW
(Empty)
1 // Copyright (c) 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/window_selector.h"
6
7 #include <algorithm>
8
9 #include "ash/screen_ash.h"
10 #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 "ui/aura/client/aura_constants.h"
16 #include "ui/aura/root_window.h"
17 #include "ui/aura/window.h"
18 #include "ui/base/events/event.h"
19 #include "ui/compositor/scoped_layer_animation_settings.h"
20 #include "ui/gfx/interpolated_transform.h"
21 #include "ui/gfx/transform_util.h"
22 #include "ui/views/corewm/window_animations.h"
23
24 namespace ash {
25
26 namespace {
27
28 const float kCardAspectRatio = 4.0f / 3.0f;
29 const int kWindowMargin = 20;
30 const int kMinCardsMajor = 3;
31 const int kOverviewTransitionMilliseconds = 100;
32
33 // Applies a transform to |window| to fit within |target_bounds| while
34 // maintaining its aspect ratio.
35 void TransformWindowToFitBounds(aura::Window* window,
36 const gfx::Rect& target_bounds) {
37 const gfx::Rect bounds = window->bounds();
38 float scale = std::min(1.0f,
39 std::min((float)target_bounds.width() / bounds.width(),
sky 2013/07/30 16:39:19 static_cast
flackr 2013/07/31 20:06:12 Done.
40 (float)target_bounds.height() / bounds.height()));
41 gfx::Transform transform;
42 gfx::Vector2d offset(
43 0.5 * (target_bounds.width() - scale * bounds.width()),
44 0.5 * (target_bounds.height() - scale * bounds.height()));
45 transform.Translate(target_bounds.x() - bounds.x() + offset.x(),
46 target_bounds.y() - bounds.y() + offset.y());
47 transform.Scale(scale, scale);
48 window->layer()->SetTransform(transform);
sky 2013/07/30 16:39:19 Why go through layer directly? Additionally, what
flackr 2013/07/31 20:06:12 Calling SetTransform on Window now, done. If some
49 }
50
51 } // namespace
52
53 WindowSelector::WindowSelector(const WindowList& windows,
54 WindowSelectorDelegate* delegate)
55 : windows_(windows),
56 delegate_(delegate) {
57 DCHECK(delegate_);
58 for (size_t i = 0; i < windows_.size(); ++i) {
59 windows_[i]->AddObserver(this);
60 if (windows_[i]->GetProperty(aura::client::kShowStateKey) ==
61 ui::SHOW_STATE_MINIMIZED) {
62 windows_[i]->layer()->SetVisible(true);
63 windows_[i]->layer()->SetOpacity(1);
64 }
65 }
66 PositionWindows();
67 ash::Shell::GetInstance()->AddPreTargetHandler(this);
68 }
69
70 WindowSelector::~WindowSelector() {
71 for (size_t i = 0; i < windows_.size(); i++) {
72 ui::ScopedLayerAnimationSettings animation_settings(
73 windows_[i]->layer()->GetAnimator());
74 animation_settings.SetPreemptionStrategy(
75 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
76 animation_settings.SetTransitionDuration(
77 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
78 windows_[i]->RemoveObserver(this);
79 if (windows_[i]->GetProperty(aura::client::kShowStateKey) ==
80 ui::SHOW_STATE_MINIMIZED) {
81 windows_[i]->layer()->SetOpacity(0);
82 windows_[i]->layer()->SetVisible(false);
83 }
84 gfx::Transform transform;
85 windows_[i]->layer()->SetTransform(transform);
86 }
87 ash::Shell::GetInstance()->RemovePreTargetHandler(this);
88 }
89
90 void WindowSelector::OnEvent(ui::Event* event) {
91 // TODO(flackr): This will prevent anything else from working while overview
92 // mode is active. This should only stop events from being sent to the windows
93 // in the overview but still allow interaction with the launcher / tray and
94 // hotkeys http://crbug.com/264289.
95 EventHandler::OnEvent(event);
96 event->StopPropagation();
97 }
98
99 void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
100 if (event->type() != ui::ET_MOUSE_RELEASED)
sky 2013/07/30 16:39:19 I believe this code means you can mouse down on on
flackr 2013/07/31 20:06:12 It seems that we send the released event to the wi
101 return;
102 HandleSelectionEvent(event);
103 }
104
105 void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
106 if (event->type() != ui::ET_GESTURE_TAP)
107 return;
108 HandleSelectionEvent(event);
109 }
110
111 void WindowSelector::OnWindowDestroyed(aura::Window* window) {
112 WindowList::iterator iter =
113 std::find(windows_.begin(), windows_.end(), window);
114 if (iter != windows_.end()) {
sky 2013/07/30 16:39:19 Shouldn't this be a DCHECK?
flackr 2013/07/31 20:06:12 Done.
115 windows_.erase(iter);
116 PositionWindows();
117 }
118 }
sky 2013/07/30 16:39:19 What if windows_ goes empty here?
flackr 2013/07/31 20:06:12 Bad things happen, since you have no more targets
119
120 void WindowSelector::HandleSelectionEvent(ui::Event* event) {
121 aura::Window* target = static_cast<aura::Window*>(event->target());
122
123 for (size_t i = 0; i < windows_.size(); i++) {
124 if (windows_[i]->Contains(target)) {
125 // The delegate may delete the WindowSelector, assume the object may no
126 // longer valid after calling this.
127 delegate_->SelectWindow(windows_[i]);
128 return;
129 }
130 }
131 }
132
133 void WindowSelector::PositionWindows() {
134 Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
135 for (size_t i = 0; i < root_window_list.size(); ++i) {
136 WindowList windows_in_root;
137 for (size_t j = 0; j < windows_.size(); ++j) {
sky 2013/07/30 16:39:19 nit: 2 thoughts here, its up to you if you want to
flackr 2013/07/31 20:06:12 I suspect this will change somewhat with alt-tab c
138 if (windows_[j]->GetRootWindow() == root_window_list[i]) {
sky 2013/07/30 16:39:19 nit: no {}
flackr 2013/07/31 20:06:12 Done.
139 windows_in_root.push_back(windows_[j]);
140 }
141 }
142 PositionWindowsOnRoot(root_window_list[i], windows_in_root);
sky 2013/07/30 16:39:19 Do you want to invoke this if windows_in_root is e
flackr 2013/07/31 20:06:12 Added early exit in PositionWindowsOnRoot.
143 }
144 }
145
146 void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window,
147 const WindowList& windows) {
148 gfx::Size window_size;
149 gfx::Rect total_bounds = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
150 Shell::GetContainer(root_window,
151 internal::kShellWindowId_DefaultContainer));
152
153 // Find the minimum number of windows per row that will fit all of the
154 // windows on screen.
155 size_t windows_per_row = 1;
156 if (total_bounds.width() > total_bounds.height())
157 windows_per_row = kMinCardsMajor;
158 for (;; ++windows_per_row) {
sky 2013/07/30 16:39:19 Seems like there has to be a better way to calcula
flackr 2013/07/31 20:06:12 Done.
159 window_size.set_width(total_bounds.width() / windows_per_row);
160 window_size.set_height(window_size.width() / kCardAspectRatio);
161 if (windows_per_row * (total_bounds.height() /
162 window_size.height()) >= windows.size())
163 break;
164 }
165 // Calculate the Y offset necessary to vertically center the stack.
166 int x_offset = total_bounds.x() + (windows.size() >= windows_per_row ? 0 :
167 (windows_per_row - windows.size()) * window_size.width() / 2);
168 int y_offset = total_bounds.y() + (total_bounds.height() -
169 ((windows.size() + windows_per_row - 1) / windows_per_row) *
170 window_size.height()) / 2;
171 for (size_t i = 0; i < windows.size(); ++i) {
172 ui::ScopedLayerAnimationSettings animation_settings(
173 windows[i]->layer()->GetAnimator());
174 animation_settings.SetPreemptionStrategy(
175 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
176 animation_settings.SetTransitionDuration(
177 base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
178 gfx::Transform transform;
179 int column = i % windows_per_row;
180 int row = i / windows_per_row;
181 gfx::Rect target_bounds(window_size.width() * column + x_offset,
182 window_size.height() * row + y_offset,
183 window_size.width(),
184 window_size.height());
185 target_bounds.Inset(kWindowMargin, kWindowMargin);
186 TransformWindowToFitBounds(windows[i], target_bounds);
187 }
188 }
189
190 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698