Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / chrome / browser / ui / gtk / gtk_chrome_link_button.cc
blobc20a094e98cb73572be42fa352cda5e491cd1f5e
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
7 #include <stdlib.h>
9 #include "chrome/browser/ui/gtk/gtk_util.h"
10 #include "ui/gfx/gtk_compat.h"
11 #include "ui/gfx/gtk_util.h"
13 static const gchar* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>";
14 static const gchar* kInsensitiveLinkMarkup = "<span color=\"%s\">%s</span>";
16 namespace {
18 // Set the GTK style on our custom link button. We don't want any border around
19 // the link text.
20 void SetLinkButtonStyle() {
21 static bool style_was_set = false;
23 if (style_was_set)
24 return;
25 style_was_set = true;
27 gtk_rc_parse_string(
28 "style \"chrome-link-button\" {"
29 " GtkButton::inner-border = {0, 0, 0, 0}"
30 " GtkButton::child-displacement-x = 0"
31 " GtkButton::child-displacement-y = 0"
32 " xthickness = 0"
33 " ythickness = 0"
34 "}"
35 "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
38 static void gtk_chrome_link_button_destroy_text_resources(
39 GtkChromeLinkButton* button) {
40 g_free(button->native_markup);
41 button->native_markup = NULL;
42 g_free(button->normal_markup);
43 button->normal_markup = NULL;
44 g_free(button->pressed_markup);
45 button->pressed_markup = NULL;
46 g_free(button->insensitive_markup);
47 button->insensitive_markup = NULL;
49 g_free(button->text);
50 button->text = NULL;
53 } // namespace
55 G_BEGIN_DECLS
56 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)
58 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
59 // If we were called before we were realized, abort. We'll be called for
60 // real when |button| is realized.
61 if (!gtk_widget_get_realized(GTK_WIDGET(button)))
62 return;
64 g_free(button->native_markup);
65 button->native_markup = NULL;
66 g_free(button->normal_markup);
67 button->normal_markup = NULL;
68 g_free(button->pressed_markup);
69 button->pressed_markup = NULL;
70 g_free(button->insensitive_markup);
71 button->insensitive_markup = NULL;
73 gchar* text = button->text;
74 gboolean uses_markup = button->uses_markup;
76 GtkStyle* style = gtk_rc_get_style(button->label);
77 GdkColor insensitive_color = style->fg[GTK_STATE_INSENSITIVE];
78 gchar insensitive_color_spec[9];
79 snprintf(insensitive_color_spec, 9, "#%02X%02X%02X",
80 insensitive_color.red / 257, insensitive_color.green / 257,
81 insensitive_color.blue / 257);
83 if (!uses_markup) {
84 button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
85 button->normal_color,
86 text);
87 button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
88 button->insensitive_markup = g_markup_printf_escaped(kInsensitiveLinkMarkup,
89 insensitive_color_spec,
90 text);
91 } else {
92 button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
93 text);
95 button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
96 button->insensitive_markup = g_strdup_printf(kInsensitiveLinkMarkup,
97 insensitive_color_spec,
98 text);
101 // Get the current GTK theme's link button text color.
102 GdkColor* native_color = NULL;
103 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);
105 if (native_color) {
106 gchar color_spec[9];
107 snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
108 native_color->green / 257, native_color->blue / 257);
109 gdk_color_free(native_color);
111 if (!uses_markup) {
112 button->native_markup = g_markup_printf_escaped(kLinkMarkup,
113 color_spec, text);
114 } else {
115 button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
117 } else {
118 // If the theme doesn't have a link color, just use blue. This matches the
119 // default for GtkLinkButton.
120 button->native_markup = g_strdup(button->normal_markup);
123 gtk_label_set_markup(GTK_LABEL(button->label),
124 button->using_native_theme ? button->native_markup :
125 button->normal_markup);
128 static void gtk_chrome_link_button_style_changed(GtkChromeLinkButton* button) {
129 // Regenerate the link with the possibly new colors after the user has
130 // changed his GTK style.
131 gtk_chrome_link_button_set_text(button);
133 if (gtk_widget_get_visible(GTK_WIDGET(button)))
134 gtk_widget_queue_draw(GTK_WIDGET(button));
137 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
138 GdkEventExpose* event) {
139 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
140 GtkWidget* label = button->label;
141 GtkStateType widget_state = gtk_widget_get_state(widget);
143 if (widget_state != button->label_state) {
144 switch (widget_state) {
145 case GTK_STATE_NORMAL:
146 gtk_label_set_markup(GTK_LABEL(label),
147 button->using_native_theme ? button->native_markup :
148 button->normal_markup);
149 break;
150 case GTK_STATE_ACTIVE:
151 gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup);
152 break;
153 case GTK_STATE_INSENSITIVE:
154 gtk_label_set_markup(GTK_LABEL(label), button->insensitive_markup);
155 break;
156 default:
157 break;
159 button->label_state = widget_state;
162 // Draw the link inside the button.
163 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);
165 // Draw the focus rectangle.
166 if (gtk_widget_has_focus(widget)) {
167 GtkAllocation allocation;
168 gtk_widget_get_allocation(widget, &allocation);
169 gtk_paint_focus(gtk_widget_get_style(widget),
170 gtk_widget_get_window(widget),
171 gtk_widget_get_state(widget),
172 &event->area, widget, NULL,
173 allocation.x, allocation.y,
174 allocation.width, allocation.height);
177 return TRUE;
180 static void gtk_chrome_link_button_enter(GtkButton* button) {
181 GtkWidget* widget = GTK_WIDGET(button);
182 GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
183 gdk_window_set_cursor(gtk_widget_get_window(widget),
184 link_button->hand_cursor);
187 static void gtk_chrome_link_button_leave(GtkButton* button) {
188 GtkWidget* widget = GTK_WIDGET(button);
189 gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
192 static void gtk_chrome_link_button_destroy(GtkObject* object) {
193 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
195 gtk_chrome_link_button_destroy_text_resources(button);
197 button->hand_cursor = NULL;
199 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
202 static void gtk_chrome_link_button_class_init(
203 GtkChromeLinkButtonClass* link_button_class) {
204 GtkWidgetClass* widget_class =
205 reinterpret_cast<GtkWidgetClass*>(link_button_class);
206 GtkButtonClass* button_class =
207 reinterpret_cast<GtkButtonClass*>(link_button_class);
208 GtkObjectClass* object_class =
209 reinterpret_cast<GtkObjectClass*>(link_button_class);
210 widget_class->expose_event = &gtk_chrome_link_button_expose;
211 button_class->enter = &gtk_chrome_link_button_enter;
212 button_class->leave = &gtk_chrome_link_button_leave;
213 object_class->destroy = &gtk_chrome_link_button_destroy;
216 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
217 SetLinkButtonStyle();
219 // We put a label in a button so we can connect to the click event. We don't
220 // let the button draw itself; catch all expose events to the button and pass
221 // them through to the label.
222 button->label = gtk_label_new(NULL);
223 button->normal_markup = NULL;
224 button->pressed_markup = NULL;
225 button->label_state = GTK_STATE_NORMAL;
226 strncpy(button->normal_color, "blue", 9);
227 button->native_markup = NULL;
228 button->using_native_theme = TRUE;
229 button->hand_cursor = gfx::GetCursor(GDK_HAND2);
230 button->text = NULL;
232 gtk_container_add(GTK_CONTAINER(button), button->label);
233 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
234 g_signal_connect(button, "realize",
235 G_CALLBACK(gtk_chrome_link_button_set_text), NULL);
236 g_signal_connect(button, "style-set",
237 G_CALLBACK(gtk_chrome_link_button_style_changed), NULL);
240 GtkWidget* gtk_chrome_link_button_new(const char* text) {
241 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
242 GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
243 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
245 return lb;
248 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
249 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
250 GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
251 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
253 return lb;
256 void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
257 gboolean use_gtk) {
258 if (use_gtk != button->using_native_theme) {
259 button->using_native_theme = use_gtk;
261 gtk_chrome_link_button_set_text(button);
263 if (gtk_widget_get_visible(GTK_WIDGET(button)))
264 gtk_widget_queue_draw(GTK_WIDGET(button));
268 void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
269 const char* text) {
270 g_free(button->text);
271 button->text = g_strdup(text);
273 gtk_chrome_link_button_set_text(button);
275 if (gtk_widget_get_visible(GTK_WIDGET(button)))
276 gtk_widget_queue_draw(GTK_WIDGET(button));
279 void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
280 const GdkColor* color) {
281 if (color) {
282 snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
283 color->green / 257, color->blue / 257);
284 } else {
285 strncpy(button->normal_color, "blue", 9);
288 gtk_chrome_link_button_set_text(button);
290 if (gtk_widget_get_visible(GTK_WIDGET(button)))
291 gtk_widget_queue_draw(GTK_WIDGET(button));
294 G_END_DECLS