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

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 flackr's comments from Patch Set 7. 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
« no previous file with comments | « ash/wm/overview/window_selector_item.h ('k') | ash/wm/overview/window_selector_unittest.cc » ('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/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 selector_item_->OnGestureEvent(event);
158 views::LabelButton::OnGestureEvent(event);
159 }
160
117 WindowSelectorItem::WindowSelectorItem(aura::Window* window) 161 WindowSelectorItem::WindowSelectorItem(aura::Window* window)
118 : dimmed_(false), 162 : dimmed_(false),
119 root_window_(window->GetRootWindow()), 163 root_window_(window->GetRootWindow()),
120 transform_window_(window), 164 transform_window_(window),
121 in_bounds_update_(false), 165 in_bounds_update_(false),
122 window_label_button_view_(nullptr), 166 window_label_button_view_(nullptr),
123 close_button_(new OverviewCloseButton(this)) { 167 close_button_(new OverviewCloseButton(this)) {
124 CreateWindowLabel(window->title()); 168 CreateWindowLabel(window->title());
125 views::Widget::InitParams params; 169 views::Widget::InitParams params;
126 params.type = views::Widget::InitParams::TYPE_POPUP; 170 params.type = views::Widget::InitParams::TYPE_POPUP;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 void WindowSelectorItem::ButtonPressed(views::Button* sender, 253 void WindowSelectorItem::ButtonPressed(views::Button* sender,
210 const ui::Event& event) { 254 const ui::Event& event) {
211 if (sender == close_button_) { 255 if (sender == close_button_) {
212 transform_window_.Close(); 256 transform_window_.Close();
213 return; 257 return;
214 } 258 }
215 CHECK(sender == window_label_button_view_); 259 CHECK(sender == window_label_button_view_);
216 wm::GetWindowState(transform_window_.window())->Activate(); 260 wm::GetWindowState(transform_window_.window())->Activate();
217 } 261 }
218 262
263 void WindowSelectorItem::OnGestureEvent(ui::GestureEvent* event) {
264 if (Shell::GetInstance()->window_selector_controller()->
265 swipe_to_close_disabled())
266 return;
267
268 int delta_x = 0;
269 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)
270 scroll_x_origin_ = event->x();
271 else
272 delta_x = event->x() - scroll_x_origin_;
273
274 switch (event->type()) {
275 case ui::ET_GESTURE_SCROLL_BEGIN: {
276 // We need to call SetHandled() for the ET_GESTURE_SCROLL_BEGIN event so
277 // that future ET_GESTURE_SCROLL_* events are sent here.
278 event->SetHandled();
279 close_button_->SetEnabled(false);
280 SetupFadeOut(close_button_widget_.GetNativeWindow());
281 break;
282 }
283 case ui::ET_GESTURE_SCROLL_UPDATE: {
284 event->SetHandled();
285 ScopedTransformOverviewWindow::ScopedAnimationSettings
286 animation_settings;
287 transform_window_.BeginScopedAnimation(
288 OverviewAnimationType::OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM,
289 &animation_settings);
290
291 gfx::Transform new_transform;
292 new_transform.Translate(delta_x, 0);
293 new_transform.PreconcatTransform(
294 transform_window_.get_overview_transform());
295 transform_window_.SetTransform(root_window(), new_transform);
296
297 const float opacity = CalculateOpacityFromScrollDistance(delta_x,
298 GetMinimumCloseDistance());
299 transform_window_.SetOpacity(opacity);
300 break;
301 }
302 case ui::ET_GESTURE_SCROLL_END: {
303 event->SetHandled();
304 if (abs(delta_x) > GetMinimumCloseDistance()) {
305 transform_window_.Close();
306 break;
307 }
308 ResetScrolledWindow();
309 break;
310 }
311 case ui::ET_SCROLL_FLING_START: {
312 event->SetHandled();
313 if (abs(delta_x) > GetMinimumCloseDistance() ||
314 fabs(event->details().velocity_x()) > kMinimumFlingVelocity) {
315 transform_window_.Close();
316 break;
317 }
318 ResetScrolledWindow();
319 break;
320 }
321 case ui::ET_GESTURE_END:
322 scroll_x_origin_ = 0;
323 break;
324 default:
325 break;
326 }
327 }
328
219 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { 329 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) {
220 window->RemoveObserver(this); 330 window->RemoveObserver(this);
221 transform_window_.OnWindowDestroyed(); 331 transform_window_.OnWindowDestroyed();
222 } 332 }
223 333
224 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { 334 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) {
225 // TODO(flackr): Maybe add the new title to a vector of titles so that we can 335 // 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. 336 // filter any of the titles the window had while in the overview session.
227 window_label_button_view_->SetText(window->title()); 337 window_label_button_view_->SetText(window->title());
228 UpdateCloseButtonAccessibilityName(); 338 UpdateCloseButtonAccessibilityName();
229 } 339 }
230 340
341 void WindowSelectorItem::ResetScrolledWindow() {
342 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
343 transform_window_.BeginScopedAnimation(
344 OverviewAnimationType::OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL,
345 &animation_settings);
346
347 transform_window_.SetTransform(root_window(),
348 transform_window_.get_overview_transform());
349 transform_window_.SetOpacity(1.0);
350
351 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
352 close_button_->SetEnabled(true);
353 }
354
231 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, 355 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
232 OverviewAnimationType animation_type) { 356 OverviewAnimationType animation_type) {
233 DCHECK(root_window_ == GetWindow()->GetRootWindow()); 357 DCHECK(root_window_ == GetWindow()->GetRootWindow());
234 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen(); 358 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen();
235 gfx::Rect selector_item_bounds = 359 gfx::Rect selector_item_bounds =
236 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio( 360 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
237 screen_bounds, target_bounds); 361 screen_bounds, target_bounds);
238 gfx::Transform transform = 362 gfx::Transform transform =
239 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds, 363 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds,
240 selector_item_bounds); 364 selector_item_bounds);
(...skipping 13 matching lines...) Expand all
254 void WindowSelectorItem::UpdateWindowLabel( 378 void WindowSelectorItem::UpdateWindowLabel(
255 const gfx::Rect& window_bounds, 379 const gfx::Rect& window_bounds,
256 OverviewAnimationType animation_type) { 380 OverviewAnimationType animation_type) {
257 // If the root window has changed, force the window label to be recreated 381 // If the root window has changed, force the window label to be recreated
258 // and faded in on the new root window. 382 // and faded in on the new root window.
259 DCHECK(!window_label_ || 383 DCHECK(!window_label_ ||
260 window_label_->GetNativeWindow()->GetRootWindow() == root_window_); 384 window_label_->GetNativeWindow()->GetRootWindow() == root_window_);
261 385
262 if (!window_label_->IsVisible()) { 386 if (!window_label_->IsVisible()) {
263 window_label_->Show(); 387 window_label_->Show();
264 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 388 SetupFadeInAfterLayout(window_label_->GetNativeWindow());
265 window_label_->GetNativeWindow());
266 } 389 }
267 390
268 gfx::Rect converted_bounds = 391 gfx::Rect converted_bounds =
269 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds); 392 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds);
270 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(), 393 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(),
271 converted_bounds.width(), converted_bounds.height()); 394 converted_bounds.width(), converted_bounds.height());
272 window_label_button_view_->set_top_padding(label_bounds.height() - 395 window_label_button_view_->set_top_padding(label_bounds.height() -
273 kVerticalLabelPadding); 396 kVerticalLabelPadding);
274 ScopedOverviewAnimationSettings animation_settings( 397 ScopedOverviewAnimationSettings animation_settings(
275 animation_type, window_label_->GetNativeWindow()); 398 animation_type, window_label_->GetNativeWindow());
(...skipping 28 matching lines...) Expand all
304 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 427 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
305 window_label_button_view_->SetFontList( 428 window_label_button_view_->SetFontList(
306 bundle.GetFontList(ui::ResourceBundle::BoldFont)); 429 bundle.GetFontList(ui::ResourceBundle::BoldFont));
307 window_label_->SetContentsView(window_label_button_view_); 430 window_label_->SetContentsView(window_label_button_view_);
308 } 431 }
309 432
310 void WindowSelectorItem::UpdateCloseButtonLayout( 433 void WindowSelectorItem::UpdateCloseButtonLayout(
311 OverviewAnimationType animation_type) { 434 OverviewAnimationType animation_type) {
312 if (!close_button_->visible()) { 435 if (!close_button_->visible()) {
313 close_button_->SetVisible(true); 436 close_button_->SetVisible(true);
314 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 437 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
315 close_button_widget_.GetNativeWindow());
316 } 438 }
317 ScopedOverviewAnimationSettings animation_settings(animation_type, 439 ScopedOverviewAnimationSettings animation_settings(animation_type,
318 close_button_widget_.GetNativeWindow()); 440 close_button_widget_.GetNativeWindow());
319 441
320 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen( 442 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen(
321 close_button_widget_.GetNativeWindow()->GetRootWindow(), 443 close_button_widget_.GetNativeWindow()->GetRootWindow(),
322 GetTransformedBounds(GetWindow())); 444 GetTransformedBounds(GetWindow()));
323 445
324 gfx::Transform close_button_transform; 446 gfx::Transform close_button_transform;
325 close_button_transform.Translate(transformed_window_bounds.right(), 447 close_button_transform.Translate(transformed_window_bounds.right(),
326 transformed_window_bounds.y()); 448 transformed_window_bounds.y());
327 close_button_widget_.GetNativeWindow()->SetTransform( 449 close_button_widget_.GetNativeWindow()->SetTransform(
328 close_button_transform); 450 close_button_transform);
329 } 451 }
330 452
331 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { 453 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() {
332 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16( 454 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16(
333 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME, 455 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME,
334 GetWindow()->title())); 456 GetWindow()->title()));
335 } 457 }
336 458
459 int WindowSelectorItem::GetMinimumCloseDistance() const {
460 return target_bounds_.size().width() / 2;
461 }
462
337 } // namespace ash 463 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/overview/window_selector_item.h ('k') | ash/wm/overview/window_selector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698