15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/alias.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/defaults.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/themes/theme_properties.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tab_contents/core_tab_helper.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_resources.h" 1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_utils.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/view_ids.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/views/tabs/media_indicator_button.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab_controller.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/theme_image_mapper.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/views/touch_uma/touch_uma.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/user_metrics.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/effects/SkGradientShader.h" 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/aura/env.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/models/list_selection_model.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/theme_provider.h" 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/animation_container.h" 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/multi_animation.h" 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/throb_animation.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/color_analysis.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/path.h" 420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ui/gfx/rect_conversions.h" 430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ui/gfx/skia_util.h" 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/border.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/image_button.h" 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/views/controls/label.h" 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/views/rect_based_targeting_utils.h" 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/views/view_targeter.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/tooltip_manager.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/window/non_client_view.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing base::UserMetricsAction; 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding around the "content" of a tab, occupied by the tab border graphics. 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst int kLeftPadding = 22; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kTopPadding = 4; 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst int kRightPadding = 17; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kBottomPadding = 2; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Height of the shadow at the top of the tab image assets. 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst int kDropShadowHeight = 4; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// How long the pulse throb takes. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPulseDurationMs = 200; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width of touch tabs. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kTouchWidth = 120; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kToolbarOverlap = 1; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFaviconTitleSpacing = 4; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const int kViewSpacing = 3; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kStandardTitleWidth = 175; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When a non-mini-tab becomes a mini-tab the width of the tab animates. If 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is rendered as a normal tab. This is done to avoid having the title 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// immediately disappear when transitioning a tab from normal to mini-tab. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTabRendererAsNormalTabWidth = 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_defaults::kMiniTabWidth + 30; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How opaque to make the hover state (out of 1). 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const double kHoverOpacity = 0.33; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opacity for non-active selected tabs. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const double kSelectedTabOpacity = .45; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Selected (but not active) tabs have their throb value scaled down by this. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const double kSelectedTabThrobScale = .5; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Durations for the various parts of the mini tab title animation. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationDuration1MS = 1600; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationStart1MS = 0; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationEnd1MS = 1900; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationDuration2MS = 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationDuration3MS = 550; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationStart3MS = 150; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationEnd3MS = 800; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeAnimationIntervalMS = 40; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Offset from the right edge for the start of the mini title change animation. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeInitialXOffset = 6; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Radius of the radial gradient used for mini title change animation. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMiniTitleChangeGradientRadius = 20; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Colors of the gradient used during the mini title change animation. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const SkColor kMiniTitleChangeGradientColor2 = 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColorSetARGB(0, 255, 255, 255); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Max number of images to cache. This has to be at least two since rounding 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// errors may lead to tabs in the same tabstrip having different sizes. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxImageCacheSize = 4; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Height of the miniature tab strip in immersive mode. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kImmersiveTabHeight = 3; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Height of the small tab indicator rectangles in immersive mode. 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kImmersiveBarHeight = 2; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Color for active and inactive tabs in the immersive mode light strip. These 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// should be a little brighter than the color of the normal art assets for tabs, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// which for active tabs is 230, 230, 230 and for inactive is 184, 184, 184. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// The minimum opacity (out of 1) when a tab (either active or inactive) is 132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// throbbing in the immersive mode light strip. 133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst double kImmersiveTabMinThrobOpacity = 0.66; 134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of steps in the immersive mode loading animation. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kImmersiveLoadingStepCount = 32; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)const char kTabCloseButtonName[] = "TabCloseButton"; 1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DrawIconAtLocation(gfx::Canvas* canvas, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::ImageSkia& image, 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int image_offset, 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int dst_x, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int dst_y, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_width, 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_height, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool filter, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SkPaint& paint) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->Save(); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->ClipRect(gfx::Rect(dst_x, dst_y, icon_width, icon_height)); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->DrawImageInt(image, 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_offset, 0, icon_width, icon_height, 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dst_x, dst_y, icon_width, icon_height, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) filter, paint); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->Restore(); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Draws the icon image at the center of |bounds|. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DrawIconCenter(gfx::Canvas* canvas, 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::ImageSkia& image, 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int image_offset, 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_width, 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_height, 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Rect& bounds, 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool filter, 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SkPaint& paint) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Center the image within bounds. 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int dst_x = bounds.x() - (icon_width - bounds.width()) / 2; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int dst_y = bounds.y() - (icon_height - bounds.height()) / 2; 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DrawIconAtLocation(canvas, image, image_offset, dst_x, dst_y, icon_width, 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_height, filter, paint); 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)chrome::HostDesktopType GetHostDesktopType(views::View* view) { 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Widget is NULL when tabs are detached. 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget* widget = view->GetWidget(); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return chrome::GetHostDesktopTypeForNativeView( 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget ? widget->GetNativeView() : NULL); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Stop()s |animation| and then deletes it. We do this rather than just deleting 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// so that the delegate is notified before the destruction. 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid StopAndDeleteAnimation(scoped_ptr<gfx::Animation> animation) { 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (animation) 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch animation->Stop(); 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FaviconCrashAnimation 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A custom animation subclass to manage the favicon crash animation. 195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class Tab::FaviconCrashAnimation : public gfx::LinearAnimation, 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) public gfx::AnimationDelegate { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit FaviconCrashAnimation(Tab* target) 199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : gfx::LinearAnimation(1000, 25, this), 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_(target) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~FaviconCrashAnimation() {} 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // gfx::Animation overrides: 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void AnimateToState(double state) OVERRIDE { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const double kHidingOffset = 27; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state < .5) { 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_->SetFaviconHidingOffset( 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<int>(floor(kHidingOffset * 2.0 * state))); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_->DisplayCrashedFavicon(); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_->SetFaviconHidingOffset( 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<int>( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // gfx::AnimationDelegate overrides: 220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) target_->SetFaviconHidingOffset(0); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* target_; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TabCloseButton 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is a Button subclass that causes middle clicks to be forwarded to the 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// parent View by explicitly not handling them in OnMousePressed. 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass Tab::TabCloseButton : public views::ImageButton, 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public views::MaskedTargeterDelegate { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch explicit TabCloseButton(Tab* tab) 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : views::ImageButton(tab), 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tab_(tab) { 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetEventTargeter( 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~TabCloseButton() {} 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // views::View: 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE { 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Tab close button has no children, so tooltip handler should be the same 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // as the event handler. 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // In addition, a hit test has to be performed for the point (as 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // GetTooltipHandlerForPoint() is responsible for it). 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!HitTestPoint(point)) 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetEventHandlerForPoint(point); 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tab_->controller_->OnMouseEventInTab(this, event); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool handled = ImageButton::OnMousePressed(event); 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Explicitly mark midle-mouse clicks as non-handled to ensure the tab 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sees them. 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return event.IsOnlyMiddleMouseButton() ? false : handled; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE { 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tab_->controller_->OnMouseEventInTab(this, event); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CustomButton::OnMouseMoved(event); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tab_->controller_->OnMouseEventInTab(this, event); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CustomButton::OnMouseReleased(event); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Consume all gesture events here so that the parent (Tab) does not 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // start consuming gestures. 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ImageButton::OnGestureEvent(event); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->SetHandled(); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual const char* GetClassName() const OVERRIDE { 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kTabCloseButtonName; 2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns the rectangular bounds of parent tab's visible region in the 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // local coordinate space of |this|. 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect GetTabBounds() const { 2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) gfx::Path tab_mask; 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tab_->GetHitTestMask(&tab_mask); 2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) gfx::RectF tab_bounds_f(gfx::SkRectToRectF(tab_mask.getBounds())); 2960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) views::View::ConvertRectToTarget(tab_, this, &tab_bounds_f); 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::ToEnclosingRect(tab_bounds_f); 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns the rectangular bounds of the tab close button in the local 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // coordinate space of |this|, not including clipped regions on the top 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // or bottom of the button. |tab_bounds| is the rectangular bounds of 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the parent tab's visible region in the local coordinate space of |this|. 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect GetTabCloseButtonBounds(const gfx::Rect& tab_bounds) const { 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect button_bounds(GetContentsBounds()); 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch button_bounds.set_x(GetMirroredXForRect(button_bounds)); 3070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int top_overflow = tab_bounds.y() - button_bounds.y(); 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int bottom_overflow = button_bounds.bottom() - tab_bounds.bottom(); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (top_overflow > 0) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) button_bounds.set_y(tab_bounds.y()); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else if (bottom_overflow > 0) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) button_bounds.set_height(button_bounds.height() - bottom_overflow); 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return button_bounds; 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // views::ViewTargeterDelegate: 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual View* TargetForRect(View* root, const gfx::Rect& rect) OVERRIDE { 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK_EQ(root, this); 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!views::UsePointBasedTargeting(rect)) 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ViewTargeterDelegate::TargetForRect(root, rect); 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ignore the padding set on the button. 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Rect contents_bounds = GetContentsBounds(); 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) contents_bounds.set_x(GetMirroredXForRect(contents_bounds)); 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Include the padding in hit-test for touch events. 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (aura::Env::GetInstance()->is_touch_down()) 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) contents_bounds = GetLocalBounds(); 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return contents_bounds.Intersects(rect) ? this : parent(); 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // views:MaskedTargeterDelegate: 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual bool GetHitTestMask(gfx::Path* mask) const OVERRIDE { 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(mask); 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->reset(); 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The parent tab may be partially occluded by another tab if we are 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // in stacked tab mode, which means that the tab close button may also 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // be partially occluded. Define the hit test mask of the tab close 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // button to be the intersection of the parent tab's visible bounds 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // and the bounds of the tab close button. 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect tab_bounds(GetTabBounds()); 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect button_bounds(GetTabCloseButtonBounds(tab_bounds)); 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect intersection(gfx::IntersectRects(tab_bounds, button_bounds)); 3490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!intersection.IsEmpty()) { 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->addRect(RectToSkRect(intersection)); 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 3530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 3560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual bool DoesIntersectRect(const View* target, 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::Rect& rect) const OVERRIDE { 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK_EQ(target, this); 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the request is not made in response to a gesture, use the 363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // default implementation. 364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (views::UsePointBasedTargeting(rect)) 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return MaskedTargeterDelegate::DoesIntersectRect(target, rect); 366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The hit test request is in response to a gesture. Return false if any 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // part of the tab close button is hidden from the user. 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(tdanderson): Consider always returning the intersection if the 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // non-rectangular shape of the tab can be accounted for. 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect tab_bounds(GetTabBounds()); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect button_bounds(GetTabCloseButtonBounds(tab_bounds)); 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!tab_bounds.Contains(button_bounds)) 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return MaskedTargeterDelegate::DoesIntersectRect(target, rect); 3770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* tab_; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TabCloseButton); 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ImageCacheEntry 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::ImageCacheEntry::ImageCacheEntry() 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : resource_id(-1), 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale_factor(ui::SCALE_FACTOR_NONE) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::ImageCacheEntry::~ImageCacheEntry() {} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tab, statics: 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 398b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char Tab::kViewClassName[] = "Tab"; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::TabImage Tab::tab_active_ = {0}; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::TabImage Tab::tab_inactive_ = {0}; 401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Tab::TabImage Tab::tab_alpha_ = {0}; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::ImageCache* Tab::image_cache_ = NULL; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tab, public: 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::Tab(TabController* controller) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : controller_(controller), 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_(false), 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dragging_(false), 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch detached_(false), 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_hiding_offset_(0), 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_(0), 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) immersive_loading_step_(0), 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) should_display_crashed_favicon_(false), 416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) close_button_(NULL), 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_(NULL), 418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_(new views::Label()), 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tab_activated_with_last_tap_down_(false), 420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) hover_controller_(this), 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) showing_icon_(false), 4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) showing_media_indicator_(false), 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) showing_close_button_(false), 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_button_color_(0) { 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(controller); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitTabResources(); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // So we get don't get enter/exit on children and don't prematurely stop the 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // hover. 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_notify_enter_exit_on_child(true); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_id(VIEW_ID_TAB); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetElideBehavior(gfx::FADE_TAIL); 436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetAutoColorReadabilityEnabled(false); 437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetText(CoreTabHelper::GetDefaultTitle()); 438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AddChildView(title_); 439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetEventTargeter( 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this))); 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Add the Close Button. 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_ = new TabCloseButton(this); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetImage(views::CustomButton::STATE_NORMAL, 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_1)); 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetImage(views::CustomButton::STATE_HOVERED, 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_1_H)); 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetImage(views::CustomButton::STATE_PRESSED, 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_1_P)); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetAccessibleName( 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Disable animation so that the red danger sign shows up immediately 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to help avoid mis-clicks. 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetAnimationDuration(0); 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(close_button_); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_context_menu_controller(this); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Tab::~Tab() { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Tab::set_animation_container(gfx::AnimationContainer* container) { 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) animation_container_ = container; 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.SetAnimationContainer(container); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Tab::IsActive() const { 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return controller_->IsActiveTab(this); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Tab::IsSelected() const { 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return controller_->IsTabSelected(this); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::SetData(const TabRendererData& data) { 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_.Equals(data)) 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabRendererData old(data_); 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_ = data; 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::string16 title = data_.title; 486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (title.empty()) { 487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title = data_.loading ? 488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : 489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CoreTabHelper::GetDefaultTitle(); 490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } else { 491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Browser::FormatTitleForDisplay(&title); 492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetText(title); 494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data_.IsCrashed()) { 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) { 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data_.media_state = TAB_MEDIA_STATE_NONE; 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS) 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // On Chrome OS, we reload killed tabs automatically when the user 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // switches to them. Don't display animations for these unless they're 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // selected (i.e. in the foreground) -- we won't reload these 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // automatically since we don't want to get into a crash loop. 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsSelected() || 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_.crashed_status != base::TERMINATION_STATUS_PROCESS_WAS_KILLED) 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartCrashAnimation(); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartCrashAnimation(); 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsPerformingCrashAnimation()) 5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StopCrashAnimation(); 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResetCrashedFavicon(); 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (data_.media_state != old.media_state) 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetMediaIndicatorButton()->TransitionToMediaState(data_.media_state); 5184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (old.mini != data_.mini) { 520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch StopAndDeleteAnimation( 521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_.PassAs<gfx::Animation>()); 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DataChanged(old); 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Layout(); 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state == data_.network_state && 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state == TabRendererData::NETWORK_STATE_NONE) { 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the network state is none and hasn't changed, do nothing. Otherwise we 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // need to advance the animation frame. 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabRendererData::NetworkState old_state = data_.network_state; 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_.network_state = state; 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AdvanceLoadingAnimation(old_state, state); 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::StartPulse() { 544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pulse_animation_.reset(new gfx::ThrobAnimation(this)); 545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pulse_animation_->SetSlideDuration(kPulseDurationMs); 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (animation_container_.get()) 547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pulse_animation_->SetContainer(animation_container_.get()); 548116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::StopPulse() { 552116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch StopAndDeleteAnimation(pulse_animation_.PassAs<gfx::Animation>()); 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::StartMiniTabTitleAnimation() { 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data().mini) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 558116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!mini_title_change_animation_) { 559d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::MultiAnimation::Parts parts; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push_back( 561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS, 562d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::Tween::EASE_OUT)); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push_back( 564d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS, 565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::Tween::ZERO)); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts.push_back( 567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS, 568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::Tween::EASE_IN)); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts[0].start_time_ms = kMiniTitleChangeAnimationStart1MS; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts[0].end_time_ms = kMiniTitleChangeAnimationEnd1MS; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts[2].start_time_ms = kMiniTitleChangeAnimationStart3MS; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS; 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta timeout = 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kMiniTitleChangeAnimationIntervalMS); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_.reset(new gfx::MultiAnimation(parts, timeout)); 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (animation_container_.get()) 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_->SetContainer(animation_container_.get()); 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_->set_delegate(this); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_->Start(); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::StopMiniTabTitleAnimation() { 584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch StopAndDeleteAnimation(mini_title_change_animation_.PassAs<gfx::Animation>()); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size Tab::GetBasicMinimumUnselectedSize() { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitTabResources(); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size minimum_size; 5925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu minimum_size.set_width(kLeftPadding + kRightPadding); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we use image images, the real minimum height of the image is 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // defined most accurately by the height of the end cap images. 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimum_size.set_height(tab_active_.image_l->height()); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return minimum_size; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size Tab::GetMinimumUnselectedSize() { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetBasicMinimumUnselectedSize(); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size Tab::GetMinimumSelectedSize() { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size minimum_size = GetBasicMinimumUnselectedSize(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) minimum_size.set_width( 6075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kLeftPadding + gfx::kFaviconSize + kRightPadding); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return minimum_size; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Size Tab::GetStandardSize() { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size standard_size = GetBasicMinimumUnselectedSize(); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) standard_size.set_width( 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) standard_size.width() + kFaviconTitleSpacing + kStandardTitleWidth); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return standard_size; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Tab::GetTouchWidth() { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kTouchWidth; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Tab::GetMiniWidth() { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser_defaults::kMiniTabWidth; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int Tab::GetImmersiveHeight() { 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kImmersiveTabHeight; 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tab, AnimationDelegate overrides: 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 637d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Tab::AnimationProgressed(const gfx::Animation* animation) { 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Ignore if the pulse animation is being performed on active tab because 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it repaints the same image. See |Tab::PaintTabBackground()|. 640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (animation == pulse_animation_.get() && IsActive()) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Tab::AnimationCanceled(const gfx::Animation* animation) { 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 649d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Tab::AnimationEnded(const gfx::Animation* animation) { 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaint(); 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tab, views::ButtonListener overrides: 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::ButtonPressed(views::Button* sender, const ui::Event& event) { 6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (media_indicator_button_ && media_indicator_button_->visible()) { 6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (media_indicator_button_->enabled()) 6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction(UserMetricsAction("CloseTab_MuteToggleAvailable")); 6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else if (data_.media_state == TAB_MEDIA_STATE_AUDIO_PLAYING) 6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction(UserMetricsAction("CloseTab_AudioIndicator")); 6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction(UserMetricsAction("CloseTab_RecordingIndicator")); 6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction(UserMetricsAction("CloseTab_NoMediaIndicator")); 6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CloseTabSource source = 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (event.type() == ui::ET_MOUSE_RELEASED && 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (event.flags() & ui::EF_FROM_TOUCH) == 0) ? CLOSE_TAB_FROM_MOUSE : 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CLOSE_TAB_FROM_TOUCH; 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(close_button_, sender); 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->CloseTab(this, source); 674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (event.type() == ui::ET_GESTURE_TAP) 675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch TouchUMA::RecordGestureAction(TouchUMA::GESTURE_TABCLOSE_TAP); 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tab, views::ContextMenuController overrides: 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::ShowContextMenuForView(views::View* source, 6827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const gfx::Point& point, 6837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ui::MenuSourceType source_type) { 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!closing()) 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ShowContextMenuForTab(this, point, source_type); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 689116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Tab, views::MaskedTargeterDelegate overrides: 690116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 691116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool Tab::GetHitTestMask(gfx::Path* mask) const { 692116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(mask); 693116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 694116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // When the window is maximized we don't want to shave off the edges or top 695116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // shadow of the tab, such that the user can click anywhere along the top 696116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // edge of the screen to select a tab. Ditto for immersive fullscreen. 697116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const views::Widget* widget = GetWidget(); 698116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool include_top_shadow = 699116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch widget && (widget->IsMaximized() || widget->IsFullscreen()); 700116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TabResources::GetHitTestMask(width(), height(), include_top_shadow, mask); 701116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // It is possible for a portion of the tab to be occluded if tabs are 703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // stacked, so modify the hit test mask to only include the visible 704116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // region of the tab. 705116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect clip; 706116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch controller_->ShouldPaintTab(this, &clip); 707116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (clip.size().GetArea()) { 708116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SkRect intersection(mask->getBounds()); 709116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch intersection.intersect(RectToSkRect(clip)); 710116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->reset(); 711116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->addRect(intersection); 712116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 713116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 714116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 715116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 716116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 717116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//////////////////////////////////////////////////////////////////////////////// 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tab, views::View overrides: 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::OnPaint(gfx::Canvas* canvas) { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't paint if we're narrower than we can render correctly. (This should 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only happen during animations). 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (width() < GetMinimumUnselectedSize().width() && !data().mini) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect clip; 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!controller_->ShouldPaintTab(this, &clip)) 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!clip.IsEmpty()) { 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas->Save(); 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas->ClipRect(clip); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (controller_->IsImmersiveStyle()) 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PaintImmersiveTab(canvas); 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PaintTab(canvas); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!clip.IsEmpty()) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->Restore(); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::Layout() { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect lb = GetContentsBounds(); 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lb.IsEmpty()) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7481675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) showing_icon_ = ShouldShowIcon(); 7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (showing_icon_) { 7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) favicon_bounds_.set_size(gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize)); 7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) favicon_bounds_.set_y(lb.y() + (lb.height() - gfx::kFaviconSize + 1) / 2); 75468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) MaybeAdjustLeftForMiniTab(&favicon_bounds_); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) showing_close_button_ = ShouldShowCloseBox(); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (showing_close_button_) { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the ratio of the close button size to tab width exceeds the maximum. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The close button should be as large as possible so that there is a larger 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hit-target for touch events. So the close button bounds extends to the 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // edges of the tab. However, the larger hit-target should be active only 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for mouse events, and the close-image should show up in the right place. 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So a border is added to the button with necessary padding. The close 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // button (BaseTab::TabCloseButton) makes sure the padding is a hit-target 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only for touch events. 7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) close_button_->SetBorder(views::Border::NullBorder()); 7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const gfx::Size close_button_size(close_button_->GetPreferredSize()); 7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int top = lb.y() + (lb.height() - close_button_size.height() + 1) / 2; 7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int bottom = height() - (close_button_size.height() + top); 7715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int left = kViewSpacing; 7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int right = width() - (lb.width() + close_button_size.width() + left); 7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) close_button_->SetBorder( 7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) views::Border::CreateEmptyBorder(top, left, bottom, right)); 775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) close_button_->SetPosition(gfx::Point(lb.width(), 0)); 776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) close_button_->SizeToPreferredSize(); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) close_button_->SetVisible(showing_close_button_); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) showing_media_indicator_ = ShouldShowMediaIndicator(); 7814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (showing_media_indicator_) { 7821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::ImageButton* const button = GetMediaIndicatorButton(); 7831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const gfx::Size image_size(button->GetPreferredSize()); 78468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int right = showing_close_button_ ? 78568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) close_button_->x() + close_button_->GetInsets().left() : lb.right(); 7861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect bounds( 7871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::max(lb.x(), right - image_size.width()), 7881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci lb.y() + (lb.height() - image_size.height() + 1) / 2, 7891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci image_size.width(), 7901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci image_size.height()); 7911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MaybeAdjustLeftForMiniTab(&bounds); 7921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci button->SetBoundsRect(bounds); 7931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci button->SetVisible(true); 7941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (media_indicator_button_) { 7951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_->SetVisible(false); 79668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 79768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Size the title to fill the remaining width and use all available height. 7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool show_title = !data().mini || width() >= kMiniTabRendererAsNormalTabWidth; 8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (show_title) { 8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int title_left = favicon_bounds_.right() + kFaviconTitleSpacing; 8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int title_width = lb.width() - title_left; 8034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (showing_media_indicator_) { 8041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci title_width = media_indicator_button_->x() - kViewSpacing - title_left; 80568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (close_button_->visible()) { 8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Allow the title to overlay the close button's empty border padding. 80768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) title_width = close_button_->x() + close_button_->GetInsets().left() - 8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kViewSpacing - title_left; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Rect rect(title_left, lb.y(), std::max(title_width, 0), lb.height()); 8116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const int title_height = title_->GetPreferredSize().height(); 8126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (title_height > rect.height()) { 8136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) rect.set_y(lb.y() - (title_height - rect.height()) / 2); 8146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) rect.set_height(title_height); 8156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) title_->SetBoundsRect(rect); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) title_->SetVisible(show_title); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::OnThemeChanged() { 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadTabImages(); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* Tab::GetClassName() const { 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kViewClassName; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Note: Anything that affects the tooltip text should be accounted for when 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // calling TooltipTextChanged() from Tab::DataChanged(). 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.media_state); 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !tooltip->empty(); 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) const { 837f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) origin->set_x(title_->x() + 10); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Tab::OnMousePressed(const ui::MouseEvent& event) { 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->OnMouseEventInTab(this, event); 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Allow a right click from touch to drag, which corresponds to a long click. 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event.IsOnlyLeftMouseButton() || 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (event.IsOnlyRightMouseButton() && event.flags() & ui::EF_FROM_TOUCH)) { 8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel original_selection; 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_selection.Copy(controller_->GetSelectionModel()); 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Changing the selection may cause our bounds to change. If that happens 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the location of the event may no longer be valid. Create a copy of the 8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // event in the parents coordinate, which won't change, and recreate an 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // event after changing so the coordinates are correct. 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::MouseEvent event_in_parent(event, static_cast<View*>(this), parent()); 8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (controller_->SupportsMultipleSelection()) { 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event.IsShiftDown() && event.IsControlDown()) { 8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->AddSelectionFromAnchorTo(this); 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (event.IsShiftDown()) { 8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ExtendSelectionTo(this); 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (event.IsControlDown()) { 8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ToggleSelected(this); 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSelected()) { 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't allow dragging non-selected tabs. 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!IsSelected()) { 8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->SelectTab(this); 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (!IsSelected()) { 8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->SelectTab(this); 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::MouseEvent cloned_event(event_in_parent, parent(), 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<View*>(this)); 8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->MaybeStartDrag(this, cloned_event, original_selection); 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Tab::OnMouseDragged(const ui::MouseEvent& event) { 8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ContinueDrag(this, event); 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::OnMouseReleased(const ui::MouseEvent& event) { 8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->OnMouseEventInTab(this, event); 8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Notify the drag helper that we're done with any potential drag operations. 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Clean up the drag helper, which is re-created on the next mouse press. 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In some cases, ending the drag will schedule the tab for destruction; if 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so, bail immediately, since our members are already dead and we shouldn't 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // do anything else except drop the tab where it is. 8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (controller_->EndDrag(END_DRAG_COMPLETE)) 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Close tab on middle click, but only if the button is released over the tab 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (normal windows behavior is to discard presses of a UI element where the 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // releases happen off the element). 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event.IsMiddleMouseButton()) { 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HitTestPoint(event.location())) { 9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->CloseTab(this, CLOSE_TAB_FROM_MOUSE); 9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (closing_) { 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We're animating closed and a middle mouse button was pushed on us but 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we don't contain the mouse anymore. We assume the user is clicking 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // quicker than the animation and we should close the tab that falls under 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the mouse. 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Tab* closest_tab = controller_->GetTabAt(this, event.location()); 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (closest_tab) 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->CloseTab(closest_tab, CLOSE_TAB_FROM_MOUSE); 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (event.IsOnlyLeftMouseButton() && !event.IsShiftDown() && 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !event.IsControlDown()) { 9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the tab was already selected mouse pressed doesn't change the 9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // selection. Reset it now to handle the case where multiple tabs were 9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // selected. 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->SelectTab(this); 9161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (media_indicator_button_ && media_indicator_button_->visible() && 9181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_->bounds().Contains(event.location())) { 9191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::RecordAction(UserMetricsAction("TabMediaIndicator_Clicked")); 9201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::OnMouseCaptureLost() { 9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->EndDrag(END_DRAG_CAPTURE_LOST); 9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::OnMouseEntered(const ui::MouseEvent& event) { 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.Show(views::GlowHoverController::SUBTLE); 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::OnMouseMoved(const ui::MouseEvent& event) { 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.SetLocation(event.location()); 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->OnMouseEventInTab(this, event); 9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::OnMouseExited(const ui::MouseEvent& event) { 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.Hide(); 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::OnGestureEvent(ui::GestureEvent* event) { 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (event->type()) { 9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case ui::ET_GESTURE_TAP_DOWN: { 9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TAP_DOWN is only dispatched for the first touch point. 9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(1, event->details().touch_points()); 9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See comment in OnMousePressed() as to why we copy the event. 9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GestureEvent event_in_parent(*event, static_cast<View*>(this), 9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent()); 9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel original_selection; 9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) original_selection.Copy(controller_->GetSelectionModel()); 9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tab_activated_with_last_tap_down_ = !IsActive(); 9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsSelected()) 9545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->SelectTab(this); 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Point loc(event->location()); 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::ConvertPointToScreen(this, &loc); 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GestureEvent cloned_event(event_in_parent, parent(), 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<View*>(this)); 9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->MaybeStartDrag(this, cloned_event, original_selection); 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::ET_GESTURE_END: 9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->EndDrag(END_DRAG_COMPLETE); 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::ET_GESTURE_SCROLL_UPDATE: 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) controller_->ContinueDrag(this, *event); 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->SetHandled(); 9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 977a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Tab::GetAccessibleState(ui::AXViewState* state) { 978a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_TAB; 9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) state->name = data_.title; 980116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state->AddStateFlag(ui::AX_STATE_MULTISELECTABLE); 981116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state->AddStateFlag(ui::AX_STATE_SELECTABLE); 9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) controller_->UpdateTabAccessibilityState(this, state); 983116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (IsSelected()) 984116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state->AddStateFlag(ui::AX_STATE_SELECTED); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tab, private 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void Tab::MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const { 99168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) 99268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 99368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth(); 99468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int ideal_delta = width() - GetMiniWidth(); 99568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int ideal_x = (GetMiniWidth() - bounds->width()) / 2; 99668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bounds->set_x(bounds->x() + static_cast<int>( 99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (1 - static_cast<float>(ideal_delta) / static_cast<float>(mini_delta)) * 99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (ideal_x - bounds->x()))); 99968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 100068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::DataChanged(const TabRendererData& old) { 10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (data().media_state != old.media_state || data().title != old.title) 10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TooltipTextChanged(); 10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data().blocked == old.blocked) 10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data().blocked) 10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartPulse(); 10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopPulse(); 10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::PaintTab(gfx::Canvas* canvas) { 10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See if the model changes whether the icons should be painted. 10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool show_icon = ShouldShowIcon(); 10174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const bool show_media_indicator = ShouldShowMediaIndicator(); 10182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool show_close_button = ShouldShowCloseBox(); 101968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (show_icon != showing_icon_ || 10204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) show_media_indicator != showing_media_indicator_ || 102168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) show_close_button != showing_close_button_) { 10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Layout(); 102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PaintTabBackground(canvas); 10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1027f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const SkColor title_color = GetThemeProvider()->GetColor(IsSelected() ? 1028f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ThemeProperties::COLOR_TAB_TEXT : 1029f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); 1030f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetVisible(!data().mini || 1031f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) width() > kMiniTabRendererAsNormalTabWidth); 1032f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) title_->SetEnabledColor(title_color); 10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (show_icon) 10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PaintIcon(canvas); 10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the close button color has changed, generate a new one. 10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!close_button_color_ || title_color != close_button_color_) { 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_color_ = title_color; 10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) close_button_->SetBackground(close_button_color_, 1042c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_1), 1043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) rb.GetImageSkiaNamed(IDR_CLOSE_1_MASK)); 10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::PaintImmersiveTab(gfx::Canvas* canvas) { 104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Use transparency for the draw-attention animation. 1049ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int alpha = 255; 1050116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pulse_animation_ && pulse_animation_->is_animating() && !data().mini) { 1051116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch alpha = pulse_animation_->CurrentValueBetween( 1052ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity)); 1053ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Draw a gray rectangle to represent the tab. This works for mini-tabs as 10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // well as regular ones. The active tab has a brigher bar. 10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor color = 10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsActive() ? kImmersiveActiveTabColor : kImmersiveInactiveTabColor; 10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect bar_rect = GetImmersiveBarRect(); 106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) canvas->FillRect(bar_rect, SkColorSetA(color, alpha)); 10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Paint network activity indicator. 10632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(jamescook): Replace this placeholder animation with a real one. 10642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For now, let's go with a Cylon eye effect, but in blue. 10652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { 106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SkColor kEyeColor = SkColorSetARGB(alpha, 71, 138, 217); 10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int eye_width = bar_rect.width() / 3; 10682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int eye_offset = bar_rect.width() * immersive_loading_step_ / 10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kImmersiveLoadingStepCount; 10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (eye_offset + eye_width < bar_rect.width()) { 10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Draw a single indicator strip because it fits inside |bar_rect|. 10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect eye_rect( 10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bar_rect.x() + eye_offset, 0, eye_width, kImmersiveBarHeight); 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->FillRect(eye_rect, kEyeColor); 10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Draw two indicators to simulate the eye "wrapping around" to the left 10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // side. The first part fills the remainder of the bar. 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int right_eye_width = bar_rect.width() - eye_offset; 10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect right_eye_rect( 10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bar_rect.x() + eye_offset, 0, right_eye_width, kImmersiveBarHeight); 10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->FillRect(right_eye_rect, kEyeColor); 10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The second part parts the remaining |eye_width| on the left. 10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int left_eye_width = eye_offset + eye_width - bar_rect.width(); 10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect left_eye_rect( 10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bar_rect.x(), 0, left_eye_width, kImmersiveBarHeight); 10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->FillRect(left_eye_rect, kEyeColor); 10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::PaintTabBackground(gfx::Canvas* canvas) { 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsActive()) { 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintActiveTabBackground(canvas); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1095116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (mini_title_change_animation_ && 1096116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mini_title_change_animation_->is_animating()) { 1097116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PaintInactiveTabBackgroundWithTitleChange(canvas); 10982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintInactiveTabBackground(canvas); 11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double throb_value = GetThrobValue(); 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (throb_value > 0) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), 11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetLocalBounds()); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintActiveTabBackground(canvas); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->Restore(); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1112116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Render the inactive tab background. We'll use this for clipping. 111468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Canvas background_canvas(size(), canvas->image_scale(), false); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintInactiveTabBackground(&background_canvas); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia background_image(background_canvas.ExtractImageRep()); 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw a radial gradient to hover_canvas. 112068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Canvas hover_canvas(size(), canvas->image_scale(), false); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int radius = kMiniTitleChangeGradientRadius; 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x0 = width() + radius - kMiniTitleChangeInitialXOffset; 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x1 = radius; 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x2 = -radius; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x; 1126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (mini_title_change_animation_->current_part_index() == 0) { 1127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch x = mini_title_change_animation_->CurrentValueBetween(x0, x1); 1128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (mini_title_change_animation_->current_part_index() == 1) { 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = x1; 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch x = mini_title_change_animation_->CurrentValueBetween(x1, x2); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPoint center_point; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) center_point.iset(x, 0); 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkColor colors[2] = { kMiniTitleChangeGradientColor1, 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMiniTitleChangeGradientColor2 }; 11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) skia::RefPtr<SkShader> shader = skia::AdoptRef( 11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkGradientShader::CreateRadial( 11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) center_point, SkIntToScalar(radius), colors, NULL, 2, 11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkShader::kClamp_TileMode)); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPaint paint; 11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) paint.setShader(shader.get()); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hover_canvas.DrawRect(gfx::Rect(x - radius, -radius, radius * 2, radius * 2), 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the radial gradient clipped to the background into hover_image. 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia hover_image = gfx::ImageSkiaOperations::CreateMaskedImage( 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia(hover_canvas.ExtractImageRep()), background_image); 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the tab background to the canvas. 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(background_image, 0, 0); 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And then the gradient on top of that. 1154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (mini_title_change_animation_->current_part_index() == 2) { 1155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint8 alpha = mini_title_change_animation_->CurrentValueBetween(255, 0); 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(hover_image, 0, 0, alpha); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(hover_image, 0, 0); 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id; 11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int frame_id; 11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::Widget* widget = GetWidget(); 11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetTabIdAndFrameId(widget, &tab_id, &frame_id); 11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Explicitly map the id so we cache correctly. 11692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const chrome::HostDesktopType host_desktop_type = GetHostDesktopType(this); 11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_id = chrome::MapThemeImage(host_desktop_type, tab_id); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // HasCustomImage() is only true if the theme provides the image. However, 11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // even if the theme does not provide a tab background, the theme machinery 11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // will make one if given a frame image. 11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ThemeProvider* theme_provider = GetThemeProvider(); 11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool theme_provided_image = theme_provider->HasCustomImage(tab_id) || 11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (frame_id != 0 && theme_provider->HasCustomImage(frame_id)); 11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool can_cache = !theme_provided_image && 11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !hover_controller_.ShouldDraw(); 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_cache) { 118368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ui::ScaleFactor scale_factor = 118468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ui::GetSupportedScaleFactor(canvas->image_scale()); 118568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkia cached_image(GetCachedImage(tab_id, size(), scale_factor)); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cached_image.width() == 0) { 118768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Canvas tmp_canvas(size(), canvas->image_scale(), false); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintInactiveTabBackgroundUsingResourceId(&tmp_canvas, tab_id); 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_image = gfx::ImageSkia(tmp_canvas.ExtractImageRep()); 119068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) SetCachedImage(tab_id, scale_factor, cached_image); 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(cached_image, 0, 0); 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PaintInactiveTabBackgroundUsingResourceId(canvas, tab_id); 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::PaintInactiveTabBackgroundUsingResourceId(gfx::Canvas* canvas, 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id) { 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WARNING: the inactive tab background may be cached. If you change what it 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is drawn from you may need to update whether it can be cached. 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tab image needs to be lined up with the background image 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so that it feels partially transparent. These offsets represent the tab 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // position within the frame background image. 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset = GetMirroredX() + background_offset_.x(); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia* tab_bg = GetThemeProvider()->GetImageSkiaNamed(tab_id); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabImage* tab_image = &tab_active_; 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabImage* tab_inactive_image = &tab_inactive_; 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabImage* alpha = &tab_alpha_; 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the theme is providing a custom background image, then its top edge 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be at the top of the tab. Otherwise, we assume that the background 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // image is a composited foreground + frame image. 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 : background_offset_.y(); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need a gfx::Canvas object to be able to extract the image from. 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We draw everything to this canvas and then output it to the canvas 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameter in addition to using it to mask the hover glow if needed. 122368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Canvas background_canvas(size(), canvas->image_scale(), false); 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw left edge. Don't draw over the toolbar, as we're not the foreground 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tab. 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_bg, offset, bg_offset_y, tab_image->l_width, height()); 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia theme_l = 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_canvas.DrawImageInt(theme_l, 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw right edge. Again, don't draw over the toolbar. 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage(*tab_bg, 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset + width() - tab_image->r_width, bg_offset_y, 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_image->r_width, height()); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia theme_r = 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_canvas.DrawImageInt(theme_r, 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap, 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - theme_r.width(), 0, theme_r.width(), 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) theme_r.height() - kToolbarOverlap, false); 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw center. Instead of masking out the top portion we simply skip over 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it by incrementing by GetDropShadowHeight(), since it's a simple 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rectangle. And again, don't draw over the toolbar. 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_canvas.TileImageInt(*tab_bg, 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset + tab_image->l_width, 12525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bg_offset_y + kDropShadowHeight, 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_image->l_width, 12545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kDropShadowHeight, 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - tab_image->l_width - tab_image->r_width, 12565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu height() - kDropShadowHeight - kToolbarOverlap); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt( 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia(background_canvas.ExtractImageRep()), 0, 0); 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetThemeProvider()->HasCustomImage(tab_id) && 12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.ShouldDraw()) { 12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hover_controller_.Draw(canvas, gfx::ImageSkia( 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background_canvas.ExtractImageRep())); 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now draw the highlights/shadows around the tab edge. 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*tab_inactive_image->image_l, 0, 0); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->TileImageInt(*tab_inactive_image->image_c, 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_image->l_width, 0, 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - tab_inactive_image->l_width - 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_image->r_width, 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) height()); 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*tab_inactive_image->image_r, 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - tab_inactive_image->r_width, 0); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) { 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia* tab_background = 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetThemeProvider()->GetImageSkiaNamed(IDR_THEME_TOOLBAR); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset = GetMirroredX() + background_offset_.x(); 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabImage* tab_image = &tab_active_; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabImage* alpha = &tab_alpha_; 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw left edge. 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia tab_l = gfx::ImageSkiaOperations::CreateTiledImage( 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_background, offset, 0, tab_image->l_width, height()); 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia theme_l = 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkiaOperations::CreateMaskedImage(tab_l, *alpha->image_l); 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(theme_l, 0, 0); 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw right edge. 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia tab_r = gfx::ImageSkiaOperations::CreateTiledImage( 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *tab_background, 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia theme_r = 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkiaOperations::CreateMaskedImage(tab_r, *alpha->image_r); 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(theme_r, width() - tab_image->r_width, 0); 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw center. Instead of masking out the top portion we simply skip over it 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by incrementing by GetDropShadowHeight(), since it's a simple rectangle. 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->TileImageInt(*tab_background, 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset + tab_image->l_width, 13055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kDropShadowHeight, 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_image->l_width, 13075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kDropShadowHeight, 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - tab_image->l_width - tab_image->r_width, 13095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu height() - kDropShadowHeight); 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now draw the highlights/shadows around the tab edge. 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*tab_image->image_l, 0, 0); 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - tab_image->l_width - tab_image->r_width, height()); 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::PaintIcon(gfx::Canvas* canvas) { 1319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Rect bounds = favicon_bounds_; 13202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bounds.IsEmpty()) 13212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds.set_x(GetMirroredXForRect(bounds)); 13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { 13264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Paint network activity (aka throbber) animation frame. 13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ThemeProvider* tp = GetThemeProvider(); 13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia frames(*tp->GetImageSkiaNamed( 13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ? 13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IDR_THROBBER_WAITING : IDR_THROBBER)); 13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_size = frames.height(); 13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int image_offset = loading_animation_frame_ * icon_size; 13342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DrawIconCenter(canvas, frames, image_offset, 13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_size, icon_size, 13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds, false, SkPaint()); 13374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (should_display_crashed_favicon_) { 13384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Paint crash favicon. 13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); 13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds.set_y(bounds.y() + favicon_hiding_offset_); 13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DrawIconCenter(canvas, crashed_favicon, 0, 1343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crashed_favicon.width(), 1344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crashed_favicon.height(), 1345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bounds, true, SkPaint()); 13464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (!data().favicon.isNull()) { 13474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Paint the normal favicon. 13484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DrawIconCenter(canvas, data().favicon, 0, 13494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data().favicon.width(), 13504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data().favicon.height(), 13514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bounds, true, SkPaint()); 13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, 13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabRendererData::NetworkState state) { 13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static bool initialized = false; 13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static int loading_animation_frame_count = 0; 13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static int waiting_animation_frame_count = 0; 13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static int waiting_to_loading_frame_count_ratio = 0; 13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!initialized) { 13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialized = true; 13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 13642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia loading_animation(*rb.GetImageSkiaNamed(IDR_THROBBER)); 13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_count = 13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation.width() / loading_animation.height(); 13672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia waiting_animation(*rb.GetImageSkiaNamed( 13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IDR_THROBBER_WAITING)); 13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waiting_animation_frame_count = 13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waiting_animation.width() / waiting_animation.height(); 13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waiting_to_loading_frame_count_ratio = 13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waiting_animation_frame_count / loading_animation_frame_count; 13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::debug::Alias(&loading_animation_frame_count); 13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::debug::Alias(&waiting_animation_frame_count); 13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_NE(0, waiting_to_loading_frame_count_ratio) << 13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Number of frames in IDR_THROBBER must be equal to or greater " << 13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "than the number of frames in IDR_THROBBER_WAITING. Please " << 13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "investigate how this happened and update http://crbug.com/132590, " << 13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "this is causing crashes in the wild."; 13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The waiting animation is the reverse of the loading animation, but at a 13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // different rate - the following reverses and scales the animation_frame_ 13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so that the frame is at an equivalent position when going from one 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // animation to the other. 13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state != old_state) { 13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_ = loading_animation_frame_count - 13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (loading_animation_frame_ / waiting_to_loading_frame_count_ratio); 13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (state == TabRendererData::NETWORK_STATE_WAITING) { 13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_ = (loading_animation_frame_ + 1) % 13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) waiting_animation_frame_count; 13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Waiting steps backwards. 13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) immersive_loading_step_ = 13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (immersive_loading_step_ - 1 + kImmersiveLoadingStepCount) % 13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kImmersiveLoadingStepCount; 13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (state == TabRendererData::NETWORK_STATE_LOADING) { 14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_ = (loading_animation_frame_ + 1) % 14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_count; 14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) immersive_loading_step_ = (immersive_loading_step_ + 1) % 14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kImmersiveLoadingStepCount; 14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) loading_animation_frame_ = 0; 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) immersive_loading_step_ = 0; 14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (controller_->IsImmersiveStyle()) 14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaintInRect(GetImmersiveBarRect()); 14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleIconPaint(); 14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Tab::IconCapacity() const { 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (height() < GetMinimumUnselectedSize().height()) 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 14174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int available_width = 14185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::max(0, width() - kLeftPadding - kRightPadding); 14195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int width_per_icon = gfx::kFaviconSize; 142068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const int kPaddingBetweenIcons = 2; 14214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (available_width >= width_per_icon && 14224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) available_width < (width_per_icon + kPaddingBetweenIcons)) { 14234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return 1; 14244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 14254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return available_width / (width_per_icon + kPaddingBetweenIcons); 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Tab::ShouldShowIcon() const { 14294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return chrome::ShouldTabShowFavicon( 14304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IconCapacity(), data().mini, IsActive(), data().show_icon, 14311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_ ? media_indicator_button_->showing_media_state() : 14321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data_.media_state); 143368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 143468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Tab::ShouldShowMediaIndicator() const { 14364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return chrome::ShouldTabShowMediaIndicator( 14374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IconCapacity(), data().mini, IsActive(), data().show_icon, 14381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_ ? media_indicator_button_->showing_media_state() : 14391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data_.media_state); 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Tab::ShouldShowCloseBox() const { 14434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return chrome::ShouldTabShowCloseButton( 14444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IconCapacity(), data().mini, IsActive()); 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double Tab::GetThrobValue() { 1448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const bool is_selected = IsSelected(); 1449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const double min = is_selected ? kSelectedTabOpacity : 0; 1450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const double scale = is_selected ? kSelectedTabThrobScale : 1; 1451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Showing both the pulse and title change animation at the same time is too 1453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // much. 1454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pulse_animation_ && pulse_animation_->is_animating() && 1455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (!mini_title_change_animation_ || 1456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !mini_title_change_animation_->is_animating())) { 1457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return pulse_animation_->GetCurrentValue() * kHoverOpacity * scale + min; 14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (hover_controller_.ShouldDraw()) { 14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kHoverOpacity * hover_controller_.GetAnimationValue() * scale + 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min; 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_selected ? kSelectedTabOpacity : 0; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::SetFaviconHidingOffset(int offset) { 14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_hiding_offset_ = offset; 14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleIconPaint(); 14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::DisplayCrashedFavicon() { 14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) should_display_crashed_favicon_ = true; 14752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::ResetCrashedFavicon() { 14782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) should_display_crashed_favicon_ = false; 14792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Tab::StopCrashAnimation() { 148268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) crash_icon_animation_.reset(); 14832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::StartCrashAnimation() { 148668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) crash_icon_animation_.reset(new FaviconCrashAnimation(this)); 148768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) crash_icon_animation_->Start(); 14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Tab::IsPerformingCrashAnimation() const { 149168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return crash_icon_animation_.get() && data_.IsCrashed(); 14922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 14932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::ScheduleIconPaint() { 1495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::Rect bounds = favicon_bounds_; 14962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bounds.IsEmpty()) 14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 14982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Extends the area to the bottom when sad_favicon is animating. 15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsPerformingCrashAnimation()) 15012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds.set_height(height() - bounds.y()); 15022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds.set_x(GetMirroredXForRect(bounds)); 15032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SchedulePaintInRect(bounds); 15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 15052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect Tab::GetImmersiveBarRect() const { 15072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The main bar is as wide as the normal tab's horizontal top line. 15082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This top line of the tab extends a few pixels left and right of the 15092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // center image due to pixels in the rounded corner images. 15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int kBarPadding = 1; 15112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int main_bar_left = tab_active_.l_width - kBarPadding; 15122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int main_bar_right = width() - tab_active_.r_width + kBarPadding; 15132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Rect( 15142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) main_bar_left, 0, main_bar_right - main_bar_left, kImmersiveBarHeight); 15152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Tab::GetTabIdAndFrameId(views::Widget* widget, 15182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* tab_id, 15192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* frame_id) const { 15205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (widget && 15215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) widget->GetTopLevelWidget()->ShouldWindowContentsBeTransparent()) { 15222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *tab_id = IDR_THEME_TAB_BACKGROUND_V; 15232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *frame_id = 0; 15242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (data().incognito) { 15252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *tab_id = IDR_THEME_TAB_BACKGROUND_INCOGNITO; 15262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *frame_id = IDR_THEME_FRAME_INCOGNITO; 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 15282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *tab_id = IDR_THEME_TAB_BACKGROUND; 15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *frame_id = IDR_THEME_FRAME; 15302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 15312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 15322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMediaIndicatorButton* Tab::GetMediaIndicatorButton() { 15341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!media_indicator_button_) { 15351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media_indicator_button_ = new MediaIndicatorButton(); 15361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddChildView(media_indicator_button_); // Takes ownership. 15371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return media_indicator_button_; 15391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 15401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 15422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tab, private static: 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::InitTabResources() { 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized) 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_cache_ = new ImageCache(); 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load the tab images once now, and maybe again later if the theme changes. 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadTabImages(); 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::LoadTabImages() { 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're not letting people override tab images just yet. 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_alpha_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_LEFT); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_alpha_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ALPHA_RIGHT); 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_active_.image_l = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_LEFT); 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_active_.image_c = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_CENTER); 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_active_.image_r = rb.GetImageSkiaNamed(IDR_TAB_ACTIVE_RIGHT); 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_active_.l_width = tab_active_.image_l->width(); 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_active_.r_width = tab_active_.image_r->width(); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_.image_l = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_LEFT); 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_.image_c = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_CENTER); 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_.image_r = rb.GetImageSkiaNamed(IDR_TAB_INACTIVE_RIGHT); 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_.l_width = tab_inactive_.image_l->width(); 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_inactive_.r_width = tab_inactive_.image_r->width(); 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkia Tab::GetCachedImage(int resource_id, 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& size, 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScaleFactor scale_factor) { 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ImageCache::const_iterator i = image_cache_->begin(); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != image_cache_->end(); ++i) { 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->resource_id == resource_id && i->scale_factor == scale_factor && 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->image.size() == size) { 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->image; 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::ImageSkia(); 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Tab::SetCachedImage(int resource_id, 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScaleFactor scale_factor, 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia& image) { 15962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageCacheEntry entry; 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.resource_id = resource_id; 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.scale_factor = scale_factor; 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.image = image; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_cache_->push_front(entry); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_cache_->size() > kMaxImageCacheSize) 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_cache_->pop_back(); 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605