| 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/libgtkui/gtk_ui.h" | 5 #include "chrome/browser/ui/libgtkui/gtk_ui.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #include <pango/pango.h> | 8 #include <pango/pango.h> |
| 9 #include <X11/Xcursor/Xcursor.h> | 9 #include <X11/Xcursor/Xcursor.h> |
| 10 |
| 11 #include <cmath> |
| 10 #include <set> | 12 #include <set> |
| 11 #include <utility> | 13 #include <utility> |
| 12 | 14 |
| 13 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 14 #include "base/debug/leak_annotations.h" | 16 #include "base/debug/leak_annotations.h" |
| 15 #include "base/environment.h" | 17 #include "base/environment.h" |
| 16 #include "base/i18n/rtl.h" | 18 #include "base/i18n/rtl.h" |
| 17 #include "base/logging.h" | 19 #include "base/logging.h" |
| 18 #include "base/macros.h" | 20 #include "base/macros.h" |
| 19 #include "base/nix/mime_util_xdg.h" | 21 #include "base/nix/mime_util_xdg.h" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // linux/debian_wheezy_i386-sysroot/usr/include/linux/stddef.h redefines NULL | 79 // linux/debian_wheezy_i386-sysroot/usr/include/linux/stddef.h redefines NULL |
| 78 // to 0, which breaks -Wsentinel. Get back the normal definition of NULL. | 80 // to 0, which breaks -Wsentinel. Get back the normal definition of NULL. |
| 79 // TODO(thakis): Remove this once we update sysroots. | 81 // TODO(thakis): Remove this once we update sysroots. |
| 80 #define __need_NULL | 82 #define __need_NULL |
| 81 #include <stddef.h> | 83 #include <stddef.h> |
| 82 | 84 |
| 83 namespace libgtkui { | 85 namespace libgtkui { |
| 84 | 86 |
| 85 namespace { | 87 namespace { |
| 86 | 88 |
| 89 const double kDefaultDPI = 96; |
| 90 |
| 87 class GtkButtonImageSource : public gfx::ImageSkiaSource { | 91 class GtkButtonImageSource : public gfx::ImageSkiaSource { |
| 88 public: | 92 public: |
| 89 GtkButtonImageSource(const char* idr_string, gfx::Size size) | 93 GtkButtonImageSource(const char* idr_string, gfx::Size size) |
| 90 : width_(size.width()), height_(size.height()) { | 94 : width_(size.width()), height_(size.height()) { |
| 91 is_blue_ = !!strstr(idr_string, "IDR_BLUE"); | 95 is_blue_ = !!strstr(idr_string, "IDR_BLUE"); |
| 92 focus_ = !!strstr(idr_string, "_FOCUSED_"); | 96 focus_ = !!strstr(idr_string, "_FOCUSED_"); |
| 93 | 97 |
| 94 if (strstr(idr_string, "_DISABLED")) { | 98 if (strstr(idr_string, "_DISABLED")) { |
| 95 state_ = ui::NativeTheme::kDisabled; | 99 state_ = ui::NativeTheme::kDisabled; |
| 96 } else if (strstr(idr_string, "_HOVER")) { | 100 } else if (strstr(idr_string, "_HOVER")) { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 LOG(WARNING) << "Unexpected gtk-xft-rgba \"" << rgba << "\""; | 347 LOG(WARNING) << "Unexpected gtk-xft-rgba \"" << rgba << "\""; |
| 344 params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; | 348 params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; |
| 345 } | 349 } |
| 346 | 350 |
| 347 g_free(hint_style); | 351 g_free(hint_style); |
| 348 g_free(rgba); | 352 g_free(rgba); |
| 349 | 353 |
| 350 return params; | 354 return params; |
| 351 } | 355 } |
| 352 | 356 |
| 353 double GetDPI() { | 357 double GetDpi() { |
| 354 // Linux chrome currently does not support dynamic DPI changes. | 358 if (display::Display::HasForceDeviceScaleFactor()) |
| 355 // Keep using the first value detected. | 359 return display::Display::GetForcedDeviceScaleFactor() * kDefaultDPI; |
| 356 static double dpi = -1.f; | |
| 357 if (dpi < 0) { | |
| 358 const double kDefaultDPI = 96; | |
| 359 | 360 |
| 360 if (display::Display::HasForceDeviceScaleFactor()) { | 361 GtkSettings* gtk_settings = gtk_settings_get_default(); |
| 361 dpi = display::Display::GetForcedDeviceScaleFactor() * kDefaultDPI; | 362 CHECK(gtk_settings); |
| 362 return dpi; | 363 gint gtk_dpi = -1; |
| 363 } | 364 g_object_get(gtk_settings, "gtk-xft-dpi", >k_dpi, NULL); |
| 364 | 365 |
| 365 GtkSettings* gtk_settings = gtk_settings_get_default(); | 366 // GTK multiplies the DPI by 1024 before storing it. |
| 366 CHECK(gtk_settings); | 367 return (gtk_dpi > 0) ? gtk_dpi / 1024.0 : kDefaultDPI; |
| 367 gint gtk_dpi = -1; | |
| 368 g_object_get(gtk_settings, "gtk-xft-dpi", >k_dpi, NULL); | |
| 369 | |
| 370 // GTK multiplies the DPI by 1024 before storing it. | |
| 371 dpi = (gtk_dpi > 0) ? gtk_dpi / 1024.0 : kDefaultDPI; | |
| 372 | |
| 373 // DSF is always >=1.0 on win/cros and lower DSF has never been considered | |
| 374 // nor tested. | |
| 375 dpi = std::max(kDefaultDPI, dpi); | |
| 376 } | |
| 377 return dpi; | |
| 378 } | 368 } |
| 379 | 369 |
| 380 // Queries GTK for its font DPI setting and returns the number of pixels in a | 370 float GetRawDeviceScaleFactor() { |
| 381 // point. | 371 if (display::Display::HasForceDeviceScaleFactor()) |
| 382 double GetPixelsInPoint(float device_scale_factor) { | 372 return display::Display::GetForcedDeviceScaleFactor(); |
| 383 double dpi = GetDPI(); | 373 return GetDpi() / kDefaultDPI; |
| 374 } |
| 375 |
| 376 // Returns the font size for the *raw* device scale factor in points. |
| 377 // The |ui_device_scale_factor| is used to cancel the scale to be applied by UI |
| 378 // and to compensate the scale when the device_scale_factor is floored. |
| 379 double GetFontSizePixelsInPoint(float ui_device_scale_factor) { |
| 380 // There are 72 points in an inch. |
| 381 double point = GetDpi() / 72.0; |
| 384 | 382 |
| 385 // Take device_scale_factor into account — if Chrome already scales the | 383 // Take device_scale_factor into account — if Chrome already scales the |
| 386 // entire UI up by 2x, we should not also scale up. | 384 // entire UI up by 2x, we should not also scale up. |
| 387 dpi /= device_scale_factor; | 385 point /= ui_device_scale_factor; |
| 388 | 386 |
| 389 // There are 72 points in an inch. | 387 // Allow the scale lower than 1.0 only for fonts. Don't always use |
| 390 return dpi / 72.0; | 388 // the raw value however, because the 1.0~1.3 is rounded to 1.0. |
| 389 float raw_scale = GetRawDeviceScaleFactor(); |
| 390 if (raw_scale < 1.0f) |
| 391 return point * raw_scale / ui_device_scale_factor; |
| 392 return point; |
| 391 } | 393 } |
| 392 | 394 |
| 393 views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { | 395 views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { |
| 394 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 396 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 395 switch (base::nix::GetDesktopEnvironment(env.get())) { | 397 switch (base::nix::GetDesktopEnvironment(env.get())) { |
| 396 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | 398 case base::nix::DESKTOP_ENVIRONMENT_KDE4: |
| 397 case base::nix::DESKTOP_ENVIRONMENT_KDE5: | 399 case base::nix::DESKTOP_ENVIRONMENT_KDE5: |
| 398 // Starting with KDE 4.4, windows' titlebars can be dragged with the | 400 // Starting with KDE 4.4, windows' titlebars can be dragged with the |
| 399 // middle mouse button to create tab groups. We don't support that in | 401 // middle mouse button to create tab groups. We don't support that in |
| 400 // Chrome, but at least avoid lowering windows in response to middle | 402 // Chrome, but at least avoid lowering windows in response to middle |
| 401 // clicks to avoid surprising users who expect the KDE behavior. | 403 // clicks to avoid surprising users who expect the KDE behavior. |
| 402 return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; | 404 return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; |
| 403 default: | 405 default: |
| 404 return views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER; | 406 return views::LinuxUI::MIDDLE_CLICK_ACTION_LOWER; |
| 405 } | 407 } |
| 406 } | 408 } |
| 407 | 409 |
| 408 } // namespace | 410 } // namespace |
| 409 | 411 |
| 410 Gtk2UI::Gtk2UI() | 412 Gtk2UI::Gtk2UI() : middle_click_action_(GetDefaultMiddleClickAction()) { |
| 411 : default_font_size_pixels_(0), | |
| 412 default_font_style_(gfx::Font::NORMAL), | |
| 413 default_font_weight_(gfx::Font::Weight::NORMAL), | |
| 414 middle_click_action_(GetDefaultMiddleClickAction()), | |
| 415 device_scale_factor_(1.0) { | |
| 416 GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); | 413 GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); |
| 417 } | 414 } |
| 418 | 415 |
| 419 Gtk2UI::~Gtk2UI() {} | 416 Gtk2UI::~Gtk2UI() {} |
| 420 | 417 |
| 421 void OnThemeChanged(GObject* obj, GParamSpec* param, Gtk2UI* gtkui) { | 418 void OnThemeChanged(GObject* obj, GParamSpec* param, Gtk2UI* gtkui) { |
| 422 gtkui->ResetStyle(); | 419 gtkui->ResetStyle(); |
| 423 } | 420 } |
| 424 | 421 |
| 425 void Gtk2UI::Initialize() { | 422 void Gtk2UI::Initialize() { |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 colors_[ThemeProperties::COLOR_TOOLBAR] = toolbar_color; | 800 colors_[ThemeProperties::COLOR_TOOLBAR] = toolbar_color; |
| 804 | 801 |
| 805 colors_[ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON] = | 802 colors_[ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON] = |
| 806 color_utils::DeriveDefaultIconColor(label_color); | 803 color_utils::DeriveDefaultIconColor(label_color); |
| 807 | 804 |
| 808 colors_[ThemeProperties::COLOR_TAB_TEXT] = label_color; | 805 colors_[ThemeProperties::COLOR_TAB_TEXT] = label_color; |
| 809 colors_[ThemeProperties::COLOR_BOOKMARK_TEXT] = label_color; | 806 colors_[ThemeProperties::COLOR_BOOKMARK_TEXT] = label_color; |
| 810 colors_[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT] = | 807 colors_[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT] = |
| 811 color_utils::BlendTowardOppositeLuma(label_color, 50); | 808 color_utils::BlendTowardOppositeLuma(label_color, 50); |
| 812 | 809 |
| 813 UpdateDefaultFont(); | 810 UpdateDeviceScaleFactor(); |
| 814 | 811 |
| 815 // Build the various icon tints. | 812 // Build the various icon tints. |
| 816 GetNormalButtonTintHSL(&button_tint_); | 813 GetNormalButtonTintHSL(&button_tint_); |
| 817 GetNormalEntryForegroundHSL(&entry_tint_); | 814 GetNormalEntryForegroundHSL(&entry_tint_); |
| 818 GetSelectedEntryForegroundHSL(&selected_entry_tint_); | 815 GetSelectedEntryForegroundHSL(&selected_entry_tint_); |
| 819 | 816 |
| 820 // We pick the text and background colors for the NTP out of the colors for a | 817 // We pick the text and background colors for the NTP out of the colors for a |
| 821 // GtkEntry. We do this because GtkEntries background color is never the same | 818 // GtkEntry. We do this because GtkEntries background color is never the same |
| 822 // as |toolbar_color|, is usually a white, and when it isn't a white, | 819 // as |toolbar_color|, is usually a white, and when it isn't a white, |
| 823 // provides sufficient contrast to |toolbar_color|. Try this out with | 820 // provides sufficient contrast to |toolbar_color|. Try this out with |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 // PANGO_SCALE Pango units in a device unit (pixel). | 1020 // PANGO_SCALE Pango units in a device unit (pixel). |
| 1024 const int size_pixels = pango_font_description_get_size(desc) / PANGO_SCALE; | 1021 const int size_pixels = pango_font_description_get_size(desc) / PANGO_SCALE; |
| 1025 default_font_size_pixels_ = size_pixels; | 1022 default_font_size_pixels_ = size_pixels; |
| 1026 query.pixel_size = size_pixels; | 1023 query.pixel_size = size_pixels; |
| 1027 } else { | 1024 } else { |
| 1028 // Non-absolute sizes are in points (again scaled by PANGO_SIZE). | 1025 // Non-absolute sizes are in points (again scaled by PANGO_SIZE). |
| 1029 // Round the value when converting to pixels to match GTK's logic. | 1026 // Round the value when converting to pixels to match GTK's logic. |
| 1030 const double size_points = pango_font_description_get_size(desc) / | 1027 const double size_points = pango_font_description_get_size(desc) / |
| 1031 static_cast<double>(PANGO_SCALE); | 1028 static_cast<double>(PANGO_SCALE); |
| 1032 default_font_size_pixels_ = static_cast<int>( | 1029 default_font_size_pixels_ = static_cast<int>( |
| 1033 GetPixelsInPoint(device_scale_factor_) * size_points + 0.5); | 1030 GetFontSizePixelsInPoint(GetDeviceScaleFactor()) * size_points); |
| 1034 query.point_size = static_cast<int>(size_points); | 1031 query.point_size = static_cast<int>(size_points); |
| 1035 } | 1032 } |
| 1036 | 1033 |
| 1037 query.style = gfx::Font::NORMAL; | 1034 query.style = gfx::Font::NORMAL; |
| 1038 query.weight = | 1035 query.weight = |
| 1039 static_cast<gfx::Font::Weight>(pango_font_description_get_weight(desc)); | 1036 static_cast<gfx::Font::Weight>(pango_font_description_get_weight(desc)); |
| 1040 // TODO(davemoore): What about PANGO_STYLE_OBLIQUE? | 1037 // TODO(davemoore): What about PANGO_STYLE_OBLIQUE? |
| 1041 if (pango_font_description_get_style(desc) == PANGO_STYLE_ITALIC) | 1038 if (pango_font_description_get_style(desc) == PANGO_STYLE_ITALIC) |
| 1042 query.style |= gfx::Font::ITALIC; | 1039 query.style |= gfx::Font::ITALIC; |
| 1043 | 1040 |
| 1044 default_font_render_params_ = | 1041 default_font_render_params_ = |
| 1045 gfx::GetFontRenderParams(query, &default_font_family_); | 1042 gfx::GetFontRenderParams(query, &default_font_family_); |
| 1046 default_font_style_ = query.style; | 1043 default_font_style_ = query.style; |
| 1047 } | 1044 } |
| 1048 | 1045 |
| 1049 void Gtk2UI::ResetStyle() { | 1046 void Gtk2UI::ResetStyle() { |
| 1050 LoadGtkValues(); | 1047 LoadGtkValues(); |
| 1051 NativeThemeGtk2::instance()->NotifyObservers(); | 1048 NativeThemeGtk2::instance()->NotifyObservers(); |
| 1052 } | 1049 } |
| 1053 | 1050 |
| 1054 void Gtk2UI::UpdateDeviceScaleFactor(float device_scale_factor) { | 1051 void Gtk2UI::UpdateDeviceScaleFactor() { |
| 1055 device_scale_factor_ = device_scale_factor; | 1052 // Note: Linux chrome currently does not support dynamic DPI |
| 1053 // changes. This is to allow flags to override the DPI settings |
| 1054 // during startup. |
| 1055 float scale = GetRawDeviceScaleFactor(); |
| 1056 |
| 1057 // Blacklist scaling factors <130% (crbug.com/484400) and round |
| 1058 // to 1 decimal to prevent rendering problems (crbug.com/485183). |
| 1059 device_scale_factor_ = scale < 1.3f ? 1.0f : roundf(scale * 10) / 10; |
| 1056 UpdateDefaultFont(); | 1060 UpdateDefaultFont(); |
| 1057 } | 1061 } |
| 1058 | 1062 |
| 1059 float Gtk2UI::GetDeviceScaleFactor() const { | 1063 float Gtk2UI::GetDeviceScaleFactor() const { |
| 1060 if (display::Display::HasForceDeviceScaleFactor()) | 1064 return device_scale_factor_; |
| 1061 return display::Display::GetForcedDeviceScaleFactor(); | |
| 1062 const int kCSSDefaultDPI = 96; | |
| 1063 const float scale = GetDPI() / kCSSDefaultDPI; | |
| 1064 | |
| 1065 // Blacklist scaling factors <130% (crbug.com/484400) and round | |
| 1066 // to 1 decimal to prevent rendering problems (crbug.com/485183). | |
| 1067 return scale < 1.3f ? 1.0f : roundf(scale * 10) / 10; | |
| 1068 } | 1065 } |
| 1069 | 1066 |
| 1070 } // namespace libgtkui | 1067 } // namespace libgtkui |
| 1071 | 1068 |
| 1072 views::LinuxUI* BuildGtk2UI() { | 1069 views::LinuxUI* BuildGtk2UI() { |
| 1073 return new libgtkui::Gtk2UI; | 1070 return new libgtkui::Gtk2UI; |
| 1074 } | 1071 } |
| OLD | NEW |