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

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

Issue 690103008: Implemented swipe to close in overview mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed flackrs comments from Patch Set 4. Created 5 years, 10 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
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/overview/window_selector_item.h" 5 #include "ash/wm/overview/window_selector_item.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "ash/screen_util.h" 10 #include "ash/screen_util.h"
(...skipping 19 matching lines...) Expand all
30 #include "ui/views/border.h" 30 #include "ui/views/border.h"
31 #include "ui/views/controls/button/image_button.h" 31 #include "ui/views/controls/button/image_button.h"
32 #include "ui/views/layout/box_layout.h" 32 #include "ui/views/layout/box_layout.h"
33 #include "ui/views/widget/widget.h" 33 #include "ui/views/widget/widget.h"
34 #include "ui/wm/core/window_util.h" 34 #include "ui/wm/core/window_util.h"
35 35
36 namespace ash { 36 namespace ash {
37 37
38 namespace { 38 namespace {
39 39
40 // The minimum fling velocity which will cause a window to be closed. Unit is
41 // pixels per second.
42 const float kMinimumFlingVelocity = 4000.0f;
43
44 // The minimum opacity used during touch scroll gestures.
45 const float kMinimumOpacity = 0.2f;
46
40 // In the conceptual overview table, the window margin is the space reserved 47 // In the conceptual overview table, the window margin is the space reserved
41 // around the window within the cell. This margin does not overlap so the 48 // around the window within the cell. This margin does not overlap so the
42 // closest distance between adjacent windows will be twice this amount. 49 // closest distance between adjacent windows will be twice this amount.
43 static const int kWindowMargin = 30; 50 static const int kWindowMargin = 30;
44 51
45 // Foreground label color. 52 // Foreground label color.
46 static const SkColor kLabelColor = SK_ColorWHITE; 53 static const SkColor kLabelColor = SK_ColorWHITE;
47 54
48 // Label shadow color. 55 // Label shadow color.
49 static const SkColor kLabelShadow = 0xB0000000; 56 static const SkColor kLabelShadow = 0xB0000000;
(...skipping 15 matching lines...) Expand all
65 gfx::Rect GetTransformedBounds(aura::Window* window) { 72 gfx::Rect GetTransformedBounds(aura::Window* window) {
66 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(window->GetRootWindow(), 73 gfx::RectF bounds(ScreenUtil::ConvertRectToScreen(window->GetRootWindow(),
67 window->layer()->GetTargetBounds())); 74 window->layer()->GetTargetBounds()));
68 gfx::Transform new_transform = TransformAboutPivot( 75 gfx::Transform new_transform = TransformAboutPivot(
69 gfx::Point(bounds.x(), bounds.y()), 76 gfx::Point(bounds.x(), bounds.y()),
70 window->layer()->GetTargetTransform()); 77 window->layer()->GetTargetTransform());
71 new_transform.TransformRect(&bounds); 78 new_transform.TransformRect(&bounds);
72 return ToEnclosingRect(bounds); 79 return ToEnclosingRect(bounds);
73 } 80 }
74 81
82 // Convenvience method to fade in a Window with predefined animation settings.
83 // Note: The fade in animation will occur after a delay where the delay is how
84 // long the lay out animations take.
85 void SetupFadeInAfterLayout(aura::Window* window) {
86 ui::Layer* layer = window->layer();
87 layer->SetOpacity(0.0f);
88 ScopedOverviewAnimationSettings animation_settings(
89 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN,
90 window);
91 layer->SetOpacity(1.0f);
92 }
93
94 // Convenience method to fade out a window using the animation settings defined
95 // by OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT.
96 void SetupFadeOut(aura::Window* window) {
97 ScopedOverviewAnimationSettings animation_settings(
98 OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_OUT,
99 window);
100 window->layer()->SetOpacity(0.0f);
101 }
102
103 // Calculates the window opacity from the given scroll |distance| and the
104 // |min opacity_distance|.
105 float CalculateOpacityFromScrollDistance(int distance,
106 int min_opacity_distance) {
107 float opacity =
108 1.0f - static_cast<float>(abs(distance)) / min_opacity_distance;
109 return std::min(1.0f, std::max(kMinimumOpacity, opacity));
110 }
111
75 // An image button with a close window icon. 112 // An image button with a close window icon.
76 class OverviewCloseButton : public views::ImageButton { 113 class OverviewCloseButton : public views::ImageButton {
77 public: 114 public:
78 explicit OverviewCloseButton(views::ButtonListener* listener); 115 explicit OverviewCloseButton(views::ButtonListener* listener);
79 ~OverviewCloseButton() override; 116 ~OverviewCloseButton() override;
80 117
81 private: 118 private:
82 DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton); 119 DISALLOW_COPY_AND_ASSIGN(OverviewCloseButton);
83 }; 120 };
84 121
85 OverviewCloseButton::OverviewCloseButton(views::ButtonListener* listener) 122 OverviewCloseButton::OverviewCloseButton(views::ButtonListener* listener)
86 : views::ImageButton(listener) { 123 : views::ImageButton(listener) {
87 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 124 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
88 SetImage(views::CustomButton::STATE_NORMAL, 125 SetImage(views::CustomButton::STATE_NORMAL,
89 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE)); 126 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE));
90 SetImage(views::CustomButton::STATE_HOVERED, 127 SetImage(views::CustomButton::STATE_HOVERED,
91 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_H)); 128 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_H));
92 SetImage(views::CustomButton::STATE_PRESSED, 129 SetImage(views::CustomButton::STATE_PRESSED,
93 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_P)); 130 rb.GetImageSkiaNamed(IDR_AURA_WINDOW_OVERVIEW_CLOSE_P));
94 } 131 }
95 132
96 OverviewCloseButton::~OverviewCloseButton() { 133 OverviewCloseButton::~OverviewCloseButton() {
97 } 134 }
98 135
99 } // namespace 136 } // namespace
100 137
101 WindowSelectorItem::OverviewLabelButton::OverviewLabelButton( 138 WindowSelectorItem::OverviewLabelButton::OverviewLabelButton(
102 views::ButtonListener* listener, 139 WindowSelectorItem* selector_item,
103 const base::string16& text) 140 const base::string16& text)
104 : LabelButton(listener, text), 141 : LabelButton(selector_item, text),
142 selector_item_(selector_item),
105 top_padding_(0) { 143 top_padding_(0) {
106 } 144 }
107 145
108 WindowSelectorItem::OverviewLabelButton::~OverviewLabelButton() { 146 WindowSelectorItem::OverviewLabelButton::~OverviewLabelButton() {
109 } 147 }
110 148
111 gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() { 149 gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() {
112 gfx::Rect bounds = GetLocalBounds(); 150 gfx::Rect bounds = GetLocalBounds();
113 bounds.Inset(0, top_padding_, 0, 0); 151 bounds.Inset(0, top_padding_, 0, 0);
114 return bounds; 152 return bounds;
115 } 153 }
116 154
155 void WindowSelectorItem::OverviewLabelButton::OnGestureEvent(
156 ui::GestureEvent* event) {
157
158 if (!Shell::GetInstance()->window_selector_controller()->
159 swipe_to_close_disabled()) {
160 int delta_x = 0;
161 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)
162 scroll_x_origin_ = event->x();
163 else
164 delta_x = event->x() - scroll_x_origin_;
165
166 switch (event->type()) {
167 case ui::ET_GESTURE_SCROLL_BEGIN:
168 event->SetHandled();
flackr 2015/02/12 18:52:43 Only the scroll begin is handled, but not the scro
bruthig 2015/02/12 20:34:15 Done.
169 selector_item_->OnScrollBegin();
170 break;
171 case ui::ET_GESTURE_SCROLL_UPDATE:
172 selector_item_->OnScrollUpdate(delta_x);
173 break;
174 case ui::ET_GESTURE_SCROLL_END:
175 selector_item_->OnScrollEnd(delta_x);
176 break;
177 case ui::ET_SCROLL_FLING_START:
178 selector_item_->OnFling(delta_x, fabs(event->details().velocity_x()));
179 break;
180 case ui::ET_GESTURE_END:
181 scroll_x_origin_ = 0;
182 break;
183 default:
184 break;
185 }
186 }
187 views::LabelButton::OnGestureEvent(event);
188 }
189
117 WindowSelectorItem::WindowSelectorItem(aura::Window* window) 190 WindowSelectorItem::WindowSelectorItem(aura::Window* window)
118 : dimmed_(false), 191 : dimmed_(false),
119 root_window_(window->GetRootWindow()), 192 root_window_(window->GetRootWindow()),
120 transform_window_(window), 193 transform_window_(window),
121 in_bounds_update_(false), 194 in_bounds_update_(false),
122 window_label_button_view_(nullptr), 195 window_label_button_view_(nullptr),
123 close_button_(new OverviewCloseButton(this)) { 196 close_button_(new OverviewCloseButton(this)) {
124 CreateWindowLabel(window->title()); 197 CreateWindowLabel(window->title());
125 views::Widget::InitParams params; 198 views::Widget::InitParams params;
126 params.type = views::Widget::InitParams::TYPE_POPUP; 199 params.type = views::Widget::InitParams::TYPE_POPUP;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 transform_window_.OnWindowDestroyed(); 294 transform_window_.OnWindowDestroyed();
222 } 295 }
223 296
224 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { 297 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) {
225 // TODO(flackr): Maybe add the new title to a vector of titles so that we can 298 // TODO(flackr): Maybe add the new title to a vector of titles so that we can
226 // filter any of the titles the window had while in the overview session. 299 // filter any of the titles the window had while in the overview session.
227 window_label_button_view_->SetText(window->title()); 300 window_label_button_view_->SetText(window->title());
228 UpdateCloseButtonAccessibilityName(); 301 UpdateCloseButtonAccessibilityName();
229 } 302 }
230 303
304 void WindowSelectorItem::OnScrollBegin() {
305 close_button_->SetEnabled(false);
306 SetupFadeOut(close_button_widget_.GetNativeWindow());
307 }
308
309 void WindowSelectorItem::OnScrollUpdate(int delta_x) {
310 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
311 transform_window_.BeginScopedAnimation(
312 OverviewAnimationType::OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM,
313 &animation_settings);
314
315 gfx::Transform new_transform;
316 new_transform.Translate(delta_x, 0);
317 new_transform.PreconcatTransform(transform_window_.get_overview_transform());
318 transform_window_.SetTransform(root_window(), new_transform);
319
320 const float opacity = CalculateOpacityFromScrollDistance(delta_x,
321 GetMinimumCloseDistance());
322 transform_window_.SetOpacity(opacity);
323 }
324
325 void WindowSelectorItem::OnScrollEnd(int delta_x) {
326 if (abs(delta_x) > GetMinimumCloseDistance()) {
327 transform_window_.Close();
328 return;
329 }
330 ResetScrolledWindow();
331 }
332
333 void WindowSelectorItem::OnFling(int delta_x, float velocity_x) {
334 if (abs(delta_x) > GetMinimumCloseDistance() ||
335 velocity_x > kMinimumFlingVelocity) {
336 transform_window_.Close();
337 return;
338 }
339 ResetScrolledWindow();
340 }
341
342 void WindowSelectorItem::ResetScrolledWindow() {
343 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
344 transform_window_.BeginScopedAnimation(
345 OverviewAnimationType::OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL,
346 &animation_settings);
347
348 transform_window_.SetTransform(root_window(),
349 transform_window_.get_overview_transform());
350 transform_window_.SetOpacity(1.0);
351
352 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
353 close_button_->SetEnabled(true);
354 }
355
231 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, 356 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
232 OverviewAnimationType animation_type) { 357 OverviewAnimationType animation_type) {
233 DCHECK(root_window_ == GetWindow()->GetRootWindow()); 358 DCHECK(root_window_ == GetWindow()->GetRootWindow());
234 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen(); 359 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen();
235 gfx::Rect selector_item_bounds = 360 gfx::Rect selector_item_bounds =
236 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio( 361 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
237 screen_bounds, target_bounds); 362 screen_bounds, target_bounds);
238 gfx::Transform transform = 363 gfx::Transform transform =
239 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds, 364 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds,
240 selector_item_bounds); 365 selector_item_bounds);
(...skipping 13 matching lines...) Expand all
254 void WindowSelectorItem::UpdateWindowLabel( 379 void WindowSelectorItem::UpdateWindowLabel(
255 const gfx::Rect& window_bounds, 380 const gfx::Rect& window_bounds,
256 OverviewAnimationType animation_type) { 381 OverviewAnimationType animation_type) {
257 // If the root window has changed, force the window label to be recreated 382 // If the root window has changed, force the window label to be recreated
258 // and faded in on the new root window. 383 // and faded in on the new root window.
259 DCHECK(!window_label_ || 384 DCHECK(!window_label_ ||
260 window_label_->GetNativeWindow()->GetRootWindow() == root_window_); 385 window_label_->GetNativeWindow()->GetRootWindow() == root_window_);
261 386
262 if (!window_label_->IsVisible()) { 387 if (!window_label_->IsVisible()) {
263 window_label_->Show(); 388 window_label_->Show();
264 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 389 SetupFadeInAfterLayout(window_label_->GetNativeWindow());
265 window_label_->GetNativeWindow());
266 } 390 }
267 391
268 gfx::Rect converted_bounds = 392 gfx::Rect converted_bounds =
269 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds); 393 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds);
270 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(), 394 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(),
271 converted_bounds.width(), converted_bounds.height()); 395 converted_bounds.width(), converted_bounds.height());
272 window_label_button_view_->set_top_padding(label_bounds.height() - 396 window_label_button_view_->set_top_padding(label_bounds.height() -
273 kVerticalLabelPadding); 397 kVerticalLabelPadding);
274 ScopedOverviewAnimationSettings animation_settings( 398 ScopedOverviewAnimationSettings animation_settings(
275 animation_type, window_label_->GetNativeWindow()); 399 animation_type, window_label_->GetNativeWindow());
(...skipping 28 matching lines...) Expand all
304 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 428 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
305 window_label_button_view_->SetFontList( 429 window_label_button_view_->SetFontList(
306 bundle.GetFontList(ui::ResourceBundle::BoldFont)); 430 bundle.GetFontList(ui::ResourceBundle::BoldFont));
307 window_label_->SetContentsView(window_label_button_view_); 431 window_label_->SetContentsView(window_label_button_view_);
308 } 432 }
309 433
310 void WindowSelectorItem::UpdateCloseButtonLayout( 434 void WindowSelectorItem::UpdateCloseButtonLayout(
311 OverviewAnimationType animation_type) { 435 OverviewAnimationType animation_type) {
312 if (!close_button_->visible()) { 436 if (!close_button_->visible()) {
313 close_button_->SetVisible(true); 437 close_button_->SetVisible(true);
314 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 438 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
315 close_button_widget_.GetNativeWindow());
316 } 439 }
317 ScopedOverviewAnimationSettings animation_settings(animation_type, 440 ScopedOverviewAnimationSettings animation_settings(animation_type,
318 close_button_widget_.GetNativeWindow()); 441 close_button_widget_.GetNativeWindow());
319 442
320 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen( 443 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen(
321 close_button_widget_.GetNativeWindow()->GetRootWindow(), 444 close_button_widget_.GetNativeWindow()->GetRootWindow(),
322 GetTransformedBounds(GetWindow())); 445 GetTransformedBounds(GetWindow()));
323 446
324 gfx::Transform close_button_transform; 447 gfx::Transform close_button_transform;
325 close_button_transform.Translate(transformed_window_bounds.right(), 448 close_button_transform.Translate(transformed_window_bounds.right(),
326 transformed_window_bounds.y()); 449 transformed_window_bounds.y());
327 close_button_widget_.GetNativeWindow()->SetTransform( 450 close_button_widget_.GetNativeWindow()->SetTransform(
328 close_button_transform); 451 close_button_transform);
329 } 452 }
330 453
331 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { 454 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() {
332 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16( 455 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16(
333 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME, 456 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME,
334 GetWindow()->title())); 457 GetWindow()->title()));
335 } 458 }
336 459
460 int WindowSelectorItem::GetMinimumCloseDistance() const {
461 return target_bounds_.size().width() / 2;
462 }
463
337 } // namespace ash 464 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698