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

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

Issue 1381203002: An energy usage monitor for Mac, and some layer-backed throbber experiments Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Paint the throbber to a layer TODO: make it a layered animation 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') | chrome/chrome_tests.gypi » ('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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include "ui/views/rect_based_targeting_utils.h" 49 #include "ui/views/rect_based_targeting_utils.h"
50 #include "ui/views/view_targeter.h" 50 #include "ui/views/view_targeter.h"
51 #include "ui/views/widget/tooltip_manager.h" 51 #include "ui/views/widget/tooltip_manager.h"
52 #include "ui/views/widget/widget.h" 52 #include "ui/views/widget/widget.h"
53 #include "ui/views/window/non_client_view.h" 53 #include "ui/views/window/non_client_view.h"
54 54
55 #if defined(USE_AURA) 55 #if defined(USE_AURA)
56 #include "ui/aura/env.h" 56 #include "ui/aura/env.h"
57 #endif 57 #endif
58 58
59 #include "base/debug/stack_trace.h"
60
59 using base::UserMetricsAction; 61 using base::UserMetricsAction;
60 62
61 namespace { 63 namespace {
62 64
63 // Height of the shadow at the top of the tab image assets. 65 // Height of the shadow at the top of the tab image assets.
64 const int kDropShadowHeight = 4; 66 const int kDropShadowHeight = 4;
65 67
66 // How long the pulse throb takes. 68 // How long the pulse throb takes.
67 const int kPulseDurationMs = 200; 69 const int kPulseDurationMs = 200;
68 70
(...skipping 61 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
142 class ThrobberView : public views::View {
143 public:
144 ThrobberView(Tab* owner, const gfx::Rect& bounds) : owner_(owner) {
145 SetPaintToLayer(true);
146 SetFillsBoundsOpaquely(false);
147 SetBoundsRect(bounds);
148 owner_->AddChildView(this);
149 }
150
151 // views::View:
152 void OnPaint(gfx::Canvas* canvas) override {
153 const TabRendererData::NetworkState state = owner_->data().network_state;
154 if (state == TabRendererData::NETWORK_STATE_NONE)
155 return;
156
157 const gfx::Rect bounds = GetLocalBounds(); // Adjust for RTL?
158
159 // Paint network activity (aka throbber) animation frame.
160 ui::ThemeProvider* tp = owner_->GetThemeProvider();
161 if (state == TabRendererData::NETWORK_STATE_WAITING) {
162 if (waiting_start_time_ == base::TimeTicks())
163 waiting_start_time_ = base::TimeTicks::Now();
164
165 waiting_state_.elapsed_time =
166 base::TimeTicks::Now() - waiting_start_time_;
167 gfx::PaintThrobberWaiting(
168 canvas, bounds, tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING),
169 waiting_state_.elapsed_time);
170 } else {
171 if (loading_start_time_ == base::TimeTicks())
172 loading_start_time_ = base::TimeTicks::Now();
173
174 waiting_state_.color =
175 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
176 gfx::PaintThrobberSpinningAfterWaiting(
177 canvas, bounds,
178 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
179 base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
180 }
181 }
182
183 private:
184 Tab* owner_; // Weak. Owns this.
185
186 // The point in time when the tab icon was first painted in the waiting state.
187 base::TimeTicks waiting_start_time_;
188
189 // The point in time when the tab icon was first painted in the loading state.
190 base::TimeTicks loading_start_time_;
191
192 // Paint state for the throbber after the most recent waiting paint.
193 gfx::ThrobberWaitingState waiting_state_;
194
195 DISALLOW_COPY_AND_ASSIGN(ThrobberView);
196 };
197
140 void DrawIconAtLocation(gfx::Canvas* canvas, 198 void DrawIconAtLocation(gfx::Canvas* canvas,
141 const gfx::ImageSkia& image, 199 const gfx::ImageSkia& image,
142 int image_offset, 200 int image_offset,
143 int dst_x, 201 int dst_x,
144 int dst_y, 202 int dst_y,
145 int icon_width, 203 int icon_width,
146 int icon_height, 204 int icon_height,
147 bool filter, 205 bool filter,
148 const SkPaint& paint) { 206 const SkPaint& paint) {
149 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. 207 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary.
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 // Tab, public: 463 // Tab, public:
406 464
407 Tab::Tab(TabController* controller) 465 Tab::Tab(TabController* controller)
408 : controller_(controller), 466 : controller_(controller),
409 closing_(false), 467 closing_(false),
410 dragging_(false), 468 dragging_(false),
411 detached_(false), 469 detached_(false),
412 favicon_hiding_offset_(0), 470 favicon_hiding_offset_(0),
413 immersive_loading_step_(0), 471 immersive_loading_step_(0),
414 should_display_crashed_favicon_(false), 472 should_display_crashed_favicon_(false),
473 throbber_(nullptr),
415 media_indicator_button_(nullptr), 474 media_indicator_button_(nullptr),
416 close_button_(nullptr), 475 close_button_(nullptr),
417 title_(new views::Label()), 476 title_(new views::Label()),
418 tab_activated_with_last_tap_down_(false), 477 tab_activated_with_last_tap_down_(false),
419 hover_controller_(this), 478 hover_controller_(this),
420 showing_icon_(false), 479 showing_icon_(false),
421 showing_media_indicator_(false), 480 showing_media_indicator_(false),
422 showing_close_button_(false), 481 showing_close_button_(false),
423 button_color_(SK_ColorTRANSPARENT) { 482 button_color_(SK_ColorTRANSPARENT) {
424 DCHECK(controller); 483 DCHECK(controller);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 } 604 }
546 605
547 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { 606 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) {
548 if (state == data_.network_state && 607 if (state == data_.network_state &&
549 state == TabRendererData::NETWORK_STATE_NONE) { 608 state == TabRendererData::NETWORK_STATE_NONE) {
550 // If the network state is none and hasn't changed, do nothing. Otherwise we 609 // If the network state is none and hasn't changed, do nothing. Otherwise we
551 // need to advance the animation frame. 610 // need to advance the animation frame.
552 return; 611 return;
553 } 612 }
554 613
555 TabRendererData::NetworkState old_state = data_.network_state;
556 data_.network_state = state; 614 data_.network_state = state;
557 AdvanceLoadingAnimation(old_state, state); 615 AdvanceLoadingAnimation(state);
558 } 616 }
559 617
560 void Tab::StartPulse() { 618 void Tab::StartPulse() {
561 pulse_animation_.reset(new gfx::ThrobAnimation(this)); 619 pulse_animation_.reset(new gfx::ThrobAnimation(this));
562 pulse_animation_->SetSlideDuration(kPulseDurationMs); 620 pulse_animation_->SetSlideDuration(kPulseDurationMs);
563 if (animation_container_.get()) 621 if (animation_container_.get())
564 pulse_animation_->SetContainer(animation_container_.get()); 622 pulse_animation_->SetContainer(animation_container_.get());
565 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); 623 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
566 } 624 }
567 625
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 const int extra_padding = 838 const int extra_padding =
781 (controller_->ShouldHideCloseButtonForInactiveTabs() || 839 (controller_->ShouldHideCloseButtonForInactiveTabs() ||
782 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; 840 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding;
783 const int start = lb.x() + extra_padding; 841 const int start = lb.x() + extra_padding;
784 favicon_bounds_.SetRect(start, lb.y(), 0, 0); 842 favicon_bounds_.SetRect(start, lb.y(), 0, 0);
785 if (showing_icon_) { 843 if (showing_icon_) {
786 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); 844 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize));
787 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); 845 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2);
788 MaybeAdjustLeftForPinnedTab(&favicon_bounds_); 846 MaybeAdjustLeftForPinnedTab(&favicon_bounds_);
789 } 847 }
848 if (throbber_)
849 throbber_->SetBoundsRect(favicon_bounds_);
790 850
791 showing_close_button_ = ShouldShowCloseBox(); 851 showing_close_button_ = ShouldShowCloseBox();
792 if (showing_close_button_) { 852 if (showing_close_button_) {
793 // If the ratio of the close button size to tab width exceeds the maximum. 853 // If the ratio of the close button size to tab width exceeds the maximum.
794 // The close button should be as large as possible so that there is a larger 854 // The close button should be as large as possible so that there is a larger
795 // hit-target for touch events. So the close button bounds extends to the 855 // hit-target for touch events. So the close button bounds extends to the
796 // edges of the tab. However, the larger hit-target should be active only 856 // edges of the tab. However, the larger hit-target should be active only
797 // for mouse events, and the close-image should show up in the right place. 857 // for mouse events, and the close-image should show up in the right place.
798 // So a border is added to the button with necessary padding. The close 858 // So a border is added to the button with necessary padding. The close
799 // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target 859 // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 } 1400 }
1341 1401
1342 void Tab::PaintIcon(gfx::Canvas* canvas) { 1402 void Tab::PaintIcon(gfx::Canvas* canvas) {
1343 gfx::Rect bounds = favicon_bounds_; 1403 gfx::Rect bounds = favicon_bounds_;
1344 if (bounds.IsEmpty()) 1404 if (bounds.IsEmpty())
1345 return; 1405 return;
1346 1406
1347 bounds.set_x(GetMirroredXForRect(bounds)); 1407 bounds.set_x(GetMirroredXForRect(bounds));
1348 1408
1349 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { 1409 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) {
1350 // Paint network activity (aka throbber) animation frame. 1410 // Throbber will do its own painting.
1351 ui::ThemeProvider* tp = GetThemeProvider();
1352 if (data().network_state == TabRendererData::NETWORK_STATE_WAITING) {
1353 if (waiting_start_time_ == base::TimeTicks())
1354 waiting_start_time_ = base::TimeTicks::Now();
1355
1356 waiting_state_.elapsed_time =
1357 base::TimeTicks::Now() - waiting_start_time_;
1358 gfx::PaintThrobberWaiting(
1359 canvas, bounds, tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING),
1360 waiting_state_.elapsed_time);
1361 } else {
1362 if (loading_start_time_ == base::TimeTicks())
1363 loading_start_time_ = base::TimeTicks::Now();
1364
1365 waiting_state_.color =
1366 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING);
1367 gfx::PaintThrobberSpinningAfterWaiting(
1368 canvas, bounds,
1369 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING),
1370 base::TimeTicks::Now() - loading_start_time_, &waiting_state_);
1371 }
1372 } else if (should_display_crashed_favicon_) { 1411 } else if (should_display_crashed_favicon_) {
1373 // Paint crash favicon. 1412 // Paint crash favicon.
1374 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1413 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1375 gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); 1414 gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON));
1376 bounds.set_y(bounds.y() + favicon_hiding_offset_); 1415 bounds.set_y(bounds.y() + favicon_hiding_offset_);
1377 DrawIconCenter(canvas, crashed_favicon, 0, 1416 DrawIconCenter(canvas, crashed_favicon, 0,
1378 crashed_favicon.width(), 1417 crashed_favicon.width(),
1379 crashed_favicon.height(), 1418 crashed_favicon.height(),
1380 bounds, true, SkPaint()); 1419 bounds, true, SkPaint());
1381 } else if (!data().favicon.isNull()) { 1420 } else if (!data().favicon.isNull()) {
1382 // Paint the normal favicon. 1421 // Paint the normal favicon.
1383 DrawIconCenter(canvas, data().favicon, 0, 1422 DrawIconCenter(canvas, data().favicon, 0,
1384 data().favicon.width(), 1423 data().favicon.width(),
1385 data().favicon.height(), 1424 data().favicon.height(),
1386 bounds, true, SkPaint()); 1425 bounds, true, SkPaint());
1387 } 1426 }
1388 } 1427 }
1389 1428
1390 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, 1429 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState state) {
1391 TabRendererData::NetworkState state) {
1392 if (state == TabRendererData::NETWORK_STATE_WAITING) { 1430 if (state == TabRendererData::NETWORK_STATE_WAITING) {
1393 // Waiting steps backwards. 1431 // Waiting steps backwards.
1394 immersive_loading_step_ = 1432 immersive_loading_step_ =
1395 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % 1433 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) %
1396 kImmersiveLoadingStepCount; 1434 kImmersiveLoadingStepCount;
1397 } else if (state == TabRendererData::NETWORK_STATE_LOADING) { 1435 } else if (state == TabRendererData::NETWORK_STATE_LOADING) {
1398 immersive_loading_step_ = (immersive_loading_step_ + 1) % 1436 immersive_loading_step_ = (immersive_loading_step_ + 1) %
1399 kImmersiveLoadingStepCount; 1437 kImmersiveLoadingStepCount;
1400 } else { 1438 } else {
1401 waiting_start_time_ = base::TimeTicks();
1402 loading_start_time_ = base::TimeTicks();
1403 waiting_state_ = gfx::ThrobberWaitingState();
1404 immersive_loading_step_ = 0; 1439 immersive_loading_step_ = 0;
1405 } 1440 }
1441
1406 if (controller_->IsImmersiveStyle()) { 1442 if (controller_->IsImmersiveStyle()) {
1407 SchedulePaintInRect(GetImmersiveBarRect()); 1443 SchedulePaintInRect(GetImmersiveBarRect());
1408 } else { 1444 return;
1445 }
1446
1447 const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE;
1448 if (needs_throbber && !throbber_) {
1449 throbber_ = new ThrobberView(this, favicon_bounds_);
1450 ScheduleIconPaint(); // Repaint the icon area to not show the icon.
1451 } else if (!needs_throbber) {
1452 delete throbber_;
1453 throbber_ = nullptr;
1409 ScheduleIconPaint(); 1454 ScheduleIconPaint();
1410 } 1455 }
1456 if (throbber_)
1457 throbber_->SchedulePaint();
1411 } 1458 }
1412 1459
1413 int Tab::IconCapacity() const { 1460 int Tab::IconCapacity() const {
1414 const gfx::Size min_size(GetMinimumUnselectedSize()); 1461 const gfx::Size min_size(GetMinimumUnselectedSize());
1415 if (height() < min_size.height()) 1462 if (height() < min_size.height())
1416 return 0; 1463 return 0;
1417 const int available_width = std::max(0, width() - min_size.width()); 1464 const int available_width = std::max(0, width() - min_size.width());
1418 // All icons are the same size as the favicon. 1465 // All icons are the same size as the favicon.
1419 const int icon_width = gfx::kFaviconSize; 1466 const int icon_width = gfx::kFaviconSize;
1420 // We need enough space to display the icons flush against each other. 1467 // We need enough space to display the icons flush against each other.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 const gfx::ImageSkia& image) { 1726 const gfx::ImageSkia& image) {
1680 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); 1727 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE);
1681 ImageCacheEntry entry; 1728 ImageCacheEntry entry;
1682 entry.resource_id = resource_id; 1729 entry.resource_id = resource_id;
1683 entry.scale_factor = scale_factor; 1730 entry.scale_factor = scale_factor;
1684 entry.image = image; 1731 entry.image = image;
1685 image_cache_->push_front(entry); 1732 image_cache_->push_front(entry);
1686 if (image_cache_->size() > kMaxImageCacheSize) 1733 if (image_cache_->size() > kMaxImageCacheSize)
1687 image_cache_->pop_back(); 1734 image_cache_->pop_back();
1688 } 1735 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698