172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tabs/tab_renderer_gtk.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <utility> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/defaults.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tab_helper.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/custom_button.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h" 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h" 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_resources.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/slide_animation.h" 263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/throb_animation.h" 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/canvas_skia_paint.h" 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/favicon_size.h" 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/platform_font_gtk.h" 3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kFontPixelSize = 12; 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kLeftPadding = 16; 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTopPadding = 6; 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kRightPadding = 15; 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kBottomPadding = 5; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDropShadowHeight = 2; 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kFaviconTitleSpacing = 4; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kTitleCloseButtonSpacing = 5; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kStandardTitleWidth = 175; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDropShadowOffset = 2; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kInactiveTabBackgroundOffsetY = 15; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When a non-mini-tab becomes a mini-tab the width of the tab animates. If 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is rendered as a normal tab. This is done to avoid having the title 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// immediately disappear when transitioning a tab from normal to mini-tab. 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMiniTabRendererAsNormalTabWidth = 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_defaults::kMiniTabWidth + 30; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The tab images are designed to overlap the toolbar by 1 pixel. For now we 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// don't actually overlap the toolbar, so this is used to know how many pixels 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// at the bottom of the tab images are to be ignored. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kToolbarOverlap = 1; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How long the hover state takes. 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kHoverDurationMs = 90; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// How opaque to make the hover state (out of 1). 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst double kHoverOpacity = 0.33; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Max opacity for the mini-tab title change animation. 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst double kMiniTitleChangeThrobOpacity = 0.75; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Duration for when the title of an inactive mini-tab changes. 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kMiniTitleChangeThrobDuration = 1000; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkScalar kTabCapWidth = 15; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkScalar kTabTopCurveWidth = 4; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst SkScalar kTabBottomCurveWidth = 3; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The vertical and horizontal offset used to position the close button 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// in the tab. TODO(jhawkins): Ask pkasting what the Fuzz is about. 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCloseButtonVertFuzz = 0; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kCloseButtonHorzFuzz = 5; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSkBitmap* crashed_favicon = NULL; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Gets the bounds of |widget| relative to |parent|. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect GetWidgetBoundsRelativeToParent(GtkWidget* parent, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point parent_pos = gtk_util::GetWidgetScreenPosition(parent); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point widget_pos = gtk_util::GetWidgetScreenPosition(widget); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(widget_pos.x() - parent_pos.x(), 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_pos.y() - parent_pos.y(), 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget->allocation.width, widget->allocation.height); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTabRendererGtk::LoadingAnimation::Data::Data( 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ThemeProvider* theme_provider) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The loading animation image is a strip of states. Each state must be 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // square, so the height must divide the width evenly. 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frames = theme_provider->GetBitmapNamed(IDR_THROBBER); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(loading_animation_frames); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(loading_animation_frames->width() % 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frames->height(), 0); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frame_count = 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frames->width() / 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frames->height(); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frames = 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_provider->GetBitmapNamed(IDR_THROBBER_WAITING); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(waiting_animation_frames); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(waiting_animation_frames->width() % 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frames->height(), 0); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frame_count = 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frames->width() / 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frames->height(); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_to_loading_frame_count_ratio = 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frame_count / 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frame_count; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(beng): eventually remove this when we have a proper themeing system. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // themes not supporting IDR_THROBBER_WAITING are causing this 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // value to be 0 which causes DIV0 crashes. The value of 5 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // matches the current bitmaps in our source. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (waiting_to_loading_frame_count_ratio == 0) 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_to_loading_frame_count_ratio = 5; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::LoadingAnimation::Data::Data( 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int loading, int waiting, int waiting_to_loading) 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : waiting_animation_frames(NULL), 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frames(NULL), 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_frame_count(loading), 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_animation_frame_count(waiting), 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch waiting_to_loading_frame_count_ratio(waiting_to_loading) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::initialized_ = false; 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::TabImage TabRendererGtk::tab_active_ = {0}; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::TabImage TabRendererGtk::tab_inactive_ = {0}; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::TabImage TabRendererGtk::tab_alpha_ = {0}; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Font* TabRendererGtk::title_font_ = NULL; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::title_font_height_ = 0; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::close_button_width_ = 0; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::close_button_height_ = 0; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSkColor TabRendererGtk::selected_title_color_ = SK_ColorBLACK; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSkColor TabRendererGtk::unselected_title_color_ = SkColorSetRGB(64, 64, 64); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabRendererGtk::LoadingAnimation, public: 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::LoadingAnimation::LoadingAnimation( 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ui::ThemeProvider* theme_provider) 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : data_(new Data(theme_provider)), 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(theme_provider), 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_state_(ANIMATION_NONE), 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_frame_(0) { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::BROWSER_THEME_CHANGED, 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::LoadingAnimation::LoadingAnimation( 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const LoadingAnimation::Data& data) 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : data_(new Data(data)), 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(NULL), 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_state_(ANIMATION_NONE), 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_frame_(0) { 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTabRendererGtk::LoadingAnimation::~LoadingAnimation() {} 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::LoadingAnimation::ValidateLoadingAnimation( 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimationState animation_state) { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_changed = false; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animation_state_ != animation_state) { 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The waiting animation is the reverse of the loading animation, but at a 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // different rate - the following reverses and scales the animation_frame_ 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that the frame is at an equivalent position when going from one 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // animation to the other. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animation_state_ == ANIMATION_WAITING && 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_state == ANIMATION_LOADING) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_frame_ = data_->loading_animation_frame_count - 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (animation_frame_ / data_->waiting_to_loading_frame_count_ratio); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_state_ = animation_state; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_changed = true; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animation_state_ != ANIMATION_NONE) { 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_frame_ = (animation_frame_ + 1) % 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ((animation_state_ == ANIMATION_WAITING) ? 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_->waiting_animation_frame_count : 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_->loading_animation_frame_count); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch has_changed = true; 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation_frame_ = 0; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return has_changed; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::LoadingAnimation::Observe( 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType type, 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.reset(new Data(theme_service_)); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// FaviconCrashAnimation 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A custom animation subclass to manage the favicon crash animation. 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass TabRendererGtk::FaviconCrashAnimation : public ui::LinearAnimation, 2133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public ui::AnimationDelegate { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit FaviconCrashAnimation(TabRendererGtk* target) 2163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen : ALLOW_THIS_IN_INITIALIZER_LIST(ui::LinearAnimation(1000, 25, this)), 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_(target) { 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual ~FaviconCrashAnimation() {} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ui::Animation overrides: 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void AnimateToState(double state) { 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const double kHidingOffset = 27; 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state < .5) { 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen target_->SetFaviconHidingOffset( 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(floor(kHidingOffset * 2.0 * state))); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen target_->DisplayCrashedFavicon(); 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen target_->SetFaviconHidingOffset( 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>( 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ui::AnimationDelegate overrides: 2373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationCanceled(const ui::Animation* animation) { 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen target_->SetFaviconHidingOffset(0); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabRendererGtk* target_; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabRendererGtk, public: 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTabRendererGtk::TabRendererGtk(ui::ThemeProvider* theme_provider) 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : showing_icon_(false), 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch showing_close_button_(false), 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_hiding_offset_(0), 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch should_display_crashed_favicon_(false), 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_(theme_provider), 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_offset_x_(0), 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_offset_y_(kInactiveTabBackgroundOffsetY), 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_color_(0) { 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitResources(); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_.Own(gtk_fixed_new()); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_app_paintable(tab_.get(), TRUE); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(tab_.get(), "expose-event", 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnExposeEventThunk), this); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(tab_.get(), "size-allocate", 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnSizeAllocateThunk), this); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_.reset(MakeCloseButton()); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(tab_.get()); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen hover_animation_.reset(new ui::SlideAnimation(this)); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_->SetSlideDuration(kHoverDurationMs); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabRendererGtk::~TabRendererGtk() { 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_.Destroy(); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BitmapCache::iterator it = cached_bitmaps_.begin(); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != cached_bitmaps_.end(); ++it) { 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete it->second.bitmap; 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::UpdateData(TabContents* contents, 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool app, 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool loading_only) { 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(contents); 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_ = GtkThemeService::GetFrom(contents->profile()); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!loading_only) { 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.title = contents->GetTitle(); 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.incognito = contents->profile()->IsOffTheRecord(); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.crashed = contents->is_crashed(); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* app_icon = 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper::GetCurrentWrapperForContents(contents)-> 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extension_tab_helper()->GetExtensionAppIcon(); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (app_icon) 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.favicon = *app_icon; 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.favicon = contents->GetFavicon(); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.app = app; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is kind of a hacky way to determine whether our icon is the default 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // favicon. But the plumbing that would be necessary to do it right would 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // be a good bit of work and would sully code for other platforms which 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // don't care to custom-theme the favicon. Hopefully the default favicon 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will eventually be chromium-themable and this code will go away. 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.is_default_favicon = 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (data_.favicon.pixelRef() == 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle::GetSharedInstance().GetBitmapNamed( 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDR_DEFAULT_FAVICON)->pixelRef()); 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Loading state also involves whether we show the favicon, since that's where 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we display the throbber. 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.loading = contents->is_loading(); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.show_icon = contents->ShouldDisplayFavicon(); 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::UpdateFromModel() { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Force a layout, since the tab may have grown a favicon. 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Layout(); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data_.crashed) { 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartCrashAnimation(); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsPerformingCrashAnimation()) 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopCrashAnimation(); 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResetCrashedFavicon(); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SetBlocked(bool blocked) { 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data_.blocked == blocked) 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.blocked = blocked; 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(zelidrag) bug 32399: Make tabs pulse on Linux as well. 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::is_blocked() const { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return data_.blocked; 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::IsSelected() const { 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::IsVisible() const { 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GTK_WIDGET_FLAGS(tab_.get()) & GTK_VISIBLE; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SetVisible(bool visible) const { 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (visible) { 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(tab_.get()); 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data_.mini) 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(close_button_->widget()); 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_hide_all(tab_.get()); 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::ValidateLoadingAnimation(AnimationState animation_state) { 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return loading_animation_.ValidateLoadingAnimation(animation_state); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabRendererGtk::PaintFaviconArea(GdkEventExpose* event) { 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ShouldShowIcon()); 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The paint area is the favicon bounds, but we're painting into the gdk 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // window belonging to the tabstrip. So the coordinates are relative to the 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // top left of the tab strip. 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->area.x = x() + favicon_bounds_.x(); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->area.y = y() + favicon_bounds_.y(); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->area.width = favicon_bounds_.width(); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event->area.height = favicon_bounds_.height(); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkiaPaint canvas(event, false); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The actual paint methods expect 0, 0 to be the tab top left (see 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // PaintTab). 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.TranslateInt(x(), y()); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the background behind the favicon. 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int theme_id; 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset_y = 0; 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsSelected()) { 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_id = IDR_THEME_TOOLBAR; 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!data_.incognito) { 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_id = IDR_THEME_TAB_BACKGROUND; 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_id = IDR_THEME_TAB_BACKGROUND_INCOGNITO; 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!theme_service_->HasCustomImage(theme_id)) 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_y = background_offset_y_; 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* tab_bg = theme_service_->GetBitmapNamed(theme_id); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.TileImageInt(*tab_bg, 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x() + favicon_bounds_.x(), offset_y + favicon_bounds_.y(), 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.x(), favicon_bounds_.y(), 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.width(), favicon_bounds_.height()); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsSelected()) { 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double throb_value = GetThrobValue(); 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (throb_value > 0) { 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkRect bounds; 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set(favicon_bounds_.x(), favicon_bounds_.y(), 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.right(), favicon_bounds_.bottom()); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.saveLayerAlpha(&bounds, static_cast<int>(throb_value * 0xff), 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkCanvas::kARGB_ClipLayer_SaveFlag); 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.drawARGB(0, 255, 255, 255, SkXfermode::kClear_Mode); 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* active_bg = theme_service_->GetBitmapNamed(IDR_THEME_TOOLBAR); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.TileImageInt(*active_bg, 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch x() + favicon_bounds_.x(), favicon_bounds_.y(), 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.x(), favicon_bounds_.y(), 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.width(), favicon_bounds_.height()); 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.restore(); 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now paint the icon. 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintIcon(&canvas); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool TabRendererGtk::ShouldShowIcon() const { 429513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (mini() && height() >= GetMinimumUnselectedSize().height()) { 430513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 431513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (!data_.show_icon) { 432513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 433513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (IsSelected()) { 434513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The selected tab clips favicon before close button. 435513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return IconCapacity() >= 2; 436513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 437513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Non-selected tabs clip close button before favicon. 438513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return IconCapacity() >= 1; 439513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 440513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size TabRendererGtk::GetMinimumUnselectedSize() { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitResources(); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size minimum_size; 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_size.set_width(kLeftPadding + kRightPadding); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since we use bitmap images, the real minimum height of the image is 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // defined most accurately by the height of the end cap images. 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch minimum_size.set_height(tab_active_.image_l->height() - kToolbarOverlap); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return minimum_size; 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size TabRendererGtk::GetMinimumSelectedSize() { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size minimum_size = GetMinimumUnselectedSize(); 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen minimum_size.set_width(kLeftPadding + kFaviconSize + kRightPadding); 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return minimum_size; 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size TabRendererGtk::GetStandardSize() { 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size standard_size = GetMinimumUnselectedSize(); 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen standard_size.Enlarge(kFaviconTitleSpacing + kStandardTitleWidth, 0); 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return standard_size; 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::GetMiniWidth() { 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return browser_defaults::kMiniTabWidth; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::GetContentHeight() { 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The height of the content of the Tab is the largest of the favicon, 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the title text and the close button graphic. 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int content_height = std::max(kFaviconSize, title_font_height_); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return std::max(content_height, close_button_height_); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::LoadTabImages() { 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_alpha_.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT); 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_alpha_.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT); 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER); 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.l_width = tab_active_.image_l->width(); 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.r_width = tab_active_.image_r->width(); 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_inactive_.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_inactive_.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_inactive_.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_inactive_.l_width = tab_inactive_.image_l->width(); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_inactive_.r_width = tab_inactive_.image_r->width(); 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_width_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->width(); 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_height_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->height(); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SetSelectedTitleColor(SkColor color) { 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch selected_title_color_ = color; 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SetUnselectedTitleColor(SkColor color) { 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unselected_title_color_ = color; 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect TabRendererGtk::GetNonMirroredBounds(GtkWidget* parent) const { 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tabstrip widget is a windowless widget so the tab widget's allocation 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is relative to the browser titlebar. We need the bounds relative to the 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tabstrip. 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = GetWidgetBoundsRelativeToParent(parent, widget()); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds.set_x(gtk_util::MirroredLeftPointForRect(parent, bounds)); 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bounds; 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect TabRendererGtk::GetRequisition() const { 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(requisition_.x(), requisition_.y(), 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch requisition_.width(), requisition_.height()); 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::StartMiniTabTitleAnimation() { 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!mini_title_animation_.get()) { 5293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen mini_title_animation_.reset(new ui::ThrobAnimation(this)); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mini_title_animation_->SetThrobDuration(kMiniTitleChangeThrobDuration); 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!mini_title_animation_->is_animating()) { 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mini_title_animation_->StartThrobbing(2); 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (mini_title_animation_->cycles_remaining() <= 2) { 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The title changed while we're already animating. Add at most one more 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cycle. This is done in an attempt to smooth out pages that continuously 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // change the title. 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mini_title_animation_->set_cycles_remaining( 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mini_title_animation_->cycles_remaining() + 2); 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::StopMiniTabTitleAnimation() { 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mini_title_animation_.get()) 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mini_title_animation_->Stop(); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SetBounds(const gfx::Rect& bounds) { 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch requisition_ = bounds; 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(tab_.get(), bounds.width(), bounds.height()); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::Observe(NotificationType type, 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear our cache when we receive a theme change notification because it 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // contains cached bitmaps based off the previous theme. 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (BitmapCache::iterator it = cached_bitmaps_.begin(); 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != cached_bitmaps_.end(); ++it) { 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete it->second.bitmap; 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cached_bitmaps_.clear(); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabRendererGtk, protected: 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenstring16 TabRendererGtk::GetTitle() const { 5723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return data_.title; 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/////////////////////////////////////////////////////////////////////////////// 5763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// TabRendererGtk, ui::AnimationDelegate implementation: 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid TabRendererGtk::AnimationProgressed(const ui::Animation* animation) { 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(tab_.get()); 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid TabRendererGtk::AnimationCanceled(const ui::Animation* animation) { 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimationEnded(animation); 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid TabRendererGtk::AnimationEnded(const ui::Animation* animation) { 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(tab_.get()); 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////////////////////////////////////////////////// 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabRendererGtk, private: 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::StartCrashAnimation() { 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!crash_animation_.get()) 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crash_animation_.reset(new FaviconCrashAnimation(this)); 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch crash_animation_->Stop(); 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch crash_animation_->Start(); 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::StopCrashAnimation() { 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!crash_animation_.get()) 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch crash_animation_->Stop(); 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::IsPerformingCrashAnimation() const { 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return crash_animation_.get() && crash_animation_->is_animating(); 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabRendererGtk::SetFaviconHidingOffset(int offset) { 611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_hiding_offset_ = offset; 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SchedulePaint(); 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabRendererGtk::DisplayCrashedFavicon() { 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch should_display_crashed_favicon_ = true; 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TabRendererGtk::ResetCrashedFavicon() { 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch should_display_crashed_favicon_ = false; 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::Paint(gfx::Canvas* canvas) { 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't paint if we're narrower than we can render correctly. (This should 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // only happen during animations). 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (width() < GetMinimumUnselectedSize().width() && !mini()) 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if the model changes whether the icons should be painted. 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool show_icon = ShouldShowIcon(); 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool show_close_button = ShouldShowCloseBox(); 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (show_icon != showing_icon_ || 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch show_close_button != showing_close_button_) 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Layout(); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 636731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick PaintTabBackground(canvas); 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!mini() || width() > kMiniTabRendererAsNormalTabWidth) 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintTitle(canvas); 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (show_icon) 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintIcon(canvas); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSkBitmap TabRendererGtk::PaintBitmap() { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkia canvas(width(), height(), false); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Paint(&canvas); 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return canvas.ExtractBitmap(); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochcairo_surface_t* TabRendererGtk::PaintToSurface() { 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkia canvas(width(), height(), false); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Paint(&canvas); 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return cairo_surface_reference(cairo_get_target(canvas.beginPlatformPaint())); 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::SchedulePaint() { 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(tab_.get()); 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect TabRendererGtk::GetLocalBounds() { 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return gfx::Rect(0, 0, bounds_.width(), bounds_.height()); 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::Layout() { 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect local_bounds = GetLocalBounds(); 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_bounds.IsEmpty()) 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_bounds.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding); 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Figure out who is tallest. 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int content_height = GetContentHeight(); 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Size the Favicon. 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch showing_icon_ = ShouldShowIcon(); 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (showing_icon_) { 677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int favicon_top = kTopPadding + (content_height - kFaviconSize) / 2; 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.SetRect(local_bounds.x(), favicon_top, 679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kFaviconSize, kFaviconSize); 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((mini() || data_.animating_mini_change) && 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_.width() < kMiniTabRendererAsNormalTabWidth) { 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth(); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int ideal_delta = bounds_.width() - GetMiniWidth(); 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ideal_delta < mini_delta) { 685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int ideal_x = (GetMiniWidth() - kFaviconSize) / 2; 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x = favicon_bounds_.x() + static_cast<int>( 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (1 - static_cast<float>(ideal_delta) / 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<float>(mini_delta)) * 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (ideal_x - favicon_bounds_.x())); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.set_x(x); 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.SetRect(local_bounds.x(), local_bounds.y(), 0, 0); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Size the Close button. 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch showing_close_button_ = ShouldShowCloseBox(); 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (showing_close_button_) { 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int close_button_top = 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kTopPadding + kCloseButtonVertFuzz + 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (content_height - close_button_height_) / 2; 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_bounds_.SetRect(local_bounds.width() + kCloseButtonHorzFuzz, 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_top, close_button_width_, 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_height_); 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the close button color has changed, generate a new one. 708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (theme_service_) { 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColor tab_text_color = 710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->GetColor(ThemeService::COLOR_TAB_TEXT); 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!close_button_color_ || tab_text_color != close_button_color_) { 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_color_ = tab_text_color; 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->SetBackground(close_button_color_, 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_TAB_CLOSE), 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK)); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_bounds_.SetRect(0, 0, 0, 0); 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!mini() || width() >= kMiniTabRendererAsNormalTabWidth) { 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Size the Title text to fill the remaining space. 725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int title_left = favicon_bounds_.right() + kFaviconTitleSpacing; 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int title_top = kTopPadding; 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the user has big fonts, the title will appear rendered too far down 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on the y-axis if we use the regular top padding, so we need to adjust it 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that the text appears centered. 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Size minimum_size = GetMinimumUnselectedSize(); 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int text_height = title_top + title_font_height_ + kBottomPadding; 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (text_height > minimum_size.height()) 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_top -= (text_height - minimum_size.height()) / 2; 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int title_width; 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (close_button_bounds_.width() && close_button_bounds_.height()) { 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_width = std::max(close_button_bounds_.x() - 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kTitleCloseButtonSpacing - title_left, 0); 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_width = std::max(local_bounds.width() - title_left, 0); 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.SetRect(title_left, title_top, title_width, content_height); 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.set_x( 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::MirroredLeftPointForRect(tab_.get(), favicon_bounds_)); 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_bounds_.set_x( 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::MirroredLeftPointForRect(tab_.get(), close_button_bounds_)); 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.set_x( 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_util::MirroredLeftPointForRect(tab_.get(), title_bounds_)); 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MoveCloseButtonWidget(); 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::MoveCloseButtonWidget() { 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!close_button_bounds_.IsEmpty()) { 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_fixed_move(GTK_FIXED(tab_.get()), close_button_->widget(), 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_bounds_.x(), close_button_bounds_.y()); 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_show(close_button_->widget()); 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_hide(close_button_->widget()); 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSkBitmap* TabRendererGtk::GetMaskedBitmap(const SkBitmap* mask, 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* background, int bg_offset_x, int bg_offset_y) { 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We store a bitmap for each mask + background pair (4 total bitmaps). We 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // replace the cached image if the tab has moved relative to the background. 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BitmapCache::iterator it = cached_bitmaps_.find(std::make_pair(mask, 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background)); 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != cached_bitmaps_.end()) { 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it->second.bg_offset_x == bg_offset_x && 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it->second.bg_offset_y == bg_offset_y) { 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return it->second.bitmap; 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The background offset changed so we should re-render with the new 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // offsets. 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete it->second.bitmap; 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap image = SkBitmapOperations::CreateTiledBitmap( 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *background, bg_offset_x, bg_offset_y, mask->width(), 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() + kToolbarOverlap); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CachedBitmap bitmap = { 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bg_offset_x, 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bg_offset_y, 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new SkBitmap(SkBitmapOperations::CreateMaskedBitmap(image, *mask)) 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cached_bitmaps_[std::make_pair(mask, background)] = bitmap; 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return bitmap.bitmap; 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintTab(GdkEventExpose* event) { 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::CanvasSkiaPaint canvas(event, false); 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (canvas.is_empty()) 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab is rendered into a windowless widget whose offset is at the 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // coordinate event->area. Translate by these offsets so we can render at 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (0,0) to match Windows' rendering metrics. 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas.TranslateInt(event->area.x, event->area.y); 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save the original x offset so we can position background images properly. 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_offset_x_ = event->area.x; 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Paint(&canvas); 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintTitle(gfx::Canvas* canvas) { 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Paint the Title. 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 title = data_.title; 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (title.empty()) { 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title = data_.loading ? 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : 815dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen TabContentsWrapper::GetDefaultTitle(); 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser::FormatTitleForDisplay(&title); 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkColor title_color = IsSelected() ? selected_title_color_ 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : unselected_title_color_; 82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen canvas->DrawStringInt(title, *title_font_, title_color, 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.x(), title_bounds_.y(), 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch title_bounds_.width(), title_bounds_.height()); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintIcon(gfx::Canvas* canvas) { 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (loading_animation_.animation_state() != ANIMATION_NONE) { 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintLoadingAnimation(canvas); 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->Save(); 832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->ClipRectInt(0, 0, width(), height() - kFaviconTitleSpacing); 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (should_display_crashed_favicon_) { 834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen canvas->DrawBitmapInt(*crashed_favicon, 0, 0, 835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crashed_favicon->width(), 836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crashed_favicon->height(), 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.x(), 838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_bounds_.y() + favicon_hiding_offset_, 839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kFaviconSize, kFaviconSize, 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true); 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!data_.favicon.isNull()) { 843ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data_.is_default_favicon && theme_service_->UseGtkTheme()) { 844ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GdkPixbuf* favicon = GtkThemeService::GetDefaultFavicon(true); 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->DrawGdkPixbuf( 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon, favicon_bounds_.x(), 847ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_bounds_.y() + favicon_hiding_offset_); 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the favicon is an app icon, it is allowed to be drawn slightly 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // larger than the standard favicon. 851ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int faviconHeightOffset = data_.app ? -2 : 0; 852ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int faviconWidthDelta = data_.app ? 853ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.favicon.width() - kFaviconSize : 0; 854ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int faviconHeightDelta = data_.app ? 855ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_.favicon.height() - kFaviconSize : 0; 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to using that class to render the favicon). 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(data_.favicon, 0, 0, 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.favicon.width(), 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_.favicon.height(), 862ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_bounds_.x() - faviconWidthDelta/2, 863ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen favicon_bounds_.y() + faviconHeightOffset 864ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen - faviconHeightDelta/2 865ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen + favicon_hiding_offset_, 866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kFaviconSize + faviconWidthDelta, 867ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen kFaviconSize + faviconHeightDelta, 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true); 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->Restore(); 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintTabBackground(gfx::Canvas* canvas) { 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsSelected()) { 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintActiveTabBackground(canvas); 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintInactiveTabBackground(canvas); 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch double throb_value = GetThrobValue(); 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (throb_value > 0) { 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect(width(), height())); 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkXfermode::kClear_Mode); 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintActiveTabBackground(canvas); 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->Restore(); 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintInactiveTabBackground(gfx::Canvas* canvas) { 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tab image needs to be lined up with the background image 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that it feels partially transparent. 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset_x = background_offset_x_; 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 900ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_id = data_.incognito ? 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 903ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* tab_bg = theme_service_->GetBitmapNamed(tab_id); 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the theme is providing a custom background image, then its top edge 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should be at the top of the tab. Otherwise, we assume that the background 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // image is a composited foreground + frame image. 908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int offset_y = theme_service_->HasCustomImage(tab_id) ? 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0 : background_offset_y_; 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw left edge. 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x, 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_y); 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*theme_l, 0, 0); 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw right edge. 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg, 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_x + width() - tab_active_.r_width, offset_y); 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*theme_r, width() - theme_r->width(), 0); 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw center. 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*tab_bg, 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_x + tab_active_.l_width, kDropShadowOffset + offset_y, 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.l_width, 2, 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - tab_active_.l_width - tab_active_.r_width, height() - 2); 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*tab_inactive_.image_l, 0, 0); 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*tab_inactive_.image_c, tab_inactive_.l_width, 0, 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - tab_inactive_.l_width - tab_inactive_.r_width, height()); 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*tab_inactive_.image_r, 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - tab_inactive_.r_width, 0); 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintActiveTabBackground(gfx::Canvas* canvas) { 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int offset_x = background_offset_x_; 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 938ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SkBitmap* tab_bg = theme_service_->GetBitmapNamed(IDR_THEME_TOOLBAR); 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw left edge. 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* theme_l = GetMaskedBitmap(tab_alpha_.image_l, tab_bg, offset_x, 0); 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*theme_l, 0, 0); 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw right edge. 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* theme_r = GetMaskedBitmap(tab_alpha_.image_r, tab_bg, 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_x + width() - tab_active_.r_width, 0); 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*theme_r, width() - tab_active_.r_width, 0); 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Draw center. 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*tab_bg, 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch offset_x + tab_active_.l_width, kDropShadowHeight, 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tab_active_.l_width, kDropShadowHeight, 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - tab_active_.l_width - tab_active_.r_width, 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch height() - kDropShadowHeight); 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*tab_active_.image_l, 0, 0); 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->TileImageInt(*tab_active_.image_c, tab_active_.l_width, 0, 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch width() - tab_active_.l_width - tab_active_.r_width, height()); 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*tab_active_.image_r, width() - tab_active_.r_width, 0); 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::PaintLoadingAnimation(gfx::Canvas* canvas) { 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SkBitmap* frames = 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (loading_animation_.animation_state() == ANIMATION_WAITING) ? 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_.waiting_animation_frames() : 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loading_animation_.loading_animation_frames(); 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int image_size = frames->height(); 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const int image_offset = loading_animation_.animation_frame() * image_size; 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(image_size == favicon_bounds_.height()); 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(image_size == favicon_bounds_.width()); 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 972dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. 973dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen canvas->Save(); 974dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen canvas->ClipRectInt( 975dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen favicon_bounds_.x(), favicon_bounds_.y(), image_size, image_size); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch canvas->DrawBitmapInt(*frames, image_offset, 0, image_size, image_size, 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon_bounds_.x(), favicon_bounds_.y(), image_size, image_size, 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch false); 979dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen canvas->Restore(); 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint TabRendererGtk::IconCapacity() const { 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (height() < GetMinimumUnselectedSize().height()) 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 985ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return (width() - kLeftPadding - kRightPadding) / kFaviconSize; 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TabRendererGtk::ShouldShowCloseBox() const { 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The selected tab never clips close button. 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !mini() && (IsSelected() || IconCapacity() >= 3); 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawButton* TabRendererGtk::MakeCloseButton() { 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE, 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE); 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_tooltip_text(button->widget(), 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch l10n_util::GetStringUTF8(IDS_TOOLTIP_CLOSE_TAB).c_str()); 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(button->widget(), "clicked", 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnCloseButtonClickedThunk), this); 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(button->widget(), "button-release-event", 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnCloseButtonMouseReleaseThunk), this); 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(button->widget(), "enter-notify-event", 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnEnterNotifyEventThunk), this); 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(button->widget(), "leave-notify-event", 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnLeaveNotifyEventThunk), this); 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_fixed_put(GTK_FIXED(tab_.get()), button->widget(), 0, 0); 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return button; 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdouble TabRendererGtk::GetThrobValue() { 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mini_title_animation_.get() && mini_title_animation_->is_animating()) { 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return mini_title_animation_->GetCurrentValue() * 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kMiniTitleChangeThrobOpacity; 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return hover_animation_.get() ? 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kHoverOpacity * hover_animation_->GetCurrentValue() : 0; 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::CloseButtonClicked() { 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Nothing to do. 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::OnCloseButtonClicked(GtkWidget* widget) { 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CloseButtonClicked(); 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean TabRendererGtk::OnCloseButtonMouseRelease(GtkWidget* widget, 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventButton* event) { 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->button == 2) { 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CloseButtonClicked(); 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean TabRendererGtk::OnExposeEvent(GtkWidget* widget, 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventExpose* event) { 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PaintTab(event); 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_container_propagate_expose(GTK_CONTAINER(tab_.get()), 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_button_->widget(), event); 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::OnSizeAllocate(GtkWidget* widget, 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkAllocation* allocation) { 1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = gfx::Rect(allocation->x, allocation->y, 1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch allocation->width, allocation->height); 1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Nothing to do if the bounds are the same. If we don't catch this, we'll 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // get an infinite loop of size-allocate signals. 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bounds_ == bounds) 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bounds_ = bounds; 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Layout(); 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean TabRendererGtk::OnEnterNotifyEvent(GtkWidget* widget, 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventCrossing* event) { 10653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen hover_animation_->SetTweenType(ui::Tween::EASE_OUT); 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_->Show(); 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean TabRendererGtk::OnLeaveNotifyEvent(GtkWidget* widget, 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventCrossing* event) { 10723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen hover_animation_->SetTweenType(ui::Tween::EASE_IN); 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_->Hide(); 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TabRendererGtk::InitResources() { 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (initialized_) 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LoadTabImages(); 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const gfx::Font& base_font = rb.GetFont(ResourceBundle::BaseFont); 108672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen title_font_ = new gfx::Font(base_font.GetFontName(), kFontPixelSize); 10873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick title_font_height_ = title_font_->GetHeight(); 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crashed_favicon = rb.GetBitmapNamed(IDR_SAD_FAVICON); 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initialized_ = true; 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1093