diff options
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_gtk.cc | 17 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_gtk.h | 11 | ||||
-rw-r--r-- | views/views.gyp | 2 | ||||
-rw-r--r-- | views/widget/tooltip_manager_gtk.cc | 67 | ||||
-rw-r--r-- | views/widget/tooltip_manager_gtk.h | 8 | ||||
-rw-r--r-- | views/widget/tooltip_window_gtk.cc | 94 | ||||
-rw-r--r-- | views/widget/tooltip_window_gtk.h | 52 |
7 files changed, 185 insertions, 66 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 403480b..f0ec3a5 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -39,6 +39,10 @@ #include "third_party/WebKit/WebKit/chromium/public/gtk/WebInputEventFactory.h" #include "webkit/glue/webcursor_gtk_data.h" +#if defined(OS_CHROMEOS) +#include "views/widget/tooltip_window_gtk.h" +#endif // defined(OS_CHROMEOS) + static const int kMaxWindowWidth = 4000; static const int kMaxWindowHeight = 4000; @@ -349,6 +353,11 @@ void RenderWidgetHostViewGtk::InitAsChild() { // |key_bindings_handler_| must be created after creating |view_| widget. key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get())); plugin_container_manager_.set_host_widget(view_.get()); + +#if defined(OS_CHROMEOS) + tooltip_window_.reset(new views::TooltipWindowGtk(view_.get())); +#endif // defined(OS_CHROMEOS) + gtk_widget_show(view_.get()); } @@ -363,6 +372,11 @@ void RenderWidgetHostViewGtk::InitAsPopup( // |key_bindings_handler_| must be created after creating |view_| widget. key_bindings_handler_.reset(new GtkKeyBindingsHandler(view_.get())); plugin_container_manager_.set_host_widget(view_.get()); + +#if defined(OS_CHROMEOS) + tooltip_window_.reset(new views::TooltipWindowGtk(view_.get())); +#endif // defined(OS_CHROMEOS) + gtk_container_add(GTK_CONTAINER(popup), view_.get()); // If we are not activatable, we don't want to grab keyboard input, @@ -608,6 +622,9 @@ void RenderWidgetHostViewGtk::SetTooltipText(const std::wstring& tooltip_text) { } else { gtk_widget_set_tooltip_text(view_.get(), WideToUTF8(clamped_tooltip).c_str()); +#if defined(OS_CHROMEOS) + tooltip_window_->SetTooltipText(clamped_tooltip); +#endif // defined(OS_CHROMEOS) } } diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h index e5939b5..3f9d90d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -26,6 +26,12 @@ class GtkKeyBindingsHandler; class MenuGtk; struct NativeWebKeyboardEvent; +#if defined(OS_CHROMEOS) +namespace views { +class TooltipWindowGtk; +} +#endif // defined(OS_CHROMEOS) + typedef struct _GtkClipboard GtkClipboard; typedef struct _GtkSelectionData GtkSelectionData; @@ -179,6 +185,11 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView { // The size that we want the renderer to be. We keep this in a separate // variable because resizing in GTK+ is async. gfx::Size requested_size_; + +#if defined(OS_CHROMEOS) + // Custimized tooltip window. + scoped_ptr<views::TooltipWindowGtk> tooltip_window_; +#endif // defined(OS_CHROMEOS) }; #endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_GTK_H_ diff --git a/views/views.gyp b/views/views.gyp index 950fb86..50c15b1 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -277,6 +277,8 @@ 'widget/tooltip_manager_win.h', 'widget/tooltip_manager.cc', 'widget/tooltip_manager.h', + 'widget/tooltip_window_gtk.cc', + 'widget/tooltip_window_gtk.h', 'widget/widget.h', 'widget/widget_gtk.cc', 'widget/widget_gtk.h', diff --git a/views/widget/tooltip_manager_gtk.cc b/views/widget/tooltip_manager_gtk.cc index 255f1ca..9ea6a00 100644 --- a/views/widget/tooltip_manager_gtk.cc +++ b/views/widget/tooltip_manager_gtk.cc @@ -71,68 +71,10 @@ int TooltipManager::GetMaxWidth(int x, int y) { return monitor_bounds.width() == 0 ? 800 : (monitor_bounds.width() + 1) / 2; } -// Callback from gtk_container_foreach. If |*label_p| is NULL and |widget| is -// a GtkLabel, |*label_p| is set to |widget|. Used to find the first GtkLabel -// in a container. -static void LabelLocatorCallback(GtkWidget* widget, - gpointer label_p) { - GtkWidget** label = static_cast<GtkWidget**>(label_p); - if (!*label && GTK_IS_LABEL(widget)) - *label = widget; -} - -// By default GtkTooltip wraps at a longish string. We want more control over -// that wrapping. The only way to do that is dig out the label and set -// gtk_label_set_max_width_chars, which is what this code does. I also tried -// setting a custom widget on the tooltip, but there is a bug in Gtk that -// triggers continually hiding/showing the widget in that case. -static void AdjustLabel(GtkTooltip* tooltip) { - static const char kAdjustedLabelPropertyValue[] = "_adjusted_label_"; - static const char kTooltipLabel[] = "_tooltip_label_"; - gpointer adjusted_value = g_object_get_data(G_OBJECT(tooltip), - kAdjustedLabelPropertyValue); - if (adjusted_value) { - gpointer label_ptr = g_object_get_data(G_OBJECT(tooltip), kTooltipLabel); - if (label_ptr) { - // Setting the text in a label doesn't force recalculating wrap position. - // We force recalculating wrap position by resetting the max width. - gtk_label_set_max_width_chars(reinterpret_cast<GtkLabel*>(label_ptr), - 2999); - gtk_label_set_max_width_chars(reinterpret_cast<GtkLabel*>(label_ptr), - 3000); - } - return; - } - - adjusted_value = reinterpret_cast<gpointer>(1); - g_object_set_data(G_OBJECT(tooltip), kAdjustedLabelPropertyValue, - adjusted_value); - GtkWidget* parent; - { - // Create a label so that we can get the parent. The Tooltip ends up taking - // ownership of the label and deleting it. - GtkWidget* label = gtk_label_new(""); - gtk_tooltip_set_custom(tooltip, label); - parent = gtk_widget_get_parent(label); - gtk_tooltip_set_custom(tooltip, NULL); - } - if (parent) { - // We found the parent, find the first label, which is where the tooltip - // text ends up going. - GtkLabel* real_label = NULL; - gtk_container_foreach(GTK_CONTAINER(parent), LabelLocatorCallback, - static_cast<gpointer>(&real_label)); - if (real_label) { - gtk_label_set_max_width_chars(GTK_LABEL(real_label), 3000); - g_object_set_data(G_OBJECT(tooltip), kTooltipLabel, - reinterpret_cast<gpointer>(real_label)); - } - } -} - TooltipManagerGtk::TooltipManagerGtk(WidgetGtk* widget) : widget_(widget), - keyboard_view_(NULL) { + keyboard_view_(NULL), + tooltip_window_(widget->window_contents()) { } bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard, @@ -163,8 +105,6 @@ bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard, if (!view->GetTooltipText(view_loc, &text)) return false; - AdjustLabel(tooltip); - // Sets the area of the tooltip. This way if different views in the same // widget have tooltips the tooltip doesn't get stuck at the same location. gfx::Rect vis_bounds = view->GetVisibleBounds(); @@ -179,8 +119,7 @@ bool TooltipManagerGtk::ShowTooltip(int x, int y, bool for_keyboard, View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc); TrimTooltipToFit(&text, &max_width, &line_count, screen_loc.x(), screen_loc.y()); - gtk_tooltip_set_text(tooltip, WideToUTF8(text).c_str()); - + tooltip_window_.SetTooltipText(text); return true; } diff --git a/views/widget/tooltip_manager_gtk.h b/views/widget/tooltip_manager_gtk.h index ca690ab..d939343 100644 --- a/views/widget/tooltip_manager_gtk.h +++ b/views/widget/tooltip_manager_gtk.h @@ -5,10 +5,11 @@ #ifndef VIEWS_WIDGET_TOOLTIP_MANAGER_GTK_H_ #define VIEWS_WIDGET_TOOLTIP_MANAGER_GTK_H_ -#include "views/widget/tooltip_manager.h" - #include <gtk/gtk.h> +#include "views/widget/tooltip_manager.h" +#include "views/widget/tooltip_window_gtk.h" + namespace views { class WidgetGtk; @@ -40,6 +41,9 @@ class TooltipManagerGtk : public TooltipManager { // The view supplied to the last invocation of ShowKeyboardTooltip. View* keyboard_view_; + // Custimized tooltip window. + TooltipWindowGtk tooltip_window_; + DISALLOW_COPY_AND_ASSIGN(TooltipManagerGtk); }; diff --git a/views/widget/tooltip_window_gtk.cc b/views/widget/tooltip_window_gtk.cc new file mode 100644 index 0000000..e76338c --- /dev/null +++ b/views/widget/tooltip_window_gtk.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "views/widget/tooltip_window_gtk.h" + +#include "base/utf_string_conversions.h" + +namespace views { + +TooltipWindowGtk::TooltipWindowGtk(GtkWidget* widget) + : host_(widget), + window_(NULL), + alignment_(NULL), + label_(NULL) { + Init(); +} + +TooltipWindowGtk::~TooltipWindowGtk() { + if (window_) + gtk_widget_destroy(window_); +} + +void TooltipWindowGtk::SetTooltipText(const std::wstring& text) { + const std::string& utf8 = WideToUTF8(text); + + gtk_label_set_text(label(), utf8.c_str()); + // Setting the text in a label doesn't force recalculating wrap position. + // We force recalculating wrap position by resetting the max width. + gtk_label_set_max_width_chars(label(), 2999); + gtk_label_set_max_width_chars(label(), 3000); +} + +void TooltipWindowGtk::Init() { + // Creates and setup tooltip window. + window_ = gtk_window_new(GTK_WINDOW_POPUP); + gtk_window_set_type_hint(GTK_WINDOW(window_), GDK_WINDOW_TYPE_HINT_TOOLTIP); + gtk_widget_set_app_paintable(window_, TRUE); + gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); + gtk_widget_set_name(window_, "gtk-tooltip"); + + GdkColormap* rgba_colormap = + gdk_screen_get_rgba_colormap(gdk_screen_get_default()); + if (rgba_colormap) + gtk_widget_set_colormap(window_, rgba_colormap); + + g_signal_connect(G_OBJECT(window_), "expose-event", + G_CALLBACK(&OnPaintThunk), this); + g_signal_connect(G_OBJECT(window_), "style-set", + G_CALLBACK(&OnStyleSetThunk), this); + + alignment_ = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); + gtk_container_add(GTK_CONTAINER(window_), alignment_); + gtk_widget_show(alignment_); + + label_ = gtk_label_new(""); + gtk_label_set_line_wrap(GTK_LABEL(label_), TRUE); + gtk_label_set_max_width_chars(GTK_LABEL(label_), 3000); + gtk_container_add(GTK_CONTAINER(alignment_), label_); + gtk_widget_show(label_); + + // Associates the tooltip window with given widget + gtk_widget_set_tooltip_window(host_, GTK_WINDOW(window_)); +} + +// Paints our customized tooltip window. +gboolean TooltipWindowGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) { + gtk_paint_flat_box(widget->style, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + NULL, + widget, + "tooltip", + 0, 0, + widget->allocation.width, + widget->allocation.height); + + return FALSE; +} + +// Style change handler. +void TooltipWindowGtk::OnStyleSet(GtkWidget* widget, + GtkStyle* previous_style) { + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment_), + widget->style->ythickness, + widget->style->ythickness, + widget->style->xthickness, + widget->style->xthickness); + + gtk_widget_queue_draw(widget); +} + +} // namespace views diff --git a/views/widget/tooltip_window_gtk.h b/views/widget/tooltip_window_gtk.h new file mode 100644 index 0000000..556fa67 --- /dev/null +++ b/views/widget/tooltip_window_gtk.h @@ -0,0 +1,52 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VIEWS_WIDGET_TOOLTIP_WINDOW_GTK_H_ +#define VIEWS_WIDGET_TOOLTIP_WINDOW_GTK_H_ + +#include <gtk/gtk.h> +#include <string> + +#include "app/gtk_signal.h" + +namespace views { + +// TooltipWindowGtk provides a customized tooltip window and gives us a +// chance to apply RGBA colormap on it. This enables the GTK theme engine to +// draw tooltip with nice shadow and rounded corner on ChromeOS. +class TooltipWindowGtk { + public: + explicit TooltipWindowGtk(GtkWidget* widget); + ~TooltipWindowGtk(); + + // Sets tooltip text to display. + void SetTooltipText(const std::wstring& text); + + GtkLabel* label() { + return GTK_LABEL(label_); + } + + protected: + CHROMEGTK_CALLBACK_1(TooltipWindowGtk, gboolean, OnPaint, GdkEventExpose*); + CHROMEGTK_CALLBACK_1(TooltipWindowGtk, void, OnStyleSet, GtkStyle*); + + private: + void Init(); + + // Underlying widget of this tooltip window. + GtkWidget* host_; + + // GtkWindow of this tooltip window. + GtkWidget* window_; + + // The alignment and label widgets contained of the tooltip window. + GtkWidget* alignment_; + GtkWidget* label_; + + DISALLOW_COPY_AND_ASSIGN(TooltipWindowGtk); +}; + +} // namespace views + +#endif // VIEWS_WIDGET_TOOLTIP_WINDOW_GTK_H_ |