#include <set>
+#include <pango/pango.h>
+
#include "base/command_line.h"
#include "base/debug/leak_annotations.h"
#include "base/environment.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/nix/mime_util_xdg.h"
+#include "base/nix/xdg_util.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h"
#include "chrome/browser/ui/libgtk2ui/unity_service.h"
#include "chrome/browser/ui/libgtk2ui/x11_input_method_context_impl_gtk2.h"
+#include "grit/components_scaled_resources.h"
#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
#include "printing/printing_context_linux.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/pango_util.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/skia_util.h"
+#include "ui/resources/grit/ui_resources.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/linux_ui/window_button_order_observer.h"
// - Render and inject the omnibox background.
// - Make sure to test with a light on dark theme, too.
+// Work around a header bug:
+// linux/debian_wheezy_i386-sysroot/usr/include/linux/stddef.h redefines NULL
+// to 0, which breaks -Wsentinel. Get back the normal definition of NULL.
+// TODO(thakis): Remove this once we update sysroots.
+#define __need_NULL
+#include <stddef.h>
+
+namespace libgtk2ui {
+
namespace {
struct GObjectDeleter {
} const kGtkIcons[] = {
{ IDR_BACK, GTK_STOCK_GO_BACK, GTK_STATE_NORMAL },
{ IDR_BACK_D, GTK_STOCK_GO_BACK, GTK_STATE_INSENSITIVE },
- { IDR_BACK_H, GTK_STOCK_GO_BACK, GTK_STATE_PRELIGHT },
- { IDR_BACK_P, GTK_STOCK_GO_BACK, GTK_STATE_ACTIVE },
{ IDR_FORWARD, GTK_STOCK_GO_FORWARD, GTK_STATE_NORMAL },
{ IDR_FORWARD_D, GTK_STOCK_GO_FORWARD, GTK_STATE_INSENSITIVE },
- { IDR_FORWARD_H, GTK_STOCK_GO_FORWARD, GTK_STATE_PRELIGHT },
- { IDR_FORWARD_P, GTK_STOCK_GO_FORWARD, GTK_STATE_ACTIVE },
{ IDR_HOME, GTK_STOCK_HOME, GTK_STATE_NORMAL },
- { IDR_HOME_H, GTK_STOCK_HOME, GTK_STATE_PRELIGHT },
- { IDR_HOME_P, GTK_STOCK_HOME, GTK_STATE_ACTIVE },
{ IDR_RELOAD, GTK_STOCK_REFRESH, GTK_STATE_NORMAL },
{ IDR_RELOAD_D, GTK_STOCK_REFRESH, GTK_STATE_INSENSITIVE },
- { IDR_RELOAD_H, GTK_STOCK_REFRESH, GTK_STATE_PRELIGHT },
- { IDR_RELOAD_P, GTK_STOCK_REFRESH, GTK_STATE_ACTIVE },
{ IDR_STOP, GTK_STOCK_STOP, GTK_STATE_NORMAL },
{ IDR_STOP_D, GTK_STOCK_STOP, GTK_STATE_INSENSITIVE },
- { IDR_STOP_H, GTK_STOCK_STOP, GTK_STATE_PRELIGHT },
- { IDR_STOP_P, GTK_STOCK_STOP, GTK_STATE_ACTIVE },
};
// The image resources that will be tinted by the 'button' tint value.
const int kOtherToolbarButtonIDs[] = {
IDR_TOOLBAR_BEZEL_HOVER,
IDR_TOOLBAR_BEZEL_PRESSED,
- IDR_BROWSER_ACTION_H,
- IDR_BROWSER_ACTION_P,
IDR_BROWSER_ACTIONS_OVERFLOW,
- IDR_BROWSER_ACTIONS_OVERFLOW_H,
- IDR_BROWSER_ACTIONS_OVERFLOW_P,
IDR_THROBBER,
IDR_THROBBER_WAITING,
IDR_THROBBER_LIGHT,
const GdkColor& text_color,
const GdkColor& background_color,
color_utils::HSL* tint) {
- SkColor accent_color = libgtk2ui::GdkColorToSkColor(accent_gdk_color);
+ SkColor accent_color = GdkColorToSkColor(accent_gdk_color);
color_utils::HSL accent_tint;
color_utils::SkColorToHSL(accent_color, &accent_tint);
color_utils::HSL text_tint;
- color_utils::SkColorToHSL(libgtk2ui::GdkColorToSkColor(text_color),
+ color_utils::SkColorToHSL(GdkColorToSkColor(text_color),
&text_tint);
color_utils::HSL background_tint;
- color_utils::SkColorToHSL(libgtk2ui::GdkColorToSkColor(background_color),
+ color_utils::SkColorToHSL(GdkColorToSkColor(background_color),
&background_tint);
// If the accent color is gray, then our normal HSL tomfoolery will bring out
// Applies an HSL shift to a GdkColor (instead of an SkColor)
void GdkColorHSLShift(const color_utils::HSL& shift, GdkColor* frame_color) {
SkColor shifted = color_utils::HSLShift(
- libgtk2ui::GdkColorToSkColor(*frame_color), shift);
+ GdkColorToSkColor(*frame_color), shift);
frame_color->pixel = 0;
frame_color->red = SkColorGetR(shifted) * kSkiaToGDKMultiplier;
}
}
-} // namespace
+// Returns a FontRenderParams corresponding to GTK's configuration.
+gfx::FontRenderParams GetGtkFontRenderParams() {
+ GtkSettings* gtk_settings = gtk_settings_get_default();
+ CHECK(gtk_settings);
+ gint antialias = 0;
+ gint hinting = 0;
+ gchar* hint_style = NULL;
+ gchar* rgba = NULL;
+ g_object_get(gtk_settings,
+ "gtk-xft-antialias", &antialias,
+ "gtk-xft-hinting", &hinting,
+ "gtk-xft-hintstyle", &hint_style,
+ "gtk-xft-rgba", &rgba,
+ NULL);
-namespace libgtk2ui {
+ gfx::FontRenderParams params;
+ params.antialiasing = antialias != 0;
+
+ if (hinting == 0 || !hint_style || strcmp(hint_style, "hintnone") == 0) {
+ params.hinting = gfx::FontRenderParams::HINTING_NONE;
+ } else if (strcmp(hint_style, "hintslight") == 0) {
+ params.hinting = gfx::FontRenderParams::HINTING_SLIGHT;
+ } else if (strcmp(hint_style, "hintmedium") == 0) {
+ params.hinting = gfx::FontRenderParams::HINTING_MEDIUM;
+ } else if (strcmp(hint_style, "hintfull") == 0) {
+ params.hinting = gfx::FontRenderParams::HINTING_FULL;
+ } else {
+ LOG(WARNING) << "Unexpected gtk-xft-hintstyle \"" << hint_style << "\"";
+ params.hinting = gfx::FontRenderParams::HINTING_NONE;
+ }
+
+ if (!rgba || strcmp(rgba, "none") == 0) {
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE;
+ } else if (strcmp(rgba, "rgb") == 0) {
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB;
+ } else if (strcmp(rgba, "bgr") == 0) {
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR;
+ } else if (strcmp(rgba, "vrgb") == 0) {
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB;
+ } else if (strcmp(rgba, "vbgr") == 0) {
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR;
+ } else {
+ LOG(WARNING) << "Unexpected gtk-xft-rgba \"" << rgba << "\"";
+ params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE;
+ }
+
+ g_free(hint_style);
+ g_free(rgba);
+
+ return params;
+}
+
+views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ switch (base::nix::GetDesktopEnvironment(env.get())) {
+ case base::nix::DESKTOP_ENVIRONMENT_KDE4:
+ // Starting with KDE 4.4, windows' titlebars can be dragged with the
+ // middle mouse button to create tab groups. We don't support that in
+ // Chrome, but at least avoid lowering windows in response to middle
+ // clicks to avoid surprising users who expect the KDE behavior.
+ return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE;
+ default:
+ return views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER;
+ }
+}
+
+} // namespace
-Gtk2UI::Gtk2UI() : middle_click_action_(MIDDLE_CLICK_ACTION_LOWER) {
+Gtk2UI::Gtk2UI() : middle_click_action_(GetDefaultMiddleClickAction()) {
GtkInitFromCommandLine(*CommandLine::ForCurrentProcess());
}
views::LabelButton* owning_button,
scoped_ptr<views::LabelButtonBorder> border) {
if (owning_button->GetNativeTheme() != NativeThemeGtk2::instance())
- return border.PassAs<views::Border>();
+ return border.Pass();
- return scoped_ptr<views::Border>(
- new Gtk2Border(this, owning_button, border.Pass()));
+ return make_scoped_ptr(new Gtk2Border(this, owning_button, border.Pass()));
}
void Gtk2UI::AddWindowButtonOrderObserver(
new X11InputMethodContextImplGtk2(delegate));
}
-bool Gtk2UI::UseAntialiasing() const {
- GtkSettings* gtk_settings = gtk_settings_get_default();
- CHECK(gtk_settings);
- gint gtk_antialias = 0;
- g_object_get(gtk_settings,
- "gtk-xft-antialias", >k_antialias,
- NULL);
- return gtk_antialias != 0;
+gfx::FontRenderParams Gtk2UI::GetDefaultFontRenderParams() const {
+ static gfx::FontRenderParams params = GetGtkFontRenderParams();
+ return params;
}
-gfx::FontRenderParams::Hinting Gtk2UI::GetHintingStyle() const {
- GtkSettings* gtk_settings = gtk_settings_get_default();
- CHECK(gtk_settings);
- gfx::FontRenderParams::Hinting hinting =
- gfx::FontRenderParams::HINTING_SLIGHT;
- gint gtk_hinting = 0;
- gchar* gtk_hint_style = NULL;
- g_object_get(gtk_settings,
- "gtk-xft-hinting", >k_hinting,
- "gtk-xft-hintstyle", >k_hint_style,
- NULL);
-
- if (gtk_hint_style) {
- if (gtk_hinting == 0 || strcmp(gtk_hint_style, "hintnone") == 0)
- hinting = gfx::FontRenderParams::HINTING_NONE;
- else if (strcmp(gtk_hint_style, "hintslight") == 0)
- hinting = gfx::FontRenderParams::HINTING_SLIGHT;
- else if (strcmp(gtk_hint_style, "hintmedium") == 0)
- hinting = gfx::FontRenderParams::HINTING_MEDIUM;
- else if (strcmp(gtk_hint_style, "hintfull") == 0)
- hinting = gfx::FontRenderParams::HINTING_FULL;
-
- g_free(gtk_hint_style);
- }
-
- return hinting;
+scoped_ptr<gfx::ScopedPangoFontDescription>
+Gtk2UI::GetDefaultPangoFontDescription() const {
+ return scoped_ptr<gfx::ScopedPangoFontDescription>(
+ new gfx::ScopedPangoFontDescription(
+ pango_font_description_copy(default_font_description_->get())));
}
-gfx::FontRenderParams::SubpixelRendering
-Gtk2UI::GetSubpixelRenderingStyle() const {
+double Gtk2UI::GetFontDPI() const {
GtkSettings* gtk_settings = gtk_settings_get_default();
CHECK(gtk_settings);
- gfx::FontRenderParams::SubpixelRendering subpixel_rendering =
- gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE;
- gchar* gtk_rgba = NULL;
- g_object_get(gtk_settings,
- "gtk-xft-rgba", >k_rgba,
- NULL);
+ gint dpi = -1;
+ g_object_get(gtk_settings, "gtk-xft-dpi", &dpi, NULL);
- if (gtk_rgba) {
- if (strcmp(gtk_rgba, "none") == 0)
- subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE;
- else if (strcmp(gtk_rgba, "rgb") == 0)
- subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB;
- else if (strcmp(gtk_rgba, "bgr") == 0)
- subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR;
- else if (strcmp(gtk_rgba, "vrgb") == 0)
- subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB;
- else if (strcmp(gtk_rgba, "vbgr") == 0)
- subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR;
-
- g_free(gtk_rgba);
- }
-
- return subpixel_rendering;
-}
-
-std::string Gtk2UI::GetDefaultFontName() const {
- GtkSettings* gtk_settings = gtk_settings_get_default();
- CHECK(gtk_settings);
-
- std::string out_font_name = "sans 10";
- gchar* font_name = NULL;
- g_object_get(gtk_settings, "gtk-font-name", &font_name, NULL);
-
- if (font_name) {
- out_font_name = std::string(font_name);
- g_free(font_name);
- }
-
- return out_font_name;
+ // GTK multiplies the DPI by 1024 before storing it.
+ return (dpi > 0) ? dpi / 1024.0 : dpi;
}
ui::SelectFileDialog* Gtk2UI::CreateSelectFileDialog(
SetThemeColorFromGtk(ThemeProperties::COLOR_BOOKMARK_TEXT, &label_color);
SetThemeColorFromGtk(ThemeProperties::COLOR_STATUS_BAR_TEXT, &label_color);
+ default_font_description_.reset(new gfx::ScopedPangoFontDescription(
+ pango_font_description_copy(label_style->font_desc)));
+
// Build the various icon tints.
GetNormalButtonTintHSL(&button_tint_);
GetNormalEntryForegroundHSL(&entry_tint_);
GtkStyle* style = gtk_rc_get_style(fake_window_);
GdkColor* color = &style->bg[GTK_STATE_NORMAL];
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- kToolbarImageWidth, kToolbarImageHeight);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(kToolbarImageWidth, kToolbarImageHeight);
bitmap.eraseARGB(0xff, color->red >> 8, color->green >> 8,
color->blue >> 8);
return bitmap;
// In GTK mode, we need to manually render several icons.
case IDR_BACK:
case IDR_BACK_D:
- case IDR_BACK_H:
- case IDR_BACK_P:
case IDR_FORWARD:
case IDR_FORWARD_D:
- case IDR_FORWARD_H:
- case IDR_FORWARD_P:
case IDR_HOME:
- case IDR_HOME_H:
- case IDR_HOME_P:
case IDR_RELOAD:
case IDR_RELOAD_D:
- case IDR_RELOAD_H:
- case IDR_RELOAD_P:
case IDR_STOP:
- case IDR_STOP_D:
- case IDR_STOP_H:
- case IDR_STOP_P: {
+ case IDR_STOP_D: {
return GenerateGTKIcon(id);
}
case IDR_TOOLBAR_BEZEL_HOVER:
return GenerateToolbarBezel(GTK_STATE_PRELIGHT, IDR_TOOLBAR_BEZEL_HOVER);
case IDR_TOOLBAR_BEZEL_PRESSED:
return GenerateToolbarBezel(GTK_STATE_ACTIVE, IDR_TOOLBAR_BEZEL_PRESSED);
- case IDR_BROWSER_ACTION_H:
- return GenerateToolbarBezel(GTK_STATE_PRELIGHT, IDR_BROWSER_ACTION_H);
- case IDR_BROWSER_ACTION_P:
- return GenerateToolbarBezel(GTK_STATE_ACTIVE, IDR_BROWSER_ACTION_P);
default: {
return GenerateTintedIcon(id, button_tint_);
}
}
SkBitmap retval;
- retval.setConfig(SkBitmap::kARGB_8888_Config,
- default_bitmap.width(),
- default_bitmap.height());
- retval.allocPixels();
+ retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height());
retval.eraseColor(0);
const SkBitmap icon = GdkPixbufToImageSkia(gdk_icon);
if (gtk_state == GTK_STATE_ACTIVE || gtk_state == GTK_STATE_PRELIGHT) {
SkBitmap border = DrawGtkButtonBorder(gtk_state,
false,
+ false,
default_bitmap.width(),
default_bitmap.height());
canvas.drawBitmap(border, 0, 0);
rb.GetImageNamed(sizing_idr).AsBitmap();
SkBitmap retval;
- retval.setConfig(SkBitmap::kARGB_8888_Config,
- default_bitmap.width(),
- default_bitmap.height());
- retval.allocPixels();
+ retval.allocN32Pixels(default_bitmap.width(), default_bitmap.height());
retval.eraseColor(0);
SkCanvas canvas(retval);
SkBitmap border = DrawGtkButtonBorder(
gtk_state,
false,
+ false,
default_bitmap.width(),
default_bitmap.height());
canvas.drawBitmap(border, 0, 0);
SkBitmap Gtk2UI::DrawGtkButtonBorder(int gtk_state,
bool focused,
+ bool call_to_action,
int width,
int height) const {
// Create a temporary GTK button to snapshot
gtk_widget_show(button);
gtk_widget_show(window);
+ if (call_to_action)
+ GTK_WIDGET_SET_FLAGS(button, GTK_HAS_DEFAULT);
+
if (focused) {
// We can't just use gtk_widget_grab_focus() here because that sets
// gtk_widget_is_focus(), but not gtk_widget_has_focus(), which is what the