| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/ui/libgtk2ui/gtk2_ui.h" | 5 #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include <pango/pango.h> | 10 #include <pango/pango.h> |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 IDR_OMNIBOX_STAR, | 174 IDR_OMNIBOX_STAR, |
| 175 IDR_OMNIBOX_STAR_DARK, | 175 IDR_OMNIBOX_STAR_DARK, |
| 176 IDR_OMNIBOX_TTS, | 176 IDR_OMNIBOX_TTS, |
| 177 IDR_OMNIBOX_TTS_DARK, | 177 IDR_OMNIBOX_TTS_DARK, |
| 178 }; | 178 }; |
| 179 | 179 |
| 180 // This table converts button ids into a pair of gtk-stock id and state. | 180 // This table converts button ids into a pair of gtk-stock id and state. |
| 181 struct IDRGtkMapping { | 181 struct IDRGtkMapping { |
| 182 int idr; | 182 int idr; |
| 183 const char* stock_id; | 183 const char* stock_id; |
| 184 GtkStateType gtk_state; | 184 GtkStateFlags gtk_state; |
| 185 } const kGtkIcons[] = { | 185 } const kGtkIcons[] = { |
| 186 { IDR_BACK, GTK_STOCK_GO_BACK, GTK_STATE_NORMAL }, | 186 { IDR_BACK, GTK_STOCK_GO_BACK, GTK_STATE_FLAG_NORMAL }, |
| 187 { IDR_BACK_D, GTK_STOCK_GO_BACK, GTK_STATE_INSENSITIVE }, | 187 { IDR_BACK_D, GTK_STOCK_GO_BACK, GTK_STATE_FLAG_INSENSITIVE }, |
| 188 | 188 |
| 189 { IDR_FORWARD, GTK_STOCK_GO_FORWARD, GTK_STATE_NORMAL }, | 189 { IDR_FORWARD, GTK_STOCK_GO_FORWARD, GTK_STATE_FLAG_NORMAL }, |
| 190 { IDR_FORWARD_D, GTK_STOCK_GO_FORWARD, GTK_STATE_INSENSITIVE }, | 190 { IDR_FORWARD_D, GTK_STOCK_GO_FORWARD, GTK_STATE_FLAG_INSENSITIVE }, |
| 191 | 191 |
| 192 { IDR_HOME, GTK_STOCK_HOME, GTK_STATE_NORMAL }, | 192 { IDR_HOME, GTK_STOCK_HOME, GTK_STATE_FLAG_NORMAL }, |
| 193 | 193 |
| 194 { IDR_RELOAD, GTK_STOCK_REFRESH, GTK_STATE_NORMAL }, | 194 { IDR_RELOAD, GTK_STOCK_REFRESH, GTK_STATE_FLAG_NORMAL }, |
| 195 { IDR_RELOAD_D, GTK_STOCK_REFRESH, GTK_STATE_INSENSITIVE }, | 195 { IDR_RELOAD_D, GTK_STOCK_REFRESH, GTK_STATE_FLAG_INSENSITIVE }, |
| 196 | 196 |
| 197 { IDR_STOP, GTK_STOCK_STOP, GTK_STATE_NORMAL }, | 197 { IDR_STOP, GTK_STOCK_STOP, GTK_STATE_FLAG_NORMAL }, |
| 198 { IDR_STOP_D, GTK_STOCK_STOP, GTK_STATE_INSENSITIVE }, | 198 { IDR_STOP_D, GTK_STOCK_STOP, GTK_STATE_FLAG_INSENSITIVE }, |
| 199 }; | 199 }; |
| 200 | 200 |
| 201 // The image resources that will be tinted by the 'button' tint value. | 201 // The image resources that will be tinted by the 'button' tint value. |
| 202 const int kOtherToolbarButtonIDs[] = { | 202 const int kOtherToolbarButtonIDs[] = { |
| 203 IDR_TOOLBAR_BEZEL_HOVER, | 203 IDR_TOOLBAR_BEZEL_HOVER, |
| 204 IDR_TOOLBAR_BEZEL_PRESSED, | 204 IDR_TOOLBAR_BEZEL_PRESSED, |
| 205 IDR_BROWSER_ACTIONS_OVERFLOW, | 205 IDR_BROWSER_ACTIONS_OVERFLOW, |
| 206 | 206 |
| 207 // TODO(erg): The dropdown arrow should be tinted because we're injecting | 207 // TODO(erg): The dropdown arrow should be tinted because we're injecting |
| 208 // various background GTK colors, but the code that accesses them needs to be | 208 // various background GTK colors, but the code that accesses them needs to be |
| (...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 if (theme_thumb_active && theme_thumb_inactive && theme_trough_color) { | 765 if (theme_thumb_active && theme_thumb_inactive && theme_trough_color) { |
| 766 *thumb_active_color = *theme_thumb_active; | 766 *thumb_active_color = *theme_thumb_active; |
| 767 *thumb_inactive_color = *theme_thumb_inactive; | 767 *thumb_inactive_color = *theme_thumb_inactive; |
| 768 *track_color = *theme_trough_color; | 768 *track_color = *theme_trough_color; |
| 769 | 769 |
| 770 gdk_color_free(theme_thumb_active); | 770 gdk_color_free(theme_thumb_active); |
| 771 gdk_color_free(theme_thumb_inactive); | 771 gdk_color_free(theme_thumb_inactive); |
| 772 gdk_color_free(theme_trough_color); | 772 gdk_color_free(theme_trough_color); |
| 773 return; | 773 return; |
| 774 } | 774 } |
| 775 | |
| 776 // Create window containing scrollbar elements | |
| 777 GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP); | |
| 778 GtkWidget* fixed = gtk_fixed_new(); | |
| 779 GtkWidget* scrollbar = gtk_hscrollbar_new(NULL); | |
| 780 gtk_container_add(GTK_CONTAINER(window), fixed); | |
| 781 gtk_container_add(GTK_CONTAINER(fixed), scrollbar); | |
| 782 gtk_widget_realize(window); | |
| 783 gtk_widget_realize(scrollbar); | |
| 784 | |
| 785 // Draw scrollbar thumb part and track into offscreen image | |
| 786 const int kWidth = 100; | |
| 787 const int kHeight = 20; | |
| 788 GtkStyle* style = gtk_rc_get_style(scrollbar); | |
| 789 GdkWindow* gdk_window = gtk_widget_get_window(window); | |
| 790 GdkPixmap* pm = gdk_pixmap_new(gdk_window, kWidth, kHeight, -1); | |
| 791 GdkRectangle rect = { 0, 0, kWidth, kHeight }; | |
| 792 unsigned char data[3 * kWidth * kHeight]; | |
| 793 for (int i = 0; i < 3; ++i) { | |
| 794 if (i < 2) { | |
| 795 // Thumb part | |
| 796 gtk_paint_slider(style, pm, | |
| 797 i == 0 ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL, | |
| 798 GTK_SHADOW_OUT, &rect, scrollbar, "slider", 0, 0, | |
| 799 kWidth, kHeight, GTK_ORIENTATION_HORIZONTAL); | |
| 800 } else { | |
| 801 // Track | |
| 802 gtk_paint_box(style, pm, GTK_STATE_ACTIVE, GTK_SHADOW_IN, &rect, | |
| 803 scrollbar, "trough-upper", 0, 0, kWidth, kHeight); | |
| 804 } | |
| 805 GdkPixbuf* pb = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, | |
| 806 FALSE, 8, kWidth, kHeight, | |
| 807 3 * kWidth, 0, 0); | |
| 808 gdk_pixbuf_get_from_drawable(pb, pm, NULL, 0, 0, 0, 0, kWidth, kHeight); | |
| 809 | |
| 810 // Sample pixels | |
| 811 int components[3] = { 0 }; | |
| 812 for (int y = 2; y < kHeight - 2; ++y) { | |
| 813 for (int c = 0; c < 3; ++c) { | |
| 814 // Sample a vertical slice of pixels at about one-thirds from the | |
| 815 // left edge. This allows us to avoid any fixed graphics that might be | |
| 816 // located at the edges or in the center of the scrollbar. | |
| 817 // Each pixel is made up of a red, green, and blue component; taking up | |
| 818 // a total of three bytes. | |
| 819 components[c] += data[3 * (kWidth / 3 + y * kWidth) + c]; | |
| 820 } | |
| 821 } | |
| 822 GdkColor* color = i == 0 ? thumb_active_color : | |
| 823 i == 1 ? thumb_inactive_color : | |
| 824 track_color; | |
| 825 color->pixel = 0; | |
| 826 // We sampled pixels across the full height of the image, ignoring a two | |
| 827 // pixel border. In some themes, the border has a completely different | |
| 828 // color which we do not want to factor into our average color computation. | |
| 829 // | |
| 830 // We now need to scale the colors from the 0..255 range, to the wider | |
| 831 // 0..65535 range, and we need to actually compute the average color; so, | |
| 832 // we divide by the total number of pixels in the sample. | |
| 833 color->red = components[0] * 65535 / (255 * (kHeight - 4)); | |
| 834 color->green = components[1] * 65535 / (255 * (kHeight - 4)); | |
| 835 color->blue = components[2] * 65535 / (255 * (kHeight - 4)); | |
| 836 | |
| 837 g_object_unref(pb); | |
| 838 } | |
| 839 g_object_unref(pm); | |
| 840 | |
| 841 gtk_widget_destroy(window); | |
| 842 | |
| 843 // Override any of the default colors with ones that were specified by the | |
| 844 // theme. | |
| 845 if (theme_thumb_active) { | |
| 846 *thumb_active_color = *theme_thumb_active; | |
| 847 gdk_color_free(theme_thumb_active); | |
| 848 } | |
| 849 | |
| 850 if (theme_thumb_inactive) { | |
| 851 *thumb_inactive_color = *theme_thumb_inactive; | |
| 852 gdk_color_free(theme_thumb_inactive); | |
| 853 } | |
| 854 | |
| 855 if (theme_trough_color) { | |
| 856 *track_color = *theme_trough_color; | |
| 857 gdk_color_free(theme_trough_color); | |
| 858 } | |
| 859 } | 775 } |
| 860 | 776 |
| 861 void Gtk2UI::LoadGtkValues() { | 777 void Gtk2UI::LoadGtkValues() { |
| 862 // TODO(erg): GtkThemeService had a comment here about having to muck with | 778 // TODO(erg): GtkThemeService had a comment here about having to muck with |
| 863 // the raw Prefs object to remove prefs::kCurrentThemeImages or else we'd | 779 // the raw Prefs object to remove prefs::kCurrentThemeImages or else we'd |
| 864 // regress startup time. Figure out how to do that when we can't access the | 780 // regress startup time. Figure out how to do that when we can't access the |
| 865 // prefs system from here. | 781 // prefs system from here. |
| 866 | 782 |
| 867 GtkStyle* frame_style = gtk_rc_get_style(fake_frame_); | 783 GtkStyle* frame_style = gtk_rc_get_style(fake_frame_); |
| 868 | 784 |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 case IDR_FORWARD: | 1052 case IDR_FORWARD: |
| 1137 case IDR_FORWARD_D: | 1053 case IDR_FORWARD_D: |
| 1138 case IDR_HOME: | 1054 case IDR_HOME: |
| 1139 case IDR_RELOAD: | 1055 case IDR_RELOAD: |
| 1140 case IDR_RELOAD_D: | 1056 case IDR_RELOAD_D: |
| 1141 case IDR_STOP: | 1057 case IDR_STOP: |
| 1142 case IDR_STOP_D: { | 1058 case IDR_STOP_D: { |
| 1143 return GenerateGTKIcon(id); | 1059 return GenerateGTKIcon(id); |
| 1144 } | 1060 } |
| 1145 case IDR_TOOLBAR_BEZEL_HOVER: | 1061 case IDR_TOOLBAR_BEZEL_HOVER: |
| 1146 return GenerateToolbarBezel(GTK_STATE_PRELIGHT, IDR_TOOLBAR_BEZEL_HOVER); | 1062 return GenerateToolbarBezel(GTK_STATE_FLAG_PRELIGHT, IDR_TOOLBAR_BEZEL_HOV
ER); |
| 1147 case IDR_TOOLBAR_BEZEL_PRESSED: | 1063 case IDR_TOOLBAR_BEZEL_PRESSED: |
| 1148 return GenerateToolbarBezel(GTK_STATE_ACTIVE, IDR_TOOLBAR_BEZEL_PRESSED); | 1064 return GenerateToolbarBezel(GTK_STATE_FLAG_ACTIVE, IDR_TOOLBAR_BEZEL_PRESS
ED); |
| 1149 default: { | 1065 default: { |
| 1150 return GenerateTintedIcon(id, button_tint_); | 1066 return GenerateTintedIcon(id, button_tint_); |
| 1151 } | 1067 } |
| 1152 } | 1068 } |
| 1153 | 1069 |
| 1154 return SkBitmap(); | 1070 return SkBitmap(); |
| 1155 } | 1071 } |
| 1156 | 1072 |
| 1157 SkBitmap Gtk2UI::GenerateFrameImage( | 1073 SkBitmap Gtk2UI::GenerateFrameImage( |
| 1158 int color_id, | 1074 int color_id, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1206 SkBitmap Gtk2UI::GenerateTintedIcon( | 1122 SkBitmap Gtk2UI::GenerateTintedIcon( |
| 1207 int base_id, | 1123 int base_id, |
| 1208 const color_utils::HSL& tint) const { | 1124 const color_utils::HSL& tint) const { |
| 1209 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1125 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 1210 return SkBitmapOperations::CreateHSLShiftedBitmap( | 1126 return SkBitmapOperations::CreateHSLShiftedBitmap( |
| 1211 rb.GetImageNamed(base_id).AsBitmap(), tint); | 1127 rb.GetImageNamed(base_id).AsBitmap(), tint); |
| 1212 } | 1128 } |
| 1213 | 1129 |
| 1214 SkBitmap Gtk2UI::GenerateGTKIcon(int base_id) const { | 1130 SkBitmap Gtk2UI::GenerateGTKIcon(int base_id) const { |
| 1215 const char* stock_id = NULL; | 1131 const char* stock_id = NULL; |
| 1216 GtkStateType gtk_state = GTK_STATE_NORMAL; | 1132 GtkStateFlags gtk_state = GTK_STATE_FLAG_NORMAL; |
| 1217 for (unsigned int i = 0; i < arraysize(kGtkIcons); ++i) { | 1133 for (unsigned int i = 0; i < arraysize(kGtkIcons); ++i) { |
| 1218 if (kGtkIcons[i].idr == base_id) { | 1134 if (kGtkIcons[i].idr == base_id) { |
| 1219 stock_id = kGtkIcons[i].stock_id; | 1135 stock_id = kGtkIcons[i].stock_id; |
| 1220 gtk_state = kGtkIcons[i].gtk_state; | 1136 gtk_state = kGtkIcons[i].gtk_state; |
| 1221 break; | 1137 break; |
| 1222 } | 1138 } |
| 1223 } | 1139 } |
| 1224 DCHECK(stock_id); | 1140 DCHECK(stock_id); |
| 1225 | 1141 |
| 1226 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1142 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 1227 SkBitmap default_bitmap = rb.GetImageNamed(base_id).AsBitmap(); | 1143 SkBitmap default_bitmap = rb.GetImageNamed(base_id).AsBitmap(); |
| 1228 | 1144 |
| 1229 gtk_widget_ensure_style(fake_frame_); | 1145 gtk_widget_ensure_style(fake_frame_); |
| 1230 GtkStyle* style = gtk_widget_get_style(fake_frame_); | 1146 GtkStyle* style = gtk_widget_get_style(fake_frame_); |
| 1231 GtkIconSet* icon_set = gtk_style_lookup_icon_set(style, stock_id); | 1147 GtkIconSet* icon_set = gtk_style_lookup_icon_set(style, stock_id); |
| 1232 if (!icon_set) | 1148 if (!icon_set) |
| 1233 return default_bitmap; | 1149 return default_bitmap; |
| 1234 | 1150 |
| 1235 // Ask GTK to render the icon to a buffer, which we will steal from. | 1151 // Ask GTK to render the icon to a buffer, which we will steal from. |
| 1236 GdkPixbuf* gdk_icon = gtk_icon_set_render_icon( | 1152 GdkPixbuf* gdk_icon = gtk_icon_set_render_icon( |
| 1237 icon_set, | 1153 icon_set, |
| 1238 style, | 1154 style, |
| 1239 base::i18n::IsRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR, | 1155 base::i18n::IsRTL() ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR, |
| 1240 gtk_state, | 1156 gtk_state == GTK_STATE_FLAG_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STAT
E_NORMAL, |
| 1241 GTK_ICON_SIZE_SMALL_TOOLBAR, | 1157 GTK_ICON_SIZE_SMALL_TOOLBAR, |
| 1242 fake_frame_, | 1158 fake_frame_, |
| 1243 NULL); | 1159 NULL); |
| 1244 | 1160 |
| 1245 if (!gdk_icon) { | 1161 if (!gdk_icon) { |
| 1246 // This can theoretically happen if an icon theme doesn't provide a | 1162 // This can theoretically happen if an icon theme doesn't provide a |
| 1247 // specific image. This should realistically never happen, but I bet there | 1163 // specific image. This should realistically never happen, but I bet there |
| 1248 // are some theme authors who don't reliably provide all icons. | 1164 // are some theme authors who don't reliably provide all icons. |
| 1249 return default_bitmap; | 1165 return default_bitmap; |
| 1250 } | 1166 } |
| 1251 | 1167 |
| 1252 SkBitmap retval; | 1168 SkBitmap retval; |
| 1253 retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height()); | 1169 retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height()); |
| 1254 retval.eraseColor(0); | 1170 retval.eraseColor(0); |
| 1255 | 1171 |
| 1256 const SkBitmap icon = GdkPixbufToImageSkia(gdk_icon); | 1172 const SkBitmap icon = GdkPixbufToImageSkia(gdk_icon); |
| 1257 g_object_unref(gdk_icon); | 1173 g_object_unref(gdk_icon); |
| 1258 | 1174 |
| 1259 SkCanvas canvas(retval); | 1175 SkCanvas canvas(retval); |
| 1260 | 1176 |
| 1261 if (gtk_state == GTK_STATE_ACTIVE || gtk_state == GTK_STATE_PRELIGHT) { | |
| 1262 SkBitmap border = DrawGtkButtonBorder(gtk_state, | |
| 1263 false, | |
| 1264 false, | |
| 1265 default_bitmap.width(), | |
| 1266 default_bitmap.height()); | |
| 1267 canvas.drawBitmap(border, 0, 0); | |
| 1268 } | |
| 1269 | |
| 1270 canvas.drawBitmap(icon, | 1177 canvas.drawBitmap(icon, |
| 1271 (default_bitmap.width() / 2) - (icon.width() / 2), | 1178 (default_bitmap.width() / 2) - (icon.width() / 2), |
| 1272 (default_bitmap.height() / 2) - (icon.height() / 2)); | 1179 (default_bitmap.height() / 2) - (icon.height() / 2)); |
| 1273 | 1180 |
| 1274 return retval; | 1181 return retval; |
| 1275 } | 1182 } |
| 1276 | 1183 |
| 1277 SkBitmap Gtk2UI::GenerateToolbarBezel(int gtk_state, int sizing_idr) const { | 1184 SkBitmap Gtk2UI::GenerateToolbarBezel(int gtk_state, int sizing_idr) const { |
| 1278 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 1185 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 1279 SkBitmap default_bitmap = | 1186 SkBitmap default_bitmap = |
| 1280 rb.GetImageNamed(sizing_idr).AsBitmap(); | 1187 rb.GetImageNamed(sizing_idr).AsBitmap(); |
| 1281 | 1188 |
| 1282 SkBitmap retval; | 1189 SkBitmap retval; |
| 1283 retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height()); | 1190 retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height()); |
| 1284 retval.eraseColor(0); | 1191 retval.eraseColor(0); |
| 1285 | 1192 |
| 1286 SkCanvas canvas(retval); | 1193 SkCanvas canvas(retval); |
| 1287 SkBitmap border = DrawGtkButtonBorder( | 1194 SkBitmap border = DrawGtkButtonBorder( |
| 1288 gtk_state, | 1195 gtk_state, |
| 1289 false, | |
| 1290 false, | |
| 1291 default_bitmap.width(), | 1196 default_bitmap.width(), |
| 1292 default_bitmap.height()); | 1197 default_bitmap.height()); |
| 1293 canvas.drawBitmap(border, 0, 0); | 1198 canvas.drawBitmap(border, 0, 0); |
| 1294 | 1199 |
| 1295 return retval; | 1200 return retval; |
| 1296 } | 1201 } |
| 1297 | 1202 |
| 1298 void Gtk2UI::GetNormalButtonTintHSL(color_utils::HSL* tint) const { | 1203 void Gtk2UI::GetNormalButtonTintHSL(color_utils::HSL* tint) const { |
| 1299 GtkStyle* window_style = gtk_rc_get_style(fake_window_); | 1204 GtkStyle* window_style = gtk_rc_get_style(fake_window_); |
| 1300 const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED]; | 1205 const GdkColor accent_gdk_color = window_style->bg[GTK_STATE_SELECTED]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1320 void Gtk2UI::GetSelectedEntryForegroundHSL(color_utils::HSL* tint) const { | 1225 void Gtk2UI::GetSelectedEntryForegroundHSL(color_utils::HSL* tint) const { |
| 1321 // The simplest of all the tints. We just use the selected text in the entry | 1226 // The simplest of all the tints. We just use the selected text in the entry |
| 1322 // since the icons tinted this way will only be displayed against | 1227 // since the icons tinted this way will only be displayed against |
| 1323 // base[GTK_STATE_SELECTED]. | 1228 // base[GTK_STATE_SELECTED]. |
| 1324 GtkStyle* style = gtk_rc_get_style(fake_entry_.get()); | 1229 GtkStyle* style = gtk_rc_get_style(fake_entry_.get()); |
| 1325 const GdkColor color = style->text[GTK_STATE_SELECTED]; | 1230 const GdkColor color = style->text[GTK_STATE_SELECTED]; |
| 1326 color_utils::SkColorToHSL(GdkColorToSkColor(color), tint); | 1231 color_utils::SkColorToHSL(GdkColorToSkColor(color), tint); |
| 1327 } | 1232 } |
| 1328 | 1233 |
| 1329 SkBitmap Gtk2UI::DrawGtkButtonBorder(int gtk_state, | 1234 SkBitmap Gtk2UI::DrawGtkButtonBorder(int gtk_state, |
| 1330 bool focused, | |
| 1331 bool call_to_action, | |
| 1332 int width, | 1235 int width, |
| 1333 int height) const { | 1236 int height) const { |
| 1237 SkBitmap border; |
| 1238 border.allocN32Pixels(width, height); |
| 1239 border.eraseColor(0); |
| 1240 |
| 1334 // Create a temporary GTK button to snapshot | 1241 // Create a temporary GTK button to snapshot |
| 1335 GtkWidget* window = gtk_offscreen_window_new(); | 1242 GtkWidget* window = gtk_offscreen_window_new(); |
| 1336 GtkWidget* button = gtk_button_new(); | 1243 GtkWidget* button = gtk_toggle_button_new(); |
| 1244 |
| 1245 if (gtk_state & GTK_STATE_FLAG_ACTIVE) |
| 1246 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), true); |
| 1247 |
| 1337 gtk_widget_set_size_request(button, width, height); | 1248 gtk_widget_set_size_request(button, width, height); |
| 1338 gtk_container_add(GTK_CONTAINER(window), button); | 1249 gtk_container_add(GTK_CONTAINER(window), button); |
| 1339 gtk_widget_realize(window); | 1250 gtk_widget_realize(window); |
| 1340 gtk_widget_realize(button); | 1251 gtk_widget_realize(button); |
| 1341 gtk_widget_show(button); | 1252 gtk_widget_show(button); |
| 1342 gtk_widget_show(window); | 1253 gtk_widget_show(window); |
| 1343 | 1254 |
| 1344 if (call_to_action) | 1255 gtk_widget_set_state_flags(button, (GtkStateFlags)gtk_state, FALSE); |
| 1345 GTK_WIDGET_SET_FLAGS(button, GTK_HAS_DEFAULT); | |
| 1346 | 1256 |
| 1347 if (focused) { | 1257 cairo_surface_t* surface = cairo_image_surface_create_for_data( |
| 1348 // We can't just use gtk_widget_grab_focus() here because that sets | 1258 static_cast<unsigned char*>(border.getAddr(0, 0)), |
| 1349 // gtk_widget_is_focus(), but not gtk_widget_has_focus(), which is what the | 1259 CAIRO_FORMAT_ARGB32, |
| 1350 // GtkButton's paint checks. | 1260 width, height, |
| 1351 GTK_WIDGET_SET_FLAGS(button, GTK_HAS_FOCUS); | 1261 width * 4); |
| 1352 } | 1262 cairo_t* cr = cairo_create(surface); |
| 1353 | 1263 |
| 1354 gtk_widget_set_state(button, static_cast<GtkStateType>(gtk_state)); | 1264 gtk_widget_draw(button, cr); |
| 1355 | 1265 |
| 1356 GdkPixmap* pixmap; | 1266 cairo_destroy(cr); |
| 1357 { | 1267 cairo_surface_destroy(surface); |
| 1358 // http://crbug.com/346740 | |
| 1359 ANNOTATE_SCOPED_MEMORY_LEAK; | |
| 1360 pixmap = gtk_widget_get_snapshot(button, NULL); | |
| 1361 } | |
| 1362 int w, h; | |
| 1363 gdk_drawable_get_size(GDK_DRAWABLE(pixmap), &w, &h); | |
| 1364 DCHECK_EQ(w, width); | |
| 1365 DCHECK_EQ(h, height); | |
| 1366 | |
| 1367 // We render the Pixmap to a Pixbuf. This can be slow, as we're scrapping | |
| 1368 // bits from X. | |
| 1369 GdkColormap* colormap = gdk_drawable_get_colormap(pixmap); | |
| 1370 GdkPixbuf* pixbuf = gdk_pixbuf_get_from_drawable(NULL, | |
| 1371 GDK_DRAWABLE(pixmap), | |
| 1372 colormap, | |
| 1373 0, 0, 0, 0, w, h); | |
| 1374 | |
| 1375 // Finally, we convert our pixbuf into a type we can use. | |
| 1376 SkBitmap border = GdkPixbufToImageSkia(pixbuf); | |
| 1377 g_object_unref(pixbuf); | |
| 1378 g_object_unref(pixmap); | |
| 1379 gtk_widget_destroy(window); | 1268 gtk_widget_destroy(window); |
| 1380 | 1269 |
| 1381 return border; | 1270 return border; |
| 1382 } | 1271 } |
| 1383 | 1272 |
| 1384 void Gtk2UI::ClearAllThemeData() { | 1273 void Gtk2UI::ClearAllThemeData() { |
| 1385 gtk_images_.clear(); | 1274 gtk_images_.clear(); |
| 1386 } | 1275 } |
| 1387 | 1276 |
| 1388 void Gtk2UI::UpdateDefaultFont(const PangoFontDescription* desc) { | 1277 void Gtk2UI::UpdateDefaultFont(const PangoFontDescription* desc) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1437 float scale = GetFontDPI() / GetBaseDPI(); | 1326 float scale = GetFontDPI() / GetBaseDPI(); |
| 1438 // Round to 1 decimal, e.g. to 1.4. | 1327 // Round to 1 decimal, e.g. to 1.4. |
| 1439 return roundf(scale * 10) / 10; | 1328 return roundf(scale * 10) / 10; |
| 1440 } | 1329 } |
| 1441 | 1330 |
| 1442 } // namespace libgtk2ui | 1331 } // namespace libgtk2ui |
| 1443 | 1332 |
| 1444 views::LinuxUI* BuildGtk2UI() { | 1333 views::LinuxUI* BuildGtk2UI() { |
| 1445 return new libgtk2ui::Gtk2UI; | 1334 return new libgtk2ui::Gtk2UI; |
| 1446 } | 1335 } |
| OLD | NEW |