| OLD | NEW |
| 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 Loading... |
| 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" |
| 43 #include "ui/gfx/skia_util.h" | 45 #include "ui/gfx/skia_util.h" |
| 44 #include "ui/gfx/vector_icons_public.h" | 46 #include "ui/gfx/vector_icons_public.h" |
| 45 #include "ui/resources/grit/ui_resources.h" | 47 #include "ui/resources/grit/ui_resources.h" |
| 46 #include "ui/views/border.h" | 48 #include "ui/views/border.h" |
| 47 #include "ui/views/controls/button/image_button.h" | 49 #include "ui/views/controls/button/image_button.h" |
| 48 #include "ui/views/controls/label.h" | 50 #include "ui/views/controls/label.h" |
| 49 #include "ui/views/rect_based_targeting_utils.h" | 51 #include "ui/views/rect_based_targeting_utils.h" |
| 50 #include "ui/views/view_targeter.h" | 52 #include "ui/views/view_targeter.h" |
| 51 #include "ui/views/widget/tooltip_manager.h" | 53 #include "ui/views/widget/tooltip_manager.h" |
| 52 #include "ui/views/widget/widget.h" | 54 #include "ui/views/widget/widget.h" |
| 53 #include "ui/views/window/non_client_view.h" | 55 #include "ui/views/window/non_client_view.h" |
| 54 | 56 |
| 55 #if defined(USE_AURA) | 57 #if defined(USE_AURA) |
| 56 #include "ui/aura/env.h" | 58 #include "ui/aura/env.h" |
| 57 #endif | 59 #endif |
| 58 | 60 |
| 61 #include "base/debug/stack_trace.h" |
| 62 |
| 59 using base::UserMetricsAction; | 63 using base::UserMetricsAction; |
| 60 | 64 |
| 61 namespace { | 65 namespace { |
| 62 | 66 |
| 63 // Height of the shadow at the top of the tab image assets. | 67 // Height of the shadow at the top of the tab image assets. |
| 64 const int kDropShadowHeight = 4; | 68 const int kDropShadowHeight = 4; |
| 65 | 69 |
| 66 // How long the pulse throb takes. | 70 // How long the pulse throb takes. |
| 67 const int kPulseDurationMs = 200; | 71 const int kPulseDurationMs = 200; |
| 68 | 72 |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 // ImageCacheEntry | 389 // ImageCacheEntry |
| 386 | 390 |
| 387 Tab::ImageCacheEntry::ImageCacheEntry() | 391 Tab::ImageCacheEntry::ImageCacheEntry() |
| 388 : resource_id(-1), | 392 : resource_id(-1), |
| 389 scale_factor(ui::SCALE_FACTOR_NONE) { | 393 scale_factor(ui::SCALE_FACTOR_NONE) { |
| 390 } | 394 } |
| 391 | 395 |
| 392 Tab::ImageCacheEntry::~ImageCacheEntry() {} | 396 Tab::ImageCacheEntry::~ImageCacheEntry() {} |
| 393 | 397 |
| 394 //////////////////////////////////////////////////////////////////////////////// | 398 //////////////////////////////////////////////////////////////////////////////// |
| 399 // ThrobberView |
| 400 |
| 401 class Tab::ThrobberView : public views::View { |
| 402 public: |
| 403 ThrobberView(Tab* owner, const gfx::Rect& bounds) |
| 404 : owner_(owner), |
| 405 waiting_arc_(owner_->GetThemeProvider()->GetColor( |
| 406 ThemeProperties::COLOR_THROBBER_WAITING), |
| 407 180) { |
| 408 SetPaintToLayer(true); |
| 409 SetFillsBoundsOpaquely(false); |
| 410 SetBoundsRect(bounds); |
| 411 owner_->AddChildView(this); |
| 412 |
| 413 mask_.SetFillsBoundsOpaquely(false); |
| 414 mask_.SetMasksToBounds(true); |
| 415 } |
| 416 |
| 417 void SchedulePaintIfRequired() { |
| 418 if (NeedsPaint()) |
| 419 SchedulePaint(); |
| 420 } |
| 421 |
| 422 // views::View: |
| 423 void OnBoundsChanged(const gfx::Rect& previous_bounds) override { |
| 424 gfx::Rect bounds = GetLocalBounds(); |
| 425 waiting_arc_.layer()->SetBounds( |
| 426 gfx::Rect(0, 0, bounds.width() * Arc::kAA, bounds.height() * Arc::kAA)); |
| 427 |
| 428 bounds.set_width(bounds.width() / 2); |
| 429 mask_.SetBounds(bounds); |
| 430 } |
| 431 |
| 432 void OnPaint(gfx::Canvas* canvas) override { |
| 433 state_ = owner_->data().network_state; |
| 434 if (state_ == TabRendererData::NETWORK_STATE_NONE) |
| 435 return; |
| 436 |
| 437 const gfx::Rect bounds = GetLocalBounds(); |
| 438 |
| 439 // Paint network activity (aka throbber) animation frame. |
| 440 ui::ThemeProvider* tp = owner_->GetThemeProvider(); |
| 441 if (state_ == TabRendererData::NETWORK_STATE_WAITING) { |
| 442 // Painted by Arc. |
| 443 } else { |
| 444 if (loading_start_time_ == base::TimeTicks()) |
| 445 loading_start_time_ = base::TimeTicks::Now(); |
| 446 |
| 447 waiting_state_.color = |
| 448 tp->GetColor(ThemeProperties::COLOR_THROBBER_WAITING); |
| 449 gfx::PaintThrobberSpinningAfterWaiting( |
| 450 canvas, bounds, |
| 451 tp->GetColor(ThemeProperties::COLOR_THROBBER_SPINNING), |
| 452 base::TimeTicks::Now() - loading_start_time_, &waiting_state_); |
| 453 } |
| 454 } |
| 455 |
| 456 private: |
| 457 class Arc : public ui::LayerDelegate { |
| 458 public: |
| 459 // Since the rotation transform mis-aligns the pixel anti-aliasing done by |
| 460 // Skia, perform a kind of FSAA by drawing on a larger canvas and scaling |
| 461 // down as part of the transform. |
| 462 static const int kAA = 4; |
| 463 |
| 464 Arc(SkColor color, SkScalar sweep) |
| 465 : color_(color), sweep_(sweep), layer_(ui::LAYER_TEXTURED) { |
| 466 layer_.set_delegate(this); |
| 467 layer_.SetFillsBoundsOpaquely(false); |
| 468 } |
| 469 |
| 470 ui::Layer* layer() { return &layer_; } |
| 471 |
| 472 void SetAngle(SkScalar angle) { |
| 473 const gfx::Size size = layer()->size(); |
| 474 gfx::Transform transform; |
| 475 transform.Translate(size.width() / 2.0 / kAA, size.height() / 2.0 / kAA); |
| 476 transform.Rotate(-angle); |
| 477 transform.Scale(1.0 / kAA, 1.0 / kAA); |
| 478 transform.Translate(-size.width() / 2, -size.height() / 2); |
| 479 layer()->SetTransform(transform); |
| 480 } |
| 481 |
| 482 // LayerDelegate: |
| 483 void OnPaintLayer(const ui::PaintContext& context) override { |
| 484 const gfx::Size size = layer()->size(); |
| 485 ui::PaintRecorder recorder(context, size); |
| 486 gfx::PaintThrobberArc(recorder.canvas(), gfx::Rect(size), color_, -90, |
| 487 sweep_); |
| 488 } |
| 489 |
| 490 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {} |
| 491 void OnDeviceScaleFactorChanged(float device_scale_factor) override {} |
| 492 base::Closure PrepareForLayerBoundsChange() override { |
| 493 return base::Closure(); |
| 494 } |
| 495 |
| 496 private: |
| 497 SkColor color_; |
| 498 SkScalar sweep_; |
| 499 ui::Layer layer_; |
| 500 |
| 501 DISALLOW_COPY_AND_ASSIGN(Arc); |
| 502 }; |
| 503 |
| 504 void ApplyWaitingRotation(const base::TimeDelta& elapsed_time) { |
| 505 const base::TimeDelta revolution_time = |
| 506 base::TimeDelta::FromMilliseconds(1320); |
| 507 bool needs_mask = elapsed_time < revolution_time / 2; |
| 508 mask_.SetMasksToBounds(needs_mask); |
| 509 waiting_arc_.SetAngle(360 * waiting_state_.elapsed_time / revolution_time); |
| 510 } |
| 511 |
| 512 bool NeedsPaint() { |
| 513 if (bounds().IsEmpty()) |
| 514 return false; |
| 515 |
| 516 TabRendererData::NetworkState new_state = owner_->data().network_state; |
| 517 const bool changing_state = new_state != state_; |
| 518 |
| 519 // Waiting throbber is fully layer-backed. |
| 520 if (new_state == TabRendererData::NETWORK_STATE_WAITING) { |
| 521 if (waiting_start_time_ == base::TimeTicks()) |
| 522 waiting_start_time_ = base::TimeTicks::Now(); |
| 523 |
| 524 state_ = new_state; |
| 525 waiting_state_.elapsed_time = |
| 526 base::TimeTicks::Now() - waiting_start_time_; |
| 527 layer()->Add(&mask_); |
| 528 mask_.Add(waiting_arc_.layer()); |
| 529 ApplyWaitingRotation(waiting_state_.elapsed_time); |
| 530 return changing_state; |
| 531 } |
| 532 |
| 533 return true; |
| 534 } |
| 535 |
| 536 Tab* owner_; // Weak. Owns this. |
| 537 |
| 538 TabRendererData::NetworkState state_ = TabRendererData::NETWORK_STATE_NONE; |
| 539 |
| 540 // The point in time when the tab icon was first painted in the waiting state. |
| 541 base::TimeTicks waiting_start_time_; |
| 542 |
| 543 // The point in time when the tab icon was first painted in the loading state. |
| 544 base::TimeTicks loading_start_time_; |
| 545 |
| 546 // Paint state for the throbber after the most recent waiting paint. |
| 547 gfx::ThrobberWaitingState waiting_state_; |
| 548 |
| 549 ui::Layer mask_; |
| 550 Arc waiting_arc_; |
| 551 |
| 552 DISALLOW_COPY_AND_ASSIGN(ThrobberView); |
| 553 }; |
| 554 |
| 555 //////////////////////////////////////////////////////////////////////////////// |
| 395 // Tab, statics: | 556 // Tab, statics: |
| 396 | 557 |
| 397 // static | 558 // static |
| 398 const char Tab::kViewClassName[] = "Tab"; | 559 const char Tab::kViewClassName[] = "Tab"; |
| 399 Tab::TabImage Tab::tab_active_ = {0}; | 560 Tab::TabImage Tab::tab_active_ = {0}; |
| 400 Tab::TabImage Tab::tab_inactive_ = {0}; | 561 Tab::TabImage Tab::tab_inactive_ = {0}; |
| 401 Tab::TabImage Tab::tab_alpha_ = {0}; | 562 Tab::TabImage Tab::tab_alpha_ = {0}; |
| 402 Tab::ImageCache* Tab::image_cache_ = NULL; | 563 Tab::ImageCache* Tab::image_cache_ = NULL; |
| 403 | 564 |
| 404 //////////////////////////////////////////////////////////////////////////////// | 565 //////////////////////////////////////////////////////////////////////////////// |
| 405 // Tab, public: | 566 // Tab, public: |
| 406 | 567 |
| 407 Tab::Tab(TabController* controller) | 568 Tab::Tab(TabController* controller) |
| 408 : controller_(controller), | 569 : controller_(controller), |
| 409 closing_(false), | 570 closing_(false), |
| 410 dragging_(false), | 571 dragging_(false), |
| 411 detached_(false), | 572 detached_(false), |
| 412 favicon_hiding_offset_(0), | 573 favicon_hiding_offset_(0), |
| 413 immersive_loading_step_(0), | 574 immersive_loading_step_(0), |
| 414 should_display_crashed_favicon_(false), | 575 should_display_crashed_favicon_(false), |
| 576 throbber_(nullptr), |
| 415 media_indicator_button_(nullptr), | 577 media_indicator_button_(nullptr), |
| 416 close_button_(nullptr), | 578 close_button_(nullptr), |
| 417 title_(new views::Label()), | 579 title_(new views::Label()), |
| 418 tab_activated_with_last_tap_down_(false), | 580 tab_activated_with_last_tap_down_(false), |
| 419 hover_controller_(this), | 581 hover_controller_(this), |
| 420 showing_icon_(false), | 582 showing_icon_(false), |
| 421 showing_media_indicator_(false), | 583 showing_media_indicator_(false), |
| 422 showing_close_button_(false), | 584 showing_close_button_(false), |
| 423 button_color_(SK_ColorTRANSPARENT) { | 585 button_color_(SK_ColorTRANSPARENT) { |
| 424 DCHECK(controller); | 586 DCHECK(controller); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 } | 707 } |
| 546 | 708 |
| 547 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { | 709 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { |
| 548 if (state == data_.network_state && | 710 if (state == data_.network_state && |
| 549 state == TabRendererData::NETWORK_STATE_NONE) { | 711 state == TabRendererData::NETWORK_STATE_NONE) { |
| 550 // If the network state is none and hasn't changed, do nothing. Otherwise we | 712 // If the network state is none and hasn't changed, do nothing. Otherwise we |
| 551 // need to advance the animation frame. | 713 // need to advance the animation frame. |
| 552 return; | 714 return; |
| 553 } | 715 } |
| 554 | 716 |
| 555 TabRendererData::NetworkState old_state = data_.network_state; | |
| 556 data_.network_state = state; | 717 data_.network_state = state; |
| 557 AdvanceLoadingAnimation(old_state, state); | 718 AdvanceLoadingAnimation(state); |
| 558 } | 719 } |
| 559 | 720 |
| 560 void Tab::StartPulse() { | 721 void Tab::StartPulse() { |
| 561 pulse_animation_.reset(new gfx::ThrobAnimation(this)); | 722 pulse_animation_.reset(new gfx::ThrobAnimation(this)); |
| 562 pulse_animation_->SetSlideDuration(kPulseDurationMs); | 723 pulse_animation_->SetSlideDuration(kPulseDurationMs); |
| 563 if (animation_container_.get()) | 724 if (animation_container_.get()) |
| 564 pulse_animation_->SetContainer(animation_container_.get()); | 725 pulse_animation_->SetContainer(animation_container_.get()); |
| 565 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); | 726 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); |
| 566 } | 727 } |
| 567 | 728 |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 const int extra_padding = | 941 const int extra_padding = |
| 781 (controller_->ShouldHideCloseButtonForInactiveTabs() || | 942 (controller_->ShouldHideCloseButtonForInactiveTabs() || |
| 782 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; | 943 (IconCapacity() < 3)) ? 0 : kExtraLeftPaddingToBalanceCloseButtonPadding; |
| 783 const int start = lb.x() + extra_padding; | 944 const int start = lb.x() + extra_padding; |
| 784 favicon_bounds_.SetRect(start, lb.y(), 0, 0); | 945 favicon_bounds_.SetRect(start, lb.y(), 0, 0); |
| 785 if (showing_icon_) { | 946 if (showing_icon_) { |
| 786 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); | 947 favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); |
| 787 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); | 948 favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); |
| 788 MaybeAdjustLeftForPinnedTab(&favicon_bounds_); | 949 MaybeAdjustLeftForPinnedTab(&favicon_bounds_); |
| 789 } | 950 } |
| 951 if (throbber_) |
| 952 throbber_->SetBoundsRect(favicon_bounds_); |
| 790 | 953 |
| 791 showing_close_button_ = ShouldShowCloseBox(); | 954 showing_close_button_ = ShouldShowCloseBox(); |
| 792 if (showing_close_button_) { | 955 if (showing_close_button_) { |
| 793 // If the ratio of the close button size to tab width exceeds the maximum. | 956 // 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 | 957 // 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 | 958 // 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 | 959 // 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. | 960 // 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 | 961 // 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 | 962 // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target |
| (...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 } | 1503 } |
| 1341 | 1504 |
| 1342 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1505 void Tab::PaintIcon(gfx::Canvas* canvas) { |
| 1343 gfx::Rect bounds = favicon_bounds_; | 1506 gfx::Rect bounds = favicon_bounds_; |
| 1344 if (bounds.IsEmpty()) | 1507 if (bounds.IsEmpty()) |
| 1345 return; | 1508 return; |
| 1346 | 1509 |
| 1347 bounds.set_x(GetMirroredXForRect(bounds)); | 1510 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1348 | 1511 |
| 1349 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { | 1512 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { |
| 1350 // Paint network activity (aka throbber) animation frame. | 1513 // 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_) { | 1514 } else if (should_display_crashed_favicon_) { |
| 1373 // Paint crash favicon. | 1515 // Paint crash favicon. |
| 1374 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1516 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 1375 gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); | 1517 gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); |
| 1376 bounds.set_y(bounds.y() + favicon_hiding_offset_); | 1518 bounds.set_y(bounds.y() + favicon_hiding_offset_); |
| 1377 DrawIconCenter(canvas, crashed_favicon, 0, | 1519 DrawIconCenter(canvas, crashed_favicon, 0, |
| 1378 crashed_favicon.width(), | 1520 crashed_favicon.width(), |
| 1379 crashed_favicon.height(), | 1521 crashed_favicon.height(), |
| 1380 bounds, true, SkPaint()); | 1522 bounds, true, SkPaint()); |
| 1381 } else if (!data().favicon.isNull()) { | 1523 } else if (!data().favicon.isNull()) { |
| 1382 // Paint the normal favicon. | 1524 // Paint the normal favicon. |
| 1383 DrawIconCenter(canvas, data().favicon, 0, | 1525 DrawIconCenter(canvas, data().favicon, 0, |
| 1384 data().favicon.width(), | 1526 data().favicon.width(), |
| 1385 data().favicon.height(), | 1527 data().favicon.height(), |
| 1386 bounds, true, SkPaint()); | 1528 bounds, true, SkPaint()); |
| 1387 } | 1529 } |
| 1388 } | 1530 } |
| 1389 | 1531 |
| 1390 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, | 1532 void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState state) { |
| 1391 TabRendererData::NetworkState state) { | |
| 1392 if (state == TabRendererData::NETWORK_STATE_WAITING) { | 1533 if (state == TabRendererData::NETWORK_STATE_WAITING) { |
| 1393 // Waiting steps backwards. | 1534 // Waiting steps backwards. |
| 1394 immersive_loading_step_ = | 1535 immersive_loading_step_ = |
| 1395 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % | 1536 (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % |
| 1396 kImmersiveLoadingStepCount; | 1537 kImmersiveLoadingStepCount; |
| 1397 } else if (state == TabRendererData::NETWORK_STATE_LOADING) { | 1538 } else if (state == TabRendererData::NETWORK_STATE_LOADING) { |
| 1398 immersive_loading_step_ = (immersive_loading_step_ + 1) % | 1539 immersive_loading_step_ = (immersive_loading_step_ + 1) % |
| 1399 kImmersiveLoadingStepCount; | 1540 kImmersiveLoadingStepCount; |
| 1400 } else { | 1541 } else { |
| 1401 waiting_start_time_ = base::TimeTicks(); | |
| 1402 loading_start_time_ = base::TimeTicks(); | |
| 1403 waiting_state_ = gfx::ThrobberWaitingState(); | |
| 1404 immersive_loading_step_ = 0; | 1542 immersive_loading_step_ = 0; |
| 1405 } | 1543 } |
| 1544 |
| 1406 if (controller_->IsImmersiveStyle()) { | 1545 if (controller_->IsImmersiveStyle()) { |
| 1407 SchedulePaintInRect(GetImmersiveBarRect()); | 1546 SchedulePaintInRect(GetImmersiveBarRect()); |
| 1408 } else { | 1547 return; |
| 1548 } |
| 1549 |
| 1550 const bool needs_throbber = state != TabRendererData::NETWORK_STATE_NONE; |
| 1551 if (needs_throbber && !throbber_) { |
| 1552 throbber_ = new ThrobberView(this, favicon_bounds_); |
| 1553 ScheduleIconPaint(); // Repaint the icon area to not show the icon. |
| 1554 } else if (!needs_throbber) { |
| 1555 delete throbber_; |
| 1556 throbber_ = nullptr; |
| 1409 ScheduleIconPaint(); | 1557 ScheduleIconPaint(); |
| 1410 } | 1558 } |
| 1559 if (throbber_) |
| 1560 throbber_->SchedulePaintIfRequired(); |
| 1411 } | 1561 } |
| 1412 | 1562 |
| 1413 int Tab::IconCapacity() const { | 1563 int Tab::IconCapacity() const { |
| 1414 const gfx::Size min_size(GetMinimumUnselectedSize()); | 1564 const gfx::Size min_size(GetMinimumUnselectedSize()); |
| 1415 if (height() < min_size.height()) | 1565 if (height() < min_size.height()) |
| 1416 return 0; | 1566 return 0; |
| 1417 const int available_width = std::max(0, width() - min_size.width()); | 1567 const int available_width = std::max(0, width() - min_size.width()); |
| 1418 // All icons are the same size as the favicon. | 1568 // All icons are the same size as the favicon. |
| 1419 const int icon_width = gfx::kFaviconSize; | 1569 const int icon_width = gfx::kFaviconSize; |
| 1420 // We need enough space to display the icons flush against each other. | 1570 // We need enough space to display the icons flush against each other. |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 const gfx::ImageSkia& image) { | 1829 const gfx::ImageSkia& image) { |
| 1680 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1830 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
| 1681 ImageCacheEntry entry; | 1831 ImageCacheEntry entry; |
| 1682 entry.resource_id = resource_id; | 1832 entry.resource_id = resource_id; |
| 1683 entry.scale_factor = scale_factor; | 1833 entry.scale_factor = scale_factor; |
| 1684 entry.image = image; | 1834 entry.image = image; |
| 1685 image_cache_->push_front(entry); | 1835 image_cache_->push_front(entry); |
| 1686 if (image_cache_->size() > kMaxImageCacheSize) | 1836 if (image_cache_->size() > kMaxImageCacheSize) |
| 1687 image_cache_->pop_back(); | 1837 image_cache_->pop_back(); |
| 1688 } | 1838 } |
| OLD | NEW |