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

Side by Side Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 1400783002: Use a layer transform for the waiting throbber Base URL: https://chromium.googlesource.com/chromium/src.git@20151006-MacViewsBrowser-Power
Patch Set: Fix color Created 5 years, 2 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 | « chrome/browser/ui/views/tabs/tab.h ('k') | ui/gfx/paint_throbber.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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/ui/views/tabs/tab.h" 5 #include "chrome/browser/ui/views/tabs/tab.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/alias.h" 10 #include "base/debug/alias.h"
(...skipping 12 matching lines...) Expand all
23 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/grit/generated_resources.h" 24 #include "chrome/grit/generated_resources.h"
25 #include "content/public/browser/user_metrics.h" 25 #include "content/public/browser/user_metrics.h"
26 #include "grit/theme_resources.h" 26 #include "grit/theme_resources.h"
27 #include "third_party/skia/include/effects/SkGradientShader.h" 27 #include "third_party/skia/include/effects/SkGradientShader.h"
28 #include "ui/accessibility/ax_view_state.h" 28 #include "ui/accessibility/ax_view_state.h"
29 #include "ui/base/l10n/l10n_util.h" 29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/models/list_selection_model.h" 30 #include "ui/base/models/list_selection_model.h"
31 #include "ui/base/resource/resource_bundle.h" 31 #include "ui/base/resource/resource_bundle.h"
32 #include "ui/base/theme_provider.h" 32 #include "ui/base/theme_provider.h"
33 #include "ui/compositor/layer_animator.h"
34 #include "ui/compositor/paint_recorder.h"
33 #include "ui/gfx/animation/animation_container.h" 35 #include "ui/gfx/animation/animation_container.h"
34 #include "ui/gfx/animation/multi_animation.h" 36 #include "ui/gfx/animation/multi_animation.h"
35 #include "ui/gfx/animation/throb_animation.h" 37 #include "ui/gfx/animation/throb_animation.h"
36 #include "ui/gfx/canvas.h" 38 #include "ui/gfx/canvas.h"
37 #include "ui/gfx/color_analysis.h" 39 #include "ui/gfx/color_analysis.h"
38 #include "ui/gfx/favicon_size.h" 40 #include "ui/gfx/favicon_size.h"
39 #include "ui/gfx/geometry/rect_conversions.h" 41 #include "ui/gfx/geometry/rect_conversions.h"
40 #include "ui/gfx/image/image_skia_operations.h" 42 #include "ui/gfx/image/image_skia_operations.h"
41 #include "ui/gfx/paint_vector_icon.h" 43 #include "ui/gfx/paint_vector_icon.h"
42 #include "ui/gfx/path.h" 44 #include "ui/gfx/path.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 // The minimum opacity (out of 1) when a tab (either active or inactive) is 132 // The minimum opacity (out of 1) when a tab (either active or inactive) is
131 // throbbing in the immersive mode light strip. 133 // throbbing in the immersive mode light strip.
132 const double kImmersiveTabMinThrobOpacity = 0.66; 134 const double kImmersiveTabMinThrobOpacity = 0.66;
133 135
134 // Number of steps in the immersive mode loading animation. 136 // Number of steps in the immersive mode loading animation.
135 const int kImmersiveLoadingStepCount = 32; 137 const int kImmersiveLoadingStepCount = 32;
136 138
137 const char kTabCloseButtonName[] = "TabCloseButton"; 139 const char kTabCloseButtonName[] = "TabCloseButton";
138 const int kTabCloseButtonSize = 16; 140 const int kTabCloseButtonSize = 16;
139 141
140 // Layer-backed view for updating a waiting or loading tab spinner.
141 class ThrobberView : public views::View {
142 public:
143 explicit ThrobberView(Tab* owner) : owner_(owner) {
144 // Since the throbber animates, paint to a separate layer do reduce repaint
145 // overheads.
146 SetPaintToLayer(true);
147 SetFillsBoundsOpaquely(false);
148 }
149
150 // views::View:
151 bool CanProcessEventsWithinSubtree() const override { return false; }
152
153 void OnPaint(gfx::Canvas* canvas) override {
154 const TabRendererData::NetworkState state = owner_->data().network_state;
155 if (state == TabRendererData::NETWORK_STATE_NONE)
156 return;
157
158 const gfx::Rect bounds = GetLocalBounds();
159
160 // Paint network activity (aka throbber) animation frame.
161 ui::ThemeProvider* tp = GetThemeProvider();
162 if (state == TabRendererData::NETWORK_STATE_WAITING) {
163 if (waiting_start_time_ == base::TimeTicks())
164 waiting_start_time_ = base::TimeTicks::Now();
165
166 waiting_state_.elapsed_time =
167 base::TimeTicks::Now() - waiting_start_time_;
168 gfx::PaintThrobberWaiting(
169 canvas, bounds, tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING),
170 waiting_state_.elapsed_time);
171 } else {
172 if (loading_start_time_ == base::TimeTicks())
173 loading_start_time_ = base::TimeTicks::Now();
174
175 waiting_state_.color =
176 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
177 gfx::PaintThrobberSpinningAfterWaiting(
178 canvas, bounds,
179 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
180 base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
181 }
182 }
183
184 private:
185 Tab* owner_; // Weak. Owns |this|.
186
187 // The point in time when the tab icon was first painted in the waiting state.
188 base::TimeTicks waiting_start_time_;
189
190 // The point in time when the tab icon was first painted in the loading state.
191 base::TimeTicks loading_start_time_;
192
193 // Paint state for the throbber after the most recent waiting paint.
194 gfx::ThrobberWaitingState waiting_state_;
195
196 DISALLOW_COPY_AND_ASSIGN(ThrobberView);
197 };
198
199 void DrawIconAtLocation(gfx::Canvas* canvas, 142 void DrawIconAtLocation(gfx::Canvas* canvas,
200 const gfx::ImageSkia& image, 143 const gfx::ImageSkia& image,
201 int image_offset, 144 int image_offset,
202 int dst_x, 145 int dst_x,
203 int dst_y, 146 int dst_y,
204 int icon_width, 147 int icon_width,
205 int icon_height, 148 int icon_height,
206 bool filter, 149 bool filter,
207 const SkPaint& paint) { 150 const SkPaint& paint) {
208 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. 151 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary.
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 // ImageCacheEntry 387 // ImageCacheEntry
445 388
446 Tab::ImageCacheEntry::ImageCacheEntry() 389 Tab::ImageCacheEntry::ImageCacheEntry()
447 : resource_id(-1), 390 : resource_id(-1),
448 scale_factor(ui::SCALE_FACTOR_NONE) { 391 scale_factor(ui::SCALE_FACTOR_NONE) {
449 } 392 }
450 393
451 Tab::ImageCacheEntry::~ImageCacheEntry() {} 394 Tab::ImageCacheEntry::~ImageCacheEntry() {}
452 395
453 //////////////////////////////////////////////////////////////////////////////// 396 ////////////////////////////////////////////////////////////////////////////////
397 // ThrobberView
398
399 // Layer-backed view for updating a waiting or loading tab spinner.
400 class Tab::ThrobberView : public views::View {
401 public:
402 explicit ThrobberView(Tab* owner) : owner_(owner), waiting_arc_(180) {
403 // Since the throbber animates, paint to a separate layer do reduce repaint
404 // overheads.
405 SetPaintToLayer(true);
406 SetFillsBoundsOpaquely(false);
407
408 waiting_mask_.SetFillsBoundsOpaquely(false);
409 waiting_mask_.SetMasksToBounds(true);
410 waiting_mask_.Add(waiting_arc_.layer());
411 }
412
413 void SchedulePaintIfRequired() {
414 if (NeedsPaint())
415 SchedulePaint();
416 }
417
418 // views::View:
419 bool CanProcessEventsWithinSubtree() const override { return false; }
420
421 void OnBoundsChanged(const gfx::Rect& previous_bounds) override {
422 gfx::Rect bounds = GetLocalBounds();
423 waiting_arc_.layer()->SetBounds(
424 gfx::Rect(0, 0, bounds.width() * Arc::kAA, bounds.height() * Arc::kAA));
425
426 bounds.set_width(bounds.width() / 2);
427 waiting_mask_.SetBounds(bounds);
428 }
429
430 void OnPaint(gfx::Canvas* canvas) override {
431 if (state_ == TabRendererData::NETWORK_STATE_NONE)
432 return;
433
434 const gfx::Rect bounds = GetLocalBounds();
435
436 // Paint network activity (aka throbber) animation frame.
437 ui::ThemeProvider* tp = owner_->GetThemeProvider();
438 if (state_ == TabRendererData::NETWORK_STATE_WAITING) {
439 // Painted by Arc.
440 } else {
441 if (loading_start_time_ == base::TimeTicks())
442 loading_start_time_ = base::TimeTicks::Now();
443
444 waiting_state_.color =
445 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
446 gfx::PaintThrobberSpinningAfterWaiting(
447 canvas, bounds,
448 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
449 base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
450 }
451 }
452
453 private:
454 class Arc : public ui::LayerDelegate {
455 public:
456 // Since the rotation transform mis-aligns the pixel anti-aliasing done by
457 // Skia, perform a kind of FSAA by drawing on a larger canvas and scaling
458 // down as part of the transform.
459 static const int kAA = 1;
460
461 explicit Arc(SkScalar sweep)
462 : color_(SK_ColorRED), sweep_(sweep), layer_(ui::LAYER_TEXTURED) {
463 layer_.set_delegate(this);
464 layer_.SetFillsBoundsOpaquely(false);
465 }
466
467 ui::Layer* layer() { return &layer_; }
468
469 void set_color(SkColor color) { color_ = color; }
470
471 void SetAngle(SkScalar angle) {
472 const gfx::Size size = layer()->size();
473 gfx::Transform transform;
474 transform.Translate(size.width() / 2.0 / kAA, size.height() / 2.0 / kAA);
475 transform.Rotate(-angle);
476 transform.Scale(1.0 / kAA, 1.0 / kAA);
477 transform.Translate(-size.width() / 2, -size.height() / 2);
478 layer()->SetTransform(transform);
479 }
480
481 // LayerDelegate:
482 void OnPaintLayer(const ui::PaintContext& context) override {
483 const gfx::Size size = layer()->size();
484 ui::PaintRecorder recorder(context, size);
485 gfx::PaintThrobberArc(recorder.canvas(), gfx::Rect(size), color_, -90,
486 sweep_);
487 }
488
489 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
490 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
491 base::Closure PrepareForLayerBoundsChange() override {
492 return base::Closure();
493 }
494
495 private:
496 SkColor color_;
497 SkScalar sweep_;
498 ui::Layer layer_;
499
500 DISALLOW_COPY_AND_ASSIGN(Arc);
501 };
502
503 void ApplyWaitingRotation(const base::TimeDelta& elapsed_time) {
504 const base::TimeDelta revolution_time =
505 base::TimeDelta::FromMilliseconds(1320);
506 bool needs_mask = elapsed_time < revolution_time / 2;
507 waiting_mask_.SetMasksToBounds(needs_mask);
508 waiting_arc_.SetAngle(360 * waiting_state_.elapsed_time / revolution_time);
509 waiting_arc_.set_color(
510 GetThemeProvider()->GetColor(ThemeProperties::COLOR_THROBBER_WAITING));
511 }
512
513 bool NeedsPaint() {
514 if (bounds().IsEmpty())
515 return false;
516
517 TabRendererData::NetworkState new_state = owner_->data().network_state;
518 const bool changing_state = new_state != state_;
519
520 // Waiting throbber is fully layer-backed.
521 if (new_state == TabRendererData::NETWORK_STATE_WAITING) {
522 if (waiting_start_time_ == base::TimeTicks())
523 waiting_start_time_ = base::TimeTicks::Now();
524
525 state_ = new_state;
526 waiting_state_.elapsed_time =
527 base::TimeTicks::Now() - waiting_start_time_;
528 layer()->Add(&waiting_mask_);
529 ApplyWaitingRotation(waiting_state_.elapsed_time);
530 return changing_state;
531 }
532
533 if (state_ == TabRendererData::NETWORK_STATE_WAITING)
534 layer()->Remove(&waiting_mask_);
535
536 state_ = new_state;
537
538 return true;
539 }
540
541 Tab* owner_; // Weak. Owns this.
542
543 TabRendererData::NetworkState state_ = TabRendererData::NETWORK_STATE_NONE;
544
545 // The point in time when the tab icon was first painted in the waiting state.
546 base::TimeTicks waiting_start_time_;
547
548 // The point in time when the tab icon was first painted in the loading state.
549 base::TimeTicks loading_start_time_;
550
551 // Paint state for the throbber after the most recent waiting paint.
552 gfx::ThrobberWaitingState waiting_state_;
553
554 ui::Layer waiting_mask_;
555 Arc waiting_arc_;
556
557 DISALLOW_COPY_AND_ASSIGN(ThrobberView);
558 };
559
560 ////////////////////////////////////////////////////////////////////////////////
454 // Tab, statics: 561 // Tab, statics:
455 562
456 // static 563 // static
457 const char Tab::kViewClassName[] = "Tab"; 564 const char Tab::kViewClassName[] = "Tab";
458 Tab::TabImage Tab::tab_active_ = {0}; 565 Tab::TabImage Tab::tab_active_ = {0};
459 Tab::TabImage Tab::tab_inactive_ = {0}; 566 Tab::TabImage Tab::tab_inactive_ = {0};
460 Tab::TabImage Tab::tab_alpha_ = {0}; 567 Tab::TabImage Tab::tab_alpha_ = {0};
461 Tab::ImageCache* Tab::image_cache_ = NULL; 568 Tab::ImageCache* Tab::image_cache_ = NULL;
462 569
463 //////////////////////////////////////////////////////////////////////////////// 570 ////////////////////////////////////////////////////////////////////////////////
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 // the left since the shoulder of a dragged tab can still paint over the icon. 1560 // the left since the shoulder of a dragged tab can still paint over the icon.
1454 gfx::Rect clip = GetLocalBounds(); 1561 gfx::Rect clip = GetLocalBounds();
1455 const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE && 1562 const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE &&
1456 controller_->ShouldPaintTab(this, &clip) && 1563 controller_->ShouldPaintTab(this, &clip) &&
1457 clip.x() == 0 && clip.Contains(favicon_bounds_); 1564 clip.x() == 0 && clip.Contains(favicon_bounds_);
1458 1565
1459 if (needs_throbber != throbber_->visible()) { 1566 if (needs_throbber != throbber_->visible()) {
1460 ScheduleIconPaint(); // Repaint the icon area to update favicon visibility. 1567 ScheduleIconPaint(); // Repaint the icon area to update favicon visibility.
1461 throbber_->SetVisible(needs_throbber); 1568 throbber_->SetVisible(needs_throbber);
1462 } 1569 }
1463 throbber_->SchedulePaint(); 1570 throbber_->SchedulePaintIfRequired();
1464 } 1571 }
1465 1572
1466 int Tab::IconCapacity() const { 1573 int Tab::IconCapacity() const {
1467 const gfx::Size min_size(GetMinimumUnselectedSize()); 1574 const gfx::Size min_size(GetMinimumUnselectedSize());
1468 if (height() < min_size.height()) 1575 if (height() < min_size.height())
1469 return 0; 1576 return 0;
1470 const int available_width = std::max(0, width() - min_size.width()); 1577 const int available_width = std::max(0, width() - min_size.width());
1471 // All icons are the same size as the favicon. 1578 // All icons are the same size as the favicon.
1472 const int icon_width = gfx::kFaviconSize; 1579 const int icon_width = gfx::kFaviconSize;
1473 // We need enough space to display the icons flush against each other. 1580 // We need enough space to display the icons flush against each other.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 const gfx::ImageSkia& image) { 1839 const gfx::ImageSkia& image) {
1733 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); 1840 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE);
1734 ImageCacheEntry entry; 1841 ImageCacheEntry entry;
1735 entry.resource_id = resource_id; 1842 entry.resource_id = resource_id;
1736 entry.scale_factor = scale_factor; 1843 entry.scale_factor = scale_factor;
1737 entry.image = image; 1844 entry.image = image;
1738 image_cache_->push_front(entry); 1845 image_cache_->push_front(entry);
1739 if (image_cache_->size() > kMaxImageCacheSize) 1846 if (image_cache_->size() > kMaxImageCacheSize)
1740 image_cache_->pop_back(); 1847 image_cache_->pop_back();
1741 } 1848 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | ui/gfx/paint_throbber.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698