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#ifndef CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_ 672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#define CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/timer.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/owned_widget_gtk.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/status_bubble.h" 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_observer.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_registrar.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "ui/base/animation/animation_delegate.h" 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/gtk/gtk_signal.h" 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/point.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass GtkThemeService; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass Profile; 263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace ui { 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochclass SlideAnimation; 293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// GTK implementation of StatusBubble. Unlike Windows, our status bubble 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// doesn't have the nice leave-the-window effect since we can't rely on the 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// window manager to not try to be "helpful" and center our popups, etc. 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We therefore position it absolutely in a GtkFixed, that we don't own. 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass StatusBubbleGtk : public StatusBubble, 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public NotificationObserver, 373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public ui::AnimationDelegate { 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit StatusBubbleGtk(Profile* profile); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~StatusBubbleGtk(); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool flip_horizontally() const { return flip_horizontally_; } 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y_offset() const { return y_offset_; } 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // StatusBubble implementation. 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void SetStatus(const string16& status); 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void SetURL(const GURL& url, const string16& languages); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Hide(); 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void MouseMoved(const gfx::Point& location, bool left_content); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // ui::AnimationDelegate implementation. 523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationEnded(const ui::Animation* animation); 533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen virtual void AnimationProgressed(const ui::Animation* animation); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called when the download shelf becomes visible or invisible. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is used by to ensure that the status bubble does not obscure 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the download shelf, when it is visible. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void UpdateDownloadShelfVisibility(bool visible); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overridden from NotificationObserver: 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void Observe(NotificationType type, 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const NotificationSource& source, 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const NotificationDetails& details); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Top of the widget hierarchy for a StatusBubble. This top level widget is 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // guarenteed to have its gtk_widget_name set to "status-bubble" for 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // identification. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* widget() { return container_.get(); } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets the text of the label widget and controls visibility. (As contrasted 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with setting the current status or URL text, which may be ignored for now). 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetStatusTextTo(const std::string& status_utf8); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets the status text to the current value of |url_|, eliding it as 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // necessary. 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetStatusTextToURL(); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets the status bubble's location in the parent GtkFixed, shows the widget 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and makes sure that the status bubble has the highest z-order. 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Show(); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Builds the widgets, containers, etc. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void InitWidgets(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notification from the window that we should retheme ourself. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UserChangedTheme(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets whether the bubble should be flipped horizontally and displayed on the 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // opposite side of the tab contents. Reshapes the container and queues a 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // redraw if necessary. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetFlipHorizontally(bool flip_horizontally); 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Expand the bubble up to the full width of the browser, so that the entire 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URL may be seen. Called after the user hovers over a link for sufficient 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void ExpandURL(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Adjust the actual size of the bubble by changing the label's size request. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void UpdateLabelSizeRequest(); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if the status bubble is in the expand-state (i.e., is 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // currently expanded or in the process of expanding). 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool expanded() { 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return expand_animation_.get(); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleMotionNotify, 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GdkEventMotion*); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CHROMEGTK_CALLBACK_1(StatusBubbleGtk, gboolean, HandleEnterNotify, 1123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen GdkEventCrossing*); 1133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationRegistrar registrar_; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Provides colors. 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GtkThemeService* theme_service_; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The toplevel event box. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OwnedWidgetGtk container_; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The GtkAlignment holding |label_|. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GtkWidget* padding_; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The GtkLabel holding the text. 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OwnedWidgetGtk label_; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The status text we want to display when there are no URLs to display. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string status_text_; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URL we are displaying for. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url_; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The possibly elided url text we want to display. 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string url_text_; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Used to determine the character set that the user can read (for eliding 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the url text). 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16 languages_; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A timer that hides our window after a delay. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::OneShotTimer<StatusBubbleGtk> hide_timer_; 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A timer that expands our window after a delay. 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::OneShotTimer<StatusBubbleGtk> expand_timer_; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The animation for resizing the status bubble on long hovers. 1483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen scoped_ptr<ui::SlideAnimation> expand_animation_; 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The start and end width of the current resize animation. 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int start_width_; 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int desired_width_; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Should the bubble be flipped horizontally (e.g. displayed on the right for 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an LTR language)? We move the bubble to the other side of the tab contents 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // rather than sliding it down when the download shelf is visible. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool flip_horizontally_; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Vertical offset used to hide the status bubble as the pointer nears it. 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int y_offset_; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the download shelf is visible, do not obscure it. 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool download_shelf_is_visible_; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 'location' and 'left_content' values from the last invocation of 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MouseMoved(). We hang onto these so we can move the bubble if necessary 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when its text changes, triggering a size change. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::Point last_mouse_location_; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool last_mouse_left_content_; 1703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 1713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Shortly after the cursor enters the status bubble, we'll get a message 1723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // that the cursor left the content area. This lets us ignore that. 1733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool ignore_next_left_content_; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif // CHROME_BROWSER_UI_GTK_STATUS_BUBBLE_GTK_H_ 177