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/custom_button.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/cairo_cached_surface.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_button.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/skbitmap_operations.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCustomDrawButtonBase::CustomDrawButtonBase(GtkThemeService* theme_provider, 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int normal_id, 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int pressed_id, 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int hover_id, 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int disabled_id) 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : background_image_(NULL), 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_override_(-1), 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch normal_id_(normal_id), 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pressed_id_(pressed_id), 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick hover_id_(hover_id), 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick disabled_id_(disabled_id), 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(theme_provider), 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flipped_(false) { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < (GTK_STATE_INSENSITIVE + 1); ++i) 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[i].reset(new CairoCachedSurface); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_image_.reset(new CairoCachedSurface); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (theme_provider) { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Load images by pretending that we got a BROWSER_THEME_CHANGED 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // notification. 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch theme_provider->InitThemesFor(this); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::BROWSER_THEME_CHANGED, 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Load the button images from the resource bundle. 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_NORMAL]->UsePixbuf( 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick normal_id_ ? rb.GetRTLEnabledPixbufNamed(normal_id_) : NULL); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_ACTIVE]->UsePixbuf( 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pressed_id_ ? rb.GetRTLEnabledPixbufNamed(pressed_id_) : NULL); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf( 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick hover_id_ ? rb.GetRTLEnabledPixbufNamed(hover_id_) : NULL); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf( 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick disabled_id_ ? rb.GetRTLEnabledPixbufNamed(disabled_id_) : NULL); 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawButtonBase::~CustomDrawButtonBase() { 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CustomDrawButtonBase::Width() const { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return surfaces_[0]->Width(); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CustomDrawButtonBase::Height() const { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return surfaces_[0]->Height(); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventExpose* e, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gdouble hover_state) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int paint_state = paint_override_ >= 0 ? 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_override_ : GTK_WIDGET_STATE(widget); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the paint state is PRELIGHT then set it to NORMAL (we will paint the 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // hover state according to |hover_state_|). 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (paint_state == GTK_STATE_PRELIGHT) 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_state = GTK_STATE_NORMAL; 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool animating_hover = hover_state > 0.0 && 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paint_state == GTK_STATE_NORMAL; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CairoCachedSurface* pixbuf = PixbufForState(paint_state); 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CairoCachedSurface* hover_pixbuf = PixbufForState(GTK_STATE_PRELIGHT); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pixbuf || !pixbuf->valid()) 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animating_hover && (!hover_pixbuf || !hover_pixbuf->valid())) 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_t* cairo_context = gdk_cairo_create(GDK_DRAWABLE(widget->window)); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_translate(cairo_context, widget->allocation.x, widget->allocation.y); 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (flipped_) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Horizontally flip the image for non-LTR/RTL reasons. 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_translate(cairo_context, widget->allocation.width, 0.0f); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_scale(cairo_context, -1.0f, 1.0f); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The widget might be larger than the pixbuf. Paint the pixbuf flush with the 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // start of the widget (left for LTR, right for RTL) and its bottom. 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Rect bounds = gfx::Rect(0, 0, pixbuf->Width(), 0); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int x = gtk_util::MirroredLeftPointForRect(widget, bounds); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y = widget->allocation.height - pixbuf->Height(); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (background_image_->valid()) { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_image_->SetSource(cairo_context, x, y); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_paint(cairo_context); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pixbuf->SetSource(cairo_context, x, y); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_paint(cairo_context); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animating_hover) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_pixbuf->SetSource(cairo_context, x, y); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_paint_with_alpha(cairo_context, hover_state); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cairo_destroy(cairo_context); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget)); 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (child) 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_container_propagate_expose(GTK_CONTAINER(widget), child, e); 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TRUE; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButtonBase::SetBackground(SkColor color, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* image, SkBitmap* mask) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!image || !mask) { 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (background_image_->valid()) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_image_->UsePixbuf(NULL); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap img = 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmapOperations::CreateButtonBackground(color, *image, *mask); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&img); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch background_image_->UsePixbuf(pixbuf); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(pixbuf); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButtonBase::Observe(NotificationType type, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, const NotificationDetails& details) { 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(theme_service_); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(NotificationType::BROWSER_THEME_CHANGED == type); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_NORMAL]->UsePixbuf(normal_id_ ? 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->GetRTLEnabledPixbufNamed(normal_id_) : NULL); 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick surfaces_[GTK_STATE_ACTIVE]->UsePixbuf(pressed_id_ ? 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->GetRTLEnabledPixbufNamed(pressed_id_) : NULL); 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick surfaces_[GTK_STATE_PRELIGHT]->UsePixbuf(hover_id_ ? 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->GetRTLEnabledPixbufNamed(hover_id_) : NULL); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch surfaces_[GTK_STATE_SELECTED]->UsePixbuf(NULL); 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick surfaces_[GTK_STATE_INSENSITIVE]->UsePixbuf(disabled_id_ ? 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->GetRTLEnabledPixbufNamed(disabled_id_) : NULL); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCairoCachedSurface* CustomDrawButtonBase::PixbufForState(int state) { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CairoCachedSurface* pixbuf = surfaces_[state].get(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fall back to the default image if we don't have one for this state. 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pixbuf || !pixbuf->valid()) 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pixbuf = surfaces_[GTK_STATE_NORMAL].get(); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return pixbuf; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CustomDrawHoverController --------------------------------------------------- 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawHoverController::CustomDrawHoverController(GtkWidget* widget) 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : slide_animation_(this), 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_(NULL) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(widget); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawHoverController::CustomDrawHoverController() 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : slide_animation_(this), 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_(NULL) { 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawHoverController::~CustomDrawHoverController() { 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawHoverController::Init(GtkWidget* widget) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(widget_ == NULL); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_ = widget; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget_, "enter-notify-event", 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick G_CALLBACK(OnEnterThunk), this); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget_, "leave-notify-event", 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick G_CALLBACK(OnLeaveThunk), this); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawHoverController::AnimationProgressed( 1953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const ui::Animation* animation) { 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(widget_); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean CustomDrawHoverController::OnEnter( 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget, 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GdkEventCrossing* event) { 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick slide_animation_.Show(); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean CustomDrawHoverController::OnLeave( 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget, 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GdkEventCrossing* event) { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the user is holding a mouse button, we don't want to animate. 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick slide_animation_.Reset(); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick slide_animation_.Hide(); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CustomDrawButton ------------------------------------------------------------ 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickCustomDrawButton::CustomDrawButton(int normal_id, 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int pressed_id, 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int hover_id, 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int disabled_id) 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : button_base_(NULL, normal_id, pressed_id, hover_id, disabled_id), 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(NULL) { 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initialize the theme stuff with no theme_provider. 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBrowserTheme(); 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCustomDrawButton::CustomDrawButton(GtkThemeService* theme_provider, 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int normal_id, 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int pressed_id, 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int hover_id, 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int disabled_id, 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* stock_id, 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GtkIconSize stock_size) 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : button_base_(theme_provider, normal_id, pressed_id, hover_id, 2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick disabled_id), 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(theme_provider) { 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick native_widget_.Own(gtk_image_new_from_stock(stock_id, stock_size)); 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Init(); 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->InitThemesFor(this); 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add(this, 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationType::BROWSER_THEME_CHANGED, 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService::AllSources()); 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCustomDrawButton::CustomDrawButton(GtkThemeService* theme_provider, 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int normal_id, 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int pressed_id, 2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int hover_id, 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int disabled_id, 2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GtkWidget* native_widget) 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : button_base_(theme_provider, normal_id, pressed_id, hover_id, 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick disabled_id), 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick native_widget_(native_widget), 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_(theme_provider) { 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen theme_service_->InitThemesFor(this); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.Add(this, 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::BROWSER_THEME_CHANGED, 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::AllSources()); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawButton::~CustomDrawButton() { 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_.Destroy(); 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick native_widget_.Destroy(); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::Init() { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch widget_.Own(gtk_chrome_button_new()); 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GTK_WIDGET_UNSET_FLAGS(widget(), GTK_CAN_FOCUS); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_signal_connect(widget(), "expose-event", 2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick G_CALLBACK(OnCustomExposeThunk), this); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_controller_.Init(widget()); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::Observe(NotificationType type, 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, const NotificationDetails& details) { 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(NotificationType::BROWSER_THEME_CHANGED == type); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBrowserTheme(); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::SetPaintOverride(GtkStateType state) { 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_base_.set_paint_override(state); 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(widget()), state); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(widget()); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::UnsetPaintOverride() { 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_base_.set_paint_override(-1); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_unset_paint_state(GTK_CHROME_BUTTON(widget())); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_queue_draw(widget()); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::SetBackground(SkColor color, 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkBitmap* image, SkBitmap* mask) { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_base_.SetBackground(color, image, mask); 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickgboolean CustomDrawButton::OnCustomExpose(GtkWidget* sender, 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GdkEventExpose* e) { 3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (UseGtkTheme()) { 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Continue processing this expose event. 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double hover_state = hover_controller_.GetCurrentValue(); 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return button_base_.OnExpose(sender, e, hover_state); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCustomDrawButton* CustomDrawButton::CloseButton( 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkThemeService* theme_provider) { 3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CustomDrawButton* button = new CustomDrawButton(theme_provider, IDR_CLOSE_BAR, 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick IDR_CLOSE_BAR_P, IDR_CLOSE_BAR_H, 0, GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return button; 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CustomDrawButton::SetBrowserTheme() { 3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (UseGtkTheme()) { 3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (native_widget_.get()) 3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_button_set_image(GTK_BUTTON(widget()), native_widget_.get()); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(widget(), -1, -1); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_app_paintable(widget(), FALSE); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (native_widget_.get()) 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick gtk_button_set_image(GTK_BUTTON(widget()), NULL); 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_size_request(widget(), button_base_.Width(), 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_base_.Height()); 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_widget_set_app_paintable(widget(), TRUE); 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_use_gtk_rendering( 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GTK_CHROME_BUTTON(widget()), UseGtkTheme()); 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool CustomDrawButton::UseGtkTheme() { 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return theme_service_ && theme_service_->UseGtkTheme(); 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 346