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/hover_controller_gtk.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_chrome_button.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const gchar* kHoverControllerGtkKey = "__HOVER_CONTROLLER_GTK__"; 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHoverControllerGtk::HoverControllerGtk(GtkWidget* button) 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : throb_animation_(this), 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_(this), 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_(button) { 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_ref(button_); 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button_, "enter-notify-event", 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnEnterThunk), this); 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button_, "leave-notify-event", 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnLeaveThunk), this); 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch signals_.Connect(button_, "destroy", 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch G_CALLBACK(OnDestroyThunk), this); 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick signals_.Connect(button_, "hierarchy-changed", 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick G_CALLBACK(OnHierarchyChangedThunk), this); 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef NDEBUG 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (g_object_get_data(G_OBJECT(button_), kHoverControllerGtkKey)) 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // !NDEBUG 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_set_data(G_OBJECT(button), kHoverControllerGtkKey, this); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHoverControllerGtk::~HoverControllerGtk() { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HoverControllerGtk::StartThrobbing(int cycles) { 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch throb_animation_.StartThrobbing(cycles); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGtkWidget* HoverControllerGtk::CreateChromeButton() { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget = gtk_chrome_button_new(); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new HoverControllerGtk(widget); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return widget; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHoverControllerGtk* HoverControllerGtk::GetHoverControllerGtk( 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* button) { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<HoverControllerGtk*>( 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_get_data(G_OBJECT(button), kHoverControllerGtkKey)); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HoverControllerGtk::Destroy() { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), -1.0); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_set_data(G_OBJECT(button_), kHoverControllerGtkKey, NULL); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_object_unref(button_); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch button_ = NULL; 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete this; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid HoverControllerGtk::AnimationProgressed(const ui::Animation* animation) { 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!button_) 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ignore the hover animation if we are throbbing. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animation == &hover_animation_ && throb_animation_.is_animating()) 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch animation->GetCurrentValue()); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid HoverControllerGtk::AnimationEnded(const ui::Animation* animation) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!button_) 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (animation != &throb_animation_) 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (throb_animation_.cycles_remaining() <= 1) 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid HoverControllerGtk::AnimationCanceled(const ui::Animation* animation) { 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AnimationEnded(animation); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean HoverControllerGtk::OnEnter(GtkWidget* widget, 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventCrossing* event) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_.Show(); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean HoverControllerGtk::OnLeave(GtkWidget* widget, 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventCrossing* event) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When the user is holding a mouse button, we don't want to animate. 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_.Reset(); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hover_animation_.Hide(); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FALSE; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HoverControllerGtk::OnHierarchyChanged(GtkWidget* widget, 114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick GtkWidget* previous_toplevel) { 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // GTK+ does not emit leave-notify-event signals when a widget 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // becomes unanchored, so manually unset the hover states. 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(widget))) { 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_widget_set_state(button_, GTK_STATE_NORMAL); 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick hover_animation_.Reset(); 120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick gtk_chrome_button_set_hover_state(GTK_CHROME_BUTTON(button_), 0.0); 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HoverControllerGtk::OnDestroy(GtkWidget* widget) { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Destroy(); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 127