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

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 6. 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(
264 ui::GestureEvent* event) {
265
266 if (!Shell::GetInstance()->window_selector_controller()->
267 swipe_to_close_disabled()) {
flackr 2015/02/12 20:52:38 Return early instead.
bruthig 2015/02/12 21:28:44 Done.
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: {
flackr 2015/02/12 20:52:38 I still think it would be correct to mark all of t
bruthig 2015/02/12 21:28:44 Done.
284 ScopedTransformOverviewWindow::ScopedAnimationSettings
285 animation_settings;
286 transform_window_.BeginScopedAnimation(
287 OverviewAnimationType::OVERVIEW_ANIMATION_SCROLL_SELECTOR_ITEM,
288 &animation_settings);
289
290 gfx::Transform new_transform;
291 new_transform.Translate(delta_x, 0);
292 new_transform.PreconcatTransform(
293 transform_window_.get_overview_transform());
294 transform_window_.SetTransform(root_window(), new_transform);
295
296 const float opacity = CalculateOpacityFromScrollDistance(delta_x,
297 GetMinimumCloseDistance());
298 transform_window_.SetOpacity(opacity);
299 break;
300 }
301 case ui::ET_GESTURE_SCROLL_END: {
302 if (abs(delta_x) > GetMinimumCloseDistance()) {
303 transform_window_.Close();
304 break;
305 }
306 ResetScrolledWindow();
307 break;
308 }
309 case ui::ET_SCROLL_FLING_START: {
310 if (abs(delta_x) > GetMinimumCloseDistance() ||
311 fabs(event->details().velocity_x()) > kMinimumFlingVelocity) {
312 transform_window_.Close();
313 break;
314 }
315 ResetScrolledWindow();
316 break;
317 }
318 case ui::ET_GESTURE_END:
319 scroll_x_origin_ = 0;
320 break;
321 default:
322 break;
323 }
324 }
325 }
326
219 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { 327 void WindowSelectorItem::OnWindowDestroying(aura::Window* window) {
220 window->RemoveObserver(this); 328 window->RemoveObserver(this);
221 transform_window_.OnWindowDestroyed(); 329 transform_window_.OnWindowDestroyed();
222 } 330 }
223 331
224 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { 332 void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) {
225 // TODO(flackr): Maybe add the new title to a vector of titles so that we can 333 // 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. 334 // filter any of the titles the window had while in the overview session.
227 window_label_button_view_->SetText(window->title()); 335 window_label_button_view_->SetText(window->title());
228 UpdateCloseButtonAccessibilityName(); 336 UpdateCloseButtonAccessibilityName();
229 } 337 }
230 338
339 void WindowSelectorItem::ResetScrolledWindow() {
340 ScopedTransformOverviewWindow::ScopedAnimationSettings animation_settings;
341 transform_window_.BeginScopedAnimation(
342 OverviewAnimationType::OVERVIEW_ANIMATION_CANCEL_SELECTOR_ITEM_SCROLL,
343 &animation_settings);
344
345 transform_window_.SetTransform(root_window(),
346 transform_window_.get_overview_transform());
347 transform_window_.SetOpacity(1.0);
348
349 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
350 close_button_->SetEnabled(true);
351 }
352
231 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, 353 void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds,
232 OverviewAnimationType animation_type) { 354 OverviewAnimationType animation_type) {
233 DCHECK(root_window_ == GetWindow()->GetRootWindow()); 355 DCHECK(root_window_ == GetWindow()->GetRootWindow());
234 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen(); 356 gfx::Rect screen_bounds = transform_window_.GetTargetBoundsInScreen();
235 gfx::Rect selector_item_bounds = 357 gfx::Rect selector_item_bounds =
236 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio( 358 ScopedTransformOverviewWindow::ShrinkRectToFitPreservingAspectRatio(
237 screen_bounds, target_bounds); 359 screen_bounds, target_bounds);
238 gfx::Transform transform = 360 gfx::Transform transform =
239 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds, 361 ScopedTransformOverviewWindow::GetTransformForRect(screen_bounds,
240 selector_item_bounds); 362 selector_item_bounds);
(...skipping 13 matching lines...) Expand all
254 void WindowSelectorItem::UpdateWindowLabel( 376 void WindowSelectorItem::UpdateWindowLabel(
255 const gfx::Rect& window_bounds, 377 const gfx::Rect& window_bounds,
256 OverviewAnimationType animation_type) { 378 OverviewAnimationType animation_type) {
257 // If the root window has changed, force the window label to be recreated 379 // If the root window has changed, force the window label to be recreated
258 // and faded in on the new root window. 380 // and faded in on the new root window.
259 DCHECK(!window_label_ || 381 DCHECK(!window_label_ ||
260 window_label_->GetNativeWindow()->GetRootWindow() == root_window_); 382 window_label_->GetNativeWindow()->GetRootWindow() == root_window_);
261 383
262 if (!window_label_->IsVisible()) { 384 if (!window_label_->IsVisible()) {
263 window_label_->Show(); 385 window_label_->Show();
264 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 386 SetupFadeInAfterLayout(window_label_->GetNativeWindow());
265 window_label_->GetNativeWindow());
266 } 387 }
267 388
268 gfx::Rect converted_bounds = 389 gfx::Rect converted_bounds =
269 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds); 390 ScreenUtil::ConvertRectFromScreen(root_window_, window_bounds);
270 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(), 391 gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.y(),
271 converted_bounds.width(), converted_bounds.height()); 392 converted_bounds.width(), converted_bounds.height());
272 window_label_button_view_->set_top_padding(label_bounds.height() - 393 window_label_button_view_->set_top_padding(label_bounds.height() -
273 kVerticalLabelPadding); 394 kVerticalLabelPadding);
274 ScopedOverviewAnimationSettings animation_settings( 395 ScopedOverviewAnimationSettings animation_settings(
275 animation_type, window_label_->GetNativeWindow()); 396 animation_type, window_label_->GetNativeWindow());
(...skipping 28 matching lines...) Expand all
304 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 425 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
305 window_label_button_view_->SetFontList( 426 window_label_button_view_->SetFontList(
306 bundle.GetFontList(ui::ResourceBundle::BoldFont)); 427 bundle.GetFontList(ui::ResourceBundle::BoldFont));
307 window_label_->SetContentsView(window_label_button_view_); 428 window_label_->SetContentsView(window_label_button_view_);
308 } 429 }
309 430
310 void WindowSelectorItem::UpdateCloseButtonLayout( 431 void WindowSelectorItem::UpdateCloseButtonLayout(
311 OverviewAnimationType animation_type) { 432 OverviewAnimationType animation_type) {
312 if (!close_button_->visible()) { 433 if (!close_button_->visible()) {
313 close_button_->SetVisible(true); 434 close_button_->SetVisible(true);
314 ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( 435 SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow());
315 close_button_widget_.GetNativeWindow());
316 } 436 }
317 ScopedOverviewAnimationSettings animation_settings(animation_type, 437 ScopedOverviewAnimationSettings animation_settings(animation_type,
318 close_button_widget_.GetNativeWindow()); 438 close_button_widget_.GetNativeWindow());
319 439
320 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen( 440 gfx::Rect transformed_window_bounds = ScreenUtil::ConvertRectFromScreen(
321 close_button_widget_.GetNativeWindow()->GetRootWindow(), 441 close_button_widget_.GetNativeWindow()->GetRootWindow(),
322 GetTransformedBounds(GetWindow())); 442 GetTransformedBounds(GetWindow()));
323 443
324 gfx::Transform close_button_transform; 444 gfx::Transform close_button_transform;
325 close_button_transform.Translate(transformed_window_bounds.right(), 445 close_button_transform.Translate(transformed_window_bounds.right(),
326 transformed_window_bounds.y()); 446 transformed_window_bounds.y());
327 close_button_widget_.GetNativeWindow()->SetTransform( 447 close_button_widget_.GetNativeWindow()->SetTransform(
328 close_button_transform); 448 close_button_transform);
329 } 449 }
330 450
331 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() { 451 void WindowSelectorItem::UpdateCloseButtonAccessibilityName() {
332 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16( 452 close_button_->SetAccessibleName(l10n_util::GetStringFUTF16(
333 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME, 453 IDS_ASH_OVERVIEW_CLOSE_ITEM_BUTTON_ACCESSIBLE_NAME,
334 GetWindow()->title())); 454 GetWindow()->title()));
335 } 455 }
336 456
457 int WindowSelectorItem::GetMinimumCloseDistance() const {
458 return target_bounds_.size().width() / 2;
459 }
460
337 } // namespace ash 461 } // 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