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

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

Issue 400009: GTK: fix link button double free.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: g_strdup_printf Created 11 years, 1 month 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 | « no previous file | no next file » | 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 #include "chrome/common/gtk_util.h" 10 #include "chrome/common/gtk_util.h"
(...skipping 15 matching lines...) Expand all
26 "style \"chrome-link-button\" {" 26 "style \"chrome-link-button\" {"
27 " GtkButton::inner-border = {0, 0, 0, 0}" 27 " GtkButton::inner-border = {0, 0, 0, 0}"
28 " GtkButton::child-displacement-x = 0" 28 " GtkButton::child-displacement-x = 0"
29 " GtkButton::child-displacement-y = 0" 29 " GtkButton::child-displacement-y = 0"
30 " xthickness = 0" 30 " xthickness = 0"
31 " ythickness = 0" 31 " ythickness = 0"
32 "}" 32 "}"
33 "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\""); 33 "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\"");
34 } 34 }
35 35
36 static void gtk_chrome_link_button_destroy_text_resources(
37 GtkChromeLinkButton* button) {
38 g_free(button->native_markup);
39 button->native_markup = NULL;
40 g_free(button->normal_markup);
41 button->normal_markup = NULL;
42 g_free(button->pressed_markup);
43 button->pressed_markup = NULL;
44
45 g_free(button->text);
46 button->text = NULL;
47 }
48
36 } // namespace 49 } // namespace
37 50
38 G_BEGIN_DECLS 51 G_BEGIN_DECLS
39 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) 52 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON)
40 53
41 // Should be called after we are realized so that the "link-color" property 54 // Should be called after we are realized so that the "link-color" property
42 // can be read. 55 // can be read.
43 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) { 56 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) {
44 // We only set the markup once. 57 // We only set the markup once.
45 if (button->normal_markup) 58 if (button->normal_markup)
46 return; 59 return;
47 60
48 gchar* text = button->text; 61 gchar* text = button->text;
49 gboolean uses_markup = button->uses_markup; 62 gboolean uses_markup = button->uses_markup;
50 63
51 if (!uses_markup) { 64 if (!uses_markup) {
52 button->normal_markup = g_markup_printf_escaped(kLinkMarkup, 65 button->normal_markup = g_markup_printf_escaped(kLinkMarkup,
53 button->normal_color, 66 button->normal_color,
54 text); 67 text);
55 button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); 68 button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text);
56 } else { 69 } else {
57 int length = strlen(kLinkMarkup) + 9 + strlen(text) + 1; 70 button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color,
58 button->normal_markup = static_cast<gchar*>(g_malloc(length)); 71 text);
59 snprintf(button->normal_markup, length, kLinkMarkup, button->normal_color,
60 text);
61 72
62 length = strlen(kLinkMarkup) + strlen("red") + strlen(text) + 1; 73 button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text);
63 button->pressed_markup = static_cast<gchar*>(g_malloc(length));
64 snprintf(button->pressed_markup, length, kLinkMarkup, "red", text);
65 } 74 }
66 75
67 // Get the current GTK theme's link button text color. 76 // Get the current GTK theme's link button text color.
68 GdkColor* native_color = NULL; 77 GdkColor* native_color = NULL;
69 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL); 78 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL);
70 79
71 if (native_color) { 80 if (native_color) {
72 gchar color_spec[9]; 81 gchar color_spec[9];
73 snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257, 82 snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257,
74 native_color->green / 257, native_color->blue / 257); 83 native_color->green / 257, native_color->blue / 257);
75 gdk_color_free(native_color); 84 gdk_color_free(native_color);
76 85
77 if (!uses_markup) { 86 if (!uses_markup) {
78 button->native_markup = g_markup_printf_escaped(kLinkMarkup, 87 button->native_markup = g_markup_printf_escaped(kLinkMarkup,
79 color_spec, text); 88 color_spec, text);
80 } else { 89 } else {
81 int length = strlen(kLinkMarkup) + strlen(color_spec) + strlen(text) + 1; 90 button->native_markup = g_strdup_printf(kLinkMarkup, color_spec, text);
82 button->native_markup = static_cast<gchar*>(g_malloc(length));
83 snprintf(button->native_markup, length, kLinkMarkup, color_spec, text);
84 } 91 }
85 } else { 92 } else {
86 // If the theme doesn't have a link color, just use blue. This matches the 93 // If the theme doesn't have a link color, just use blue. This matches the
87 // default for GtkLinkButton. 94 // default for GtkLinkButton.
88 button->native_markup = button->normal_markup; 95 button->native_markup = g_strdup(button->normal_markup);
89 } 96 }
90 97
91 gtk_label_set_markup(GTK_LABEL(button->label), 98 gtk_label_set_markup(GTK_LABEL(button->label),
92 button->using_native_theme ? button->native_markup : 99 button->using_native_theme ? button->native_markup :
93 button->normal_markup); 100 button->normal_markup);
94 } 101 }
95 102
96 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, 103 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget,
97 GdkEventExpose* event) { 104 GdkEventExpose* event) {
98 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); 105 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 gdk_window_set_cursor(widget->window, link_button->hand_cursor); 139 gdk_window_set_cursor(widget->window, link_button->hand_cursor);
133 } 140 }
134 141
135 static void gtk_chrome_link_button_leave(GtkButton* button) { 142 static void gtk_chrome_link_button_leave(GtkButton* button) {
136 GtkWidget* widget = GTK_WIDGET(button); 143 GtkWidget* widget = GTK_WIDGET(button);
137 gdk_window_set_cursor(widget->window, NULL); 144 gdk_window_set_cursor(widget->window, NULL);
138 } 145 }
139 146
140 static void gtk_chrome_link_button_destroy(GtkObject* object) { 147 static void gtk_chrome_link_button_destroy(GtkObject* object) {
141 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object); 148 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object);
142 if (button->native_markup && (button->native_markup != button->normal_markup)) 149
143 g_free(button->native_markup); 150 gtk_chrome_link_button_destroy_text_resources(button);
144 button->native_markup = NULL; 151
145 if (button->normal_markup) {
146 g_free(button->normal_markup);
147 button->normal_markup = NULL;
148 }
149 if (button->pressed_markup) {
150 g_free(button->pressed_markup);
151 button->pressed_markup = NULL;
152 }
153 if (button->hand_cursor) { 152 if (button->hand_cursor) {
154 gdk_cursor_unref(button->hand_cursor); 153 gdk_cursor_unref(button->hand_cursor);
155 button->hand_cursor = NULL; 154 button->hand_cursor = NULL;
156 } 155 }
157 156
158 free(button->text);
159 button->text = NULL;
160
161 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object); 157 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object);
162 } 158 }
163 159
164 static void gtk_chrome_link_button_class_init( 160 static void gtk_chrome_link_button_class_init(
165 GtkChromeLinkButtonClass* link_button_class) { 161 GtkChromeLinkButtonClass* link_button_class) {
166 GtkWidgetClass* widget_class = 162 GtkWidgetClass* widget_class =
167 reinterpret_cast<GtkWidgetClass*>(link_button_class); 163 reinterpret_cast<GtkWidgetClass*>(link_button_class);
168 GtkButtonClass* button_class = 164 GtkButtonClass* button_class =
169 reinterpret_cast<GtkButtonClass*>(link_button_class); 165 reinterpret_cast<GtkButtonClass*>(link_button_class);
170 GtkObjectClass* object_class = 166 GtkObjectClass* object_class =
(...skipping 19 matching lines...) Expand all
190 button->using_native_theme = TRUE; 186 button->using_native_theme = TRUE;
191 button->hand_cursor = gtk_util::GetCursor(GDK_HAND2); 187 button->hand_cursor = gtk_util::GetCursor(GDK_HAND2);
192 button->text = NULL; 188 button->text = NULL;
193 189
194 gtk_container_add(GTK_CONTAINER(button), button->label); 190 gtk_container_add(GTK_CONTAINER(button), button->label);
195 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); 191 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE);
196 } 192 }
197 193
198 GtkWidget* gtk_chrome_link_button_new(const char* text) { 194 GtkWidget* gtk_chrome_link_button_new(const char* text) {
199 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); 195 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
200 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(text); 196 GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(text);
201 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE; 197 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE;
202 return lb; 198 return lb;
203 } 199 }
204 200
205 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) { 201 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) {
206 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); 202 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL));
207 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(markup); 203 GTK_CHROME_LINK_BUTTON(lb)->text = g_strdup(markup);
208 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE; 204 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE;
209 return lb; 205 return lb;
210 } 206 }
211 207
212 void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button, 208 void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button,
213 gboolean use_gtk) { 209 gboolean use_gtk) {
214 if (use_gtk != button->using_native_theme) { 210 if (use_gtk != button->using_native_theme) {
215 button->using_native_theme = use_gtk; 211 button->using_native_theme = use_gtk;
216 if (GTK_WIDGET_VISIBLE(button)) 212 if (GTK_WIDGET_VISIBLE(button))
217 gtk_widget_queue_draw(GTK_WIDGET(button)); 213 gtk_widget_queue_draw(GTK_WIDGET(button));
218 } 214 }
219 } 215 }
220 216
221 void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button, 217 void gtk_chrome_link_button_set_label(GtkChromeLinkButton* button,
222 const char* text) { 218 const char* text) {
223 if (button->text) {
224 free(button->text);
225 }
226 button->text = strdup(text);
227
228 // Clear the markup so we can redraw. 219 // Clear the markup so we can redraw.
229 if (button->native_markup && (button->native_markup != button->normal_markup)) 220 gtk_chrome_link_button_destroy_text_resources(button);
230 g_free(button->native_markup); 221 button->text = g_strdup(text);
231 button->native_markup = NULL;
232 if (button->normal_markup) {
233 g_free(button->normal_markup);
234 button->normal_markup = NULL;
235 }
236 if (button->pressed_markup) {
237 g_free(button->pressed_markup);
238 button->pressed_markup = NULL;
239 }
240 222
241 if (GTK_WIDGET_VISIBLE(button)) 223 if (GTK_WIDGET_VISIBLE(button))
242 gtk_widget_queue_draw(GTK_WIDGET(button)); 224 gtk_widget_queue_draw(GTK_WIDGET(button));
243 } 225 }
244 226
245 void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button, 227 void gtk_chrome_link_button_set_normal_color(GtkChromeLinkButton* button,
246 const GdkColor* color) { 228 const GdkColor* color) {
247 if (button->normal_markup) { 229 g_free(button->normal_markup);
248 g_free(button->normal_markup); 230 button->normal_markup = NULL;
249 button->normal_markup = NULL;
250 }
251 231
252 if (color) { 232 if (color) {
253 snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257, 233 snprintf(button->normal_color, 9, "#%02X%02X%02X", color->red / 257,
254 color->green / 257, color->blue / 257); 234 color->green / 257, color->blue / 257);
255 } else { 235 } else {
256 strncpy(button->normal_color, "blue", 9); 236 strncpy(button->normal_color, "blue", 9);
257 } 237 }
258 238
259 if (GTK_WIDGET_VISIBLE(button)) 239 if (GTK_WIDGET_VISIBLE(button))
260 gtk_widget_queue_draw(GTK_WIDGET(button)); 240 gtk_widget_queue_draw(GTK_WIDGET(button));
261 } 241 }
262 242
263 G_END_DECLS 243 G_END_DECLS
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698