Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(484)

Side by Side Diff: chrome/browser/gtk/gtk_chrome_link_button.cc

Issue 160495: retry r2226, with a fix for a case where we could double free. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gtk/gtk_chrome_link_button.h ('k') | chrome/browser/gtk/infobar_gtk.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/gtk_chrome_link_button.h" 5 #include "chrome/browser/gtk/gtk_chrome_link_button.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 10
(...skipping 19 matching lines...) Expand all
30 " ythickness = 0" 30 " ythickness = 0"
31 "}" 31 "}"
32 "widget \"*chrome-link-button\" style \"chrome-link-button\""); 32 "widget \"*chrome-link-button\" style \"chrome-link-button\"");
33 } 33 }
34 34
35 } // namespace 35 } // namespace
36 36
37 G_BEGIN_DECLS 37 G_BEGIN_DECLS
38 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) 38 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)
39 39
40 // Should be called after we are realized so that the "link-color" property
41 // can be read.
42 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
43 // We only set the markup once.
44 if (button->blue_markup)
45 return;
46
47 gchar* text = button->text;
48 gboolean uses_markup = button->uses_markup;
49
50 if (!uses_markup) {
51 button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text);
52 button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
53 } else {
54 button->blue_markup = static_cast<gchar*>(
55 g_malloc(strlen(kLinkMarkup) + strlen("blue") + strlen(text) + 1));
56 sprintf(button->blue_markup, kLinkMarkup, "blue", text);
57
58 button->red_markup = static_cast<gchar*>(
59 g_malloc(strlen(kLinkMarkup) + strlen("red") + strlen(text) + 1));
60 sprintf(button->red_markup, kLinkMarkup, "red", text);
61 }
62
63 // Get the current GTK theme's link button text color.
64 GdkColor* native_color = NULL;
65 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);
66
67 if (native_color) {
68 gchar color_spec[9];
69 sprintf(color_spec, "#%02X%02X%02X", native_color->red / 257,
70 native_color->green / 257, native_color->blue / 257);
71 gdk_color_free(native_color);
72
73 if (!uses_markup) {
74 button->native_markup = g_markup_printf_escaped(kLinkMarkup,
75 color_spec, text);
76 } else {
77 button->native_markup = static_cast<gchar*>(
78 g_malloc(strlen(kLinkMarkup) + strlen(color_spec) + strlen(text) +
79 1));
80 sprintf(button->native_markup, kLinkMarkup, color_spec, text);
81 }
82 } else {
83 // If the theme doesn't have a link color, just use blue. This matches the
84 // default for GtkLinkButton.
85 button->native_markup = button->blue_markup;
86 }
87
88 gtk_label_set_markup(GTK_LABEL(button->label),
89 button->using_native_theme ? button->native_markup : button->blue_markup);
90 }
91
40 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, 92 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
41 GdkEventExpose* event) { 93 GdkEventExpose* event) {
42 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); 94 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
43 GtkWidget* label = button->label; 95 GtkWidget* label = button->label;
44 96
97 gtk_chrome_link_button_set_text(button);
98
45 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) { 99 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) {
46 gtk_label_set_markup(GTK_LABEL(label), button->red_markup); 100 gtk_label_set_markup(GTK_LABEL(label), button->red_markup);
47 button->is_blue = FALSE; 101 button->is_blue = FALSE;
48 } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) { 102 } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) {
49 gtk_label_set_markup(GTK_LABEL(label), button->blue_markup); 103 gtk_label_set_markup(GTK_LABEL(label),
104 button->using_native_theme ? button->native_markup : button->blue_markup );
50 button->is_blue = TRUE; 105 button->is_blue = TRUE;
51 } 106 }
52 107
53 // Draw the link inside the button. 108 // Draw the link inside the button.
54 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); 109 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event);
55 110
56 // Draw the focus rectangle. 111 // Draw the focus rectangle.
57 if (GTK_WIDGET_HAS_FOCUS(widget)) { 112 if (GTK_WIDGET_HAS_FOCUS(widget)) {
58 gtk_paint_focus(widget->style, widget->window, 113 gtk_paint_focus(widget->style, widget->window,
59 static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)), 114 static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)),
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 static void gtk_chrome_link_button_leave(GtkButton* button) { 162 static void gtk_chrome_link_button_leave(GtkButton* button) {
108 GtkWidget* widget = GTK_WIDGET(button); 163 GtkWidget* widget = GTK_WIDGET(button);
109 GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button); 164 GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button);
110 gdk_window_set_cursor(widget->window, NULL); 165 gdk_window_set_cursor(widget->window, NULL);
111 free(link_button->click_button_event); 166 free(link_button->click_button_event);
112 link_button->click_button_event = NULL; 167 link_button->click_button_event = NULL;
113 } 168 }
114 169
115 static void gtk_chrome_link_button_destroy(GtkObject* object) { 170 static void gtk_chrome_link_button_destroy(GtkObject* object) {
116 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object); 171 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
172 if (button->native_markup && (button->native_markup != button->blue_markup))
173 g_free(button->native_markup);
174 button->native_markup = NULL;
Evan Stade 2009/08/01 01:34:00 the difference from the last change is making it a
117 if (button->blue_markup) { 175 if (button->blue_markup) {
118 g_free(button->blue_markup); 176 g_free(button->blue_markup);
119 button->blue_markup = NULL; 177 button->blue_markup = NULL;
120 } 178 }
121 if (button->red_markup) { 179 if (button->red_markup) {
122 g_free(button->red_markup); 180 g_free(button->red_markup);
123 button->red_markup = NULL; 181 button->red_markup = NULL;
124 } 182 }
125 if (button->hand_cursor) { 183 if (button->hand_cursor) {
126 gdk_cursor_unref(button->hand_cursor); 184 gdk_cursor_unref(button->hand_cursor);
127 button->hand_cursor = NULL; 185 button->hand_cursor = NULL;
128 } 186 }
187
129 free(button->click_button_event); 188 free(button->click_button_event);
130 button->click_button_event = NULL; 189 button->click_button_event = NULL;
131 190
191 free(button->text);
192 button->text = NULL;
193
132 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object); 194 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
133 } 195 }
134 196
135 static void gtk_chrome_link_button_class_init( 197 static void gtk_chrome_link_button_class_init(
136 GtkChromeLinkButtonClass* link_button_class) { 198 GtkChromeLinkButtonClass* link_button_class) {
137 GtkWidgetClass* widget_class = 199 GtkWidgetClass* widget_class =
138 reinterpret_cast<GtkWidgetClass*>(link_button_class); 200 reinterpret_cast<GtkWidgetClass*>(link_button_class);
139 GtkButtonClass* button_class = 201 GtkButtonClass* button_class =
140 reinterpret_cast<GtkButtonClass*>(link_button_class); 202 reinterpret_cast<GtkButtonClass*>(link_button_class);
141 GtkObjectClass* object_class = 203 GtkObjectClass* object_class =
142 reinterpret_cast<GtkObjectClass*>(link_button_class); 204 reinterpret_cast<GtkObjectClass*>(link_button_class);
143 widget_class->expose_event = &gtk_chrome_link_button_expose; 205 widget_class->expose_event = &gtk_chrome_link_button_expose;
144 widget_class->button_press_event = &gtk_chrome_link_button_button_press; 206 widget_class->button_press_event = &gtk_chrome_link_button_button_press;
145 widget_class->button_release_event = &gtk_chrome_link_button_button_release; 207 widget_class->button_release_event = &gtk_chrome_link_button_button_release;
146 button_class->enter = &gtk_chrome_link_button_enter; 208 button_class->enter = &gtk_chrome_link_button_enter;
147 button_class->leave = &gtk_chrome_link_button_leave; 209 button_class->leave = &gtk_chrome_link_button_leave;
148 object_class->destroy = &gtk_chrome_link_button_destroy; 210 object_class->destroy = &gtk_chrome_link_button_destroy;
149 } 211 }
150 212
151 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { 213 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) {
152 SetLinkButtonStyle(); 214 SetLinkButtonStyle();
153 215
154 // We put a label in a button so we can connect to the click event. We don't 216 // We put a label in a button so we can connect to the click event. We don't
155 // let the button draw itself; catch all expose events to the button and pass 217 // let the button draw itself; catch all expose events to the button and pass
156 // them through to the label. 218 // them through to the label.
157 button->label = gtk_label_new(NULL); 219 button->label = gtk_label_new(NULL);
158 button->blue_markup = NULL; 220 button->blue_markup = NULL;
159 button->red_markup = NULL; 221 button->red_markup = NULL;
160 button->is_blue = TRUE; 222 button->is_blue = TRUE;
223 button->native_markup = NULL;
224 button->using_native_theme = TRUE;
161 button->hand_cursor = gdk_cursor_new(GDK_HAND2); 225 button->hand_cursor = gdk_cursor_new(GDK_HAND2);
162 button->click_button_event = NULL; 226 button->click_button_event = NULL;
227 button->text = NULL;
163 228
164 gtk_container_add(GTK_CONTAINER(button), button->label); 229 gtk_container_add(GTK_CONTAINER(button), button->label);
165 gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button"); 230 gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button");
166 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); 231 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
167 } 232 }
168 233
169 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button,
170 const char* text,
171 bool contains_markup) {
172 // We should have only been called once or we'd leak the markups.
173 DCHECK(!button->blue_markup && !button->red_markup);
174
175 if (!contains_markup) {
176 button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text);
177 button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
178 } else {
179 button->blue_markup = static_cast<gchar*>(
180 g_malloc(strlen(kLinkMarkup) + strlen("blue") + strlen(text) + 1));
181 sprintf(button->blue_markup, kLinkMarkup, "blue", text);
182
183 button->red_markup = static_cast<gchar*>(
184 g_malloc(strlen(kLinkMarkup) + strlen("red") + strlen(text) + 1));
185 sprintf(button->red_markup, kLinkMarkup, "red", text);
186 }
187
188 gtk_label_set_markup(GTK_LABEL(button->label), button->blue_markup);
189 button->is_blue = TRUE;
190 }
191
192 GtkWidget* gtk_chrome_link_button_new(const char* text) { 234 GtkWidget* gtk_chrome_link_button_new(const char* text) {
193 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); 235 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
194 gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), text, false); 236 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(text);
237 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
195 return lb; 238 return lb;
196 } 239 }
197 240
198 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) { 241 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
199 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); 242 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
200 gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), markup, true); 243 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(markup);
244 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
201 return lb; 245 return lb;
202 } 246 }
203 247
248 void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
249 gboolean use_gtk) {
250 if (use_gtk != button->using_native_theme) {
251 button->using_native_theme = use_gtk;
252 if (GTK_WIDGET_VISIBLE(button))
253 gtk_widget_queue_draw(GTK_WIDGET(button));
254 }
255 }
256
204 const GdkEventButton* gtk_chrome_link_button_get_event_for_click( 257 const GdkEventButton* gtk_chrome_link_button_get_event_for_click(
205 GtkChromeLinkButton* button) { 258 GtkChromeLinkButton* button) {
206 return button->click_button_event; 259 return button->click_button_event;
207 } 260 }
208 261
209 G_END_DECLS 262 G_END_DECLS
OLDNEW
« no previous file with comments | « chrome/browser/gtk/gtk_chrome_link_button.h ('k') | chrome/browser/gtk/infobar_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698