| 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 <X11/Xcursor/Xcursor.h> | 7 #include <X11/Xcursor/Xcursor.h> |
| 8 #include <dlfcn.h> | 8 #include <dlfcn.h> |
| 9 #include <math.h> | 9 #include <math.h> |
| 10 #include <pango/pango.h> | 10 #include <pango/pango.h> |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #include "ui/gfx/geometry/size.h" | 51 #include "ui/gfx/geometry/size.h" |
| 52 #include "ui/gfx/image/image.h" | 52 #include "ui/gfx/image/image.h" |
| 53 #include "ui/gfx/image/image_skia_source.h" | 53 #include "ui/gfx/image/image_skia_source.h" |
| 54 #include "ui/gfx/skbitmap_operations.h" | 54 #include "ui/gfx/skbitmap_operations.h" |
| 55 #include "ui/gfx/skia_util.h" | 55 #include "ui/gfx/skia_util.h" |
| 56 #include "ui/gfx/x/x11_types.h" | 56 #include "ui/gfx/x/x11_types.h" |
| 57 #include "ui/native_theme/native_theme.h" | 57 #include "ui/native_theme/native_theme.h" |
| 58 #include "ui/views/controls/button/blue_button.h" | 58 #include "ui/views/controls/button/blue_button.h" |
| 59 #include "ui/views/controls/button/label_button.h" | 59 #include "ui/views/controls/button/label_button.h" |
| 60 #include "ui/views/controls/button/label_button_border.h" | 60 #include "ui/views/controls/button/label_button_border.h" |
| 61 #include "ui/views/linux_ui/device_scale_factor_observer.h" |
| 61 #include "ui/views/linux_ui/window_button_order_observer.h" | 62 #include "ui/views/linux_ui/window_button_order_observer.h" |
| 62 #include "ui/views/resources/grit/views_resources.h" | 63 #include "ui/views/resources/grit/views_resources.h" |
| 63 | 64 |
| 64 #if GTK_MAJOR_VERSION == 2 | 65 #if GTK_MAJOR_VERSION == 2 |
| 65 #include "chrome/browser/ui/libgtkui/native_theme_gtk2.h" // nogncheck | 66 #include "chrome/browser/ui/libgtkui/native_theme_gtk2.h" // nogncheck |
| 66 #elif GTK_MAJOR_VERSION == 3 | 67 #elif GTK_MAJOR_VERSION == 3 |
| 67 #include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" // nogncheck | 68 #include "chrome/browser/ui/libgtkui/native_theme_gtk3.h" // nogncheck |
| 68 #endif | 69 #endif |
| 69 | 70 |
| 70 #if BUILDFLAG(ENABLE_BASIC_PRINTING) | 71 #if BUILDFLAG(ENABLE_BASIC_PRINTING) |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 LOG(WARNING) << "Unexpected gtk-xft-rgba \"" << rgba << "\""; | 307 LOG(WARNING) << "Unexpected gtk-xft-rgba \"" << rgba << "\""; |
| 307 params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; | 308 params.subpixel_rendering = gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; |
| 308 } | 309 } |
| 309 | 310 |
| 310 g_free(hint_style); | 311 g_free(hint_style); |
| 311 g_free(rgba); | 312 g_free(rgba); |
| 312 | 313 |
| 313 return params; | 314 return params; |
| 314 } | 315 } |
| 315 | 316 |
| 316 float GetRawDeviceScaleFactor() { | |
| 317 if (display::Display::HasForceDeviceScaleFactor()) | |
| 318 return display::Display::GetForcedDeviceScaleFactor(); | |
| 319 | |
| 320 GdkScreen* screen = gdk_screen_get_default(); | |
| 321 gint scale = gdk_screen_get_monitor_scale_factor( | |
| 322 screen, gdk_screen_get_primary_monitor(screen)); | |
| 323 gdouble resolution = gdk_screen_get_resolution(screen); | |
| 324 const float scale_factor = | |
| 325 resolution <= 0 ? scale : resolution * scale / kDefaultDPI; | |
| 326 // Blacklist scaling factors <120% (crbug.com/484400) and round | |
| 327 // to 1 decimal to prevent rendering problems (crbug.com/485183). | |
| 328 return scale_factor < 1.2f ? 1.0f : roundf(scale_factor * 10) / 10; | |
| 329 } | |
| 330 | |
| 331 views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { | 317 views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { |
| 332 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 318 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 333 switch (base::nix::GetDesktopEnvironment(env.get())) { | 319 switch (base::nix::GetDesktopEnvironment(env.get())) { |
| 334 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | 320 case base::nix::DESKTOP_ENVIRONMENT_KDE4: |
| 335 case base::nix::DESKTOP_ENVIRONMENT_KDE5: | 321 case base::nix::DESKTOP_ENVIRONMENT_KDE5: |
| 336 // Starting with KDE 4.4, windows' titlebars can be dragged with the | 322 // Starting with KDE 4.4, windows' titlebars can be dragged with the |
| 337 // middle mouse button to create tab groups. We don't support that in | 323 // middle mouse button to create tab groups. We don't support that in |
| 338 // Chrome, but at least avoid lowering windows in response to middle | 324 // Chrome, but at least avoid lowering windows in response to middle |
| 339 // clicks to avoid surprising users who expect the KDE behavior. | 325 // clicks to avoid surprising users who expect the KDE behavior. |
| 340 return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; | 326 return views::LinuxUI::MIDDLE_CLICK_ACTION_NONE; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 dlsym(GetGdkSharedLibrary(), "gdk_set_allowed_backends")); | 395 dlsym(GetGdkSharedLibrary(), "gdk_set_allowed_backends")); |
| 410 if (GtkVersionCheck(3, 10)) | 396 if (GtkVersionCheck(3, 10)) |
| 411 DCHECK(_gdk_set_allowed_backends); | 397 DCHECK(_gdk_set_allowed_backends); |
| 412 if (_gdk_set_allowed_backends) | 398 if (_gdk_set_allowed_backends) |
| 413 _gdk_set_allowed_backends("x11"); | 399 _gdk_set_allowed_backends("x11"); |
| 414 #endif | 400 #endif |
| 415 GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); | 401 GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); |
| 416 #if GTK_MAJOR_VERSION == 2 | 402 #if GTK_MAJOR_VERSION == 2 |
| 417 native_theme_ = NativeThemeGtk2::instance(); | 403 native_theme_ = NativeThemeGtk2::instance(); |
| 418 fake_window_ = chrome_gtk_frame_new(); | 404 fake_window_ = chrome_gtk_frame_new(); |
| 419 gtk_widget_realize(fake_window_); // Is this necessary? | |
| 420 #elif GTK_MAJOR_VERSION == 3 | 405 #elif GTK_MAJOR_VERSION == 3 |
| 421 native_theme_ = NativeThemeGtk3::instance(); | 406 native_theme_ = NativeThemeGtk3::instance(); |
| 422 (void)fake_window_; // Silence the unused warning. | 407 fake_window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 423 #else | 408 #else |
| 424 #error "Unsupported GTK version" | 409 #error "Unsupported GTK version" |
| 425 #endif | 410 #endif |
| 411 gtk_widget_realize(fake_window_); |
| 426 } | 412 } |
| 427 | 413 |
| 428 GtkUi::~GtkUi() { | 414 GtkUi::~GtkUi() { |
| 429 #if GTK_MAJOR_VERSION == 2 | |
| 430 gtk_widget_destroy(fake_window_); | 415 gtk_widget_destroy(fake_window_); |
| 431 #endif | |
| 432 } | 416 } |
| 433 | 417 |
| 434 void OnThemeChanged(GObject* obj, GParamSpec* param, GtkUi* gtkui) { | 418 void OnThemeChanged(GObject* obj, GParamSpec* param, GtkUi* gtkui) { |
| 435 gtkui->ResetStyle(); | 419 gtkui->ResetStyle(); |
| 436 } | 420 } |
| 437 | 421 |
| 438 void GtkUi::Initialize() { | 422 void GtkUi::Initialize() { |
| 439 GtkSettings* settings = gtk_settings_get_default(); | 423 GtkSettings* settings = gtk_settings_get_default(); |
| 440 g_signal_connect_after(settings, "notify::gtk-theme-name", | 424 g_signal_connect_after(settings, "notify::gtk-theme-name", |
| 441 G_CALLBACK(OnThemeChanged), this); | 425 G_CALLBACK(OnThemeChanged), this); |
| 442 g_signal_connect_after(settings, "notify::gtk-icon-theme-name", | 426 g_signal_connect_after(settings, "notify::gtk-icon-theme-name", |
| 443 G_CALLBACK(OnThemeChanged), this); | 427 G_CALLBACK(OnThemeChanged), this); |
| 444 | 428 |
| 429 GdkScreen* screen = gdk_screen_get_default(); |
| 430 // Listen for DPI changes. |
| 431 g_signal_connect_after(screen, "notify::resolution", |
| 432 G_CALLBACK(OnDeviceScaleFactorMaybeChangedThunk), |
| 433 this); |
| 434 // Listen for scale factor changes. We would prefer to listen on |
| 435 // |screen|, but there is no scale-factor property, so use an |
| 436 // unmapped window instead. |
| 437 g_signal_connect(fake_window_, "notify::scale-factor", |
| 438 G_CALLBACK(OnDeviceScaleFactorMaybeChangedThunk), this); |
| 439 |
| 445 LoadGtkValues(); | 440 LoadGtkValues(); |
| 446 | 441 |
| 447 #if BUILDFLAG(ENABLE_BASIC_PRINTING) | 442 #if BUILDFLAG(ENABLE_BASIC_PRINTING) |
| 448 printing::PrintingContextLinux::SetCreatePrintDialogFunction( | 443 printing::PrintingContextLinux::SetCreatePrintDialogFunction( |
| 449 &PrintDialogGtk2::CreatePrintDialog); | 444 &PrintDialogGtk2::CreatePrintDialog); |
| 450 printing::PrintingContextLinux::SetPdfPaperSizeFunction( | 445 printing::PrintingContextLinux::SetPdfPaperSizeFunction( |
| 451 &GetPdfPaperSizeDeviceUnitsGtk); | 446 &GetPdfPaperSizeDeviceUnitsGtk); |
| 452 #endif | 447 #endif |
| 453 | 448 |
| 454 #if defined(USE_GCONF) | 449 #if defined(USE_GCONF) |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 | 691 |
| 697 return std::move(gtk_border); | 692 return std::move(gtk_border); |
| 698 } | 693 } |
| 699 | 694 |
| 700 void GtkUi::AddWindowButtonOrderObserver( | 695 void GtkUi::AddWindowButtonOrderObserver( |
| 701 views::WindowButtonOrderObserver* observer) { | 696 views::WindowButtonOrderObserver* observer) { |
| 702 if (!leading_buttons_.empty() || !trailing_buttons_.empty()) { | 697 if (!leading_buttons_.empty() || !trailing_buttons_.empty()) { |
| 703 observer->OnWindowButtonOrderingChange(leading_buttons_, trailing_buttons_); | 698 observer->OnWindowButtonOrderingChange(leading_buttons_, trailing_buttons_); |
| 704 } | 699 } |
| 705 | 700 |
| 706 observer_list_.AddObserver(observer); | 701 window_button_order_observer_list_.AddObserver(observer); |
| 707 } | 702 } |
| 708 | 703 |
| 709 void GtkUi::RemoveWindowButtonOrderObserver( | 704 void GtkUi::RemoveWindowButtonOrderObserver( |
| 710 views::WindowButtonOrderObserver* observer) { | 705 views::WindowButtonOrderObserver* observer) { |
| 711 observer_list_.RemoveObserver(observer); | 706 window_button_order_observer_list_.RemoveObserver(observer); |
| 712 } | 707 } |
| 713 | 708 |
| 714 void GtkUi::SetWindowButtonOrdering( | 709 void GtkUi::SetWindowButtonOrdering( |
| 715 const std::vector<views::FrameButton>& leading_buttons, | 710 const std::vector<views::FrameButton>& leading_buttons, |
| 716 const std::vector<views::FrameButton>& trailing_buttons) { | 711 const std::vector<views::FrameButton>& trailing_buttons) { |
| 717 leading_buttons_ = leading_buttons; | 712 leading_buttons_ = leading_buttons; |
| 718 trailing_buttons_ = trailing_buttons; | 713 trailing_buttons_ = trailing_buttons; |
| 719 | 714 |
| 720 for (views::WindowButtonOrderObserver& observer : observer_list_) | 715 for (views::WindowButtonOrderObserver& observer : |
| 716 window_button_order_observer_list_) { |
| 721 observer.OnWindowButtonOrderingChange(leading_buttons_, trailing_buttons_); | 717 observer.OnWindowButtonOrderingChange(leading_buttons_, trailing_buttons_); |
| 718 } |
| 722 } | 719 } |
| 723 | 720 |
| 724 void GtkUi::SetNonClientMiddleClickAction(NonClientMiddleClickAction action) { | 721 void GtkUi::SetNonClientMiddleClickAction(NonClientMiddleClickAction action) { |
| 725 middle_click_action_ = action; | 722 middle_click_action_ = action; |
| 726 } | 723 } |
| 727 | 724 |
| 728 std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( | 725 std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( |
| 729 ui::LinuxInputMethodContextDelegate* delegate, | 726 ui::LinuxInputMethodContextDelegate* delegate, |
| 730 bool is_simple) const { | 727 bool is_simple) const { |
| 731 return std::unique_ptr<ui::LinuxInputMethodContext>( | 728 return std::unique_ptr<ui::LinuxInputMethodContext>( |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 GtkUi::GetNonClientMiddleClickAction() { | 760 GtkUi::GetNonClientMiddleClickAction() { |
| 764 return middle_click_action_; | 761 return middle_click_action_; |
| 765 } | 762 } |
| 766 | 763 |
| 767 void GtkUi::NotifyWindowManagerStartupComplete() { | 764 void GtkUi::NotifyWindowManagerStartupComplete() { |
| 768 // TODO(port) Implement this using _NET_STARTUP_INFO_BEGIN/_NET_STARTUP_INFO | 765 // TODO(port) Implement this using _NET_STARTUP_INFO_BEGIN/_NET_STARTUP_INFO |
| 769 // from http://standards.freedesktop.org/startup-notification-spec/ instead. | 766 // from http://standards.freedesktop.org/startup-notification-spec/ instead. |
| 770 gdk_notify_startup_complete(); | 767 gdk_notify_startup_complete(); |
| 771 } | 768 } |
| 772 | 769 |
| 770 void GtkUi::AddDeviceScaleFactorObserver( |
| 771 views::DeviceScaleFactorObserver* observer) { |
| 772 device_scale_factor_observer_list_.AddObserver(observer); |
| 773 } |
| 774 |
| 775 void GtkUi::RemoveDeviceScaleFactorObserver( |
| 776 views::DeviceScaleFactorObserver* observer) { |
| 777 device_scale_factor_observer_list_.RemoveObserver(observer); |
| 778 } |
| 779 |
| 773 bool GtkUi::MatchEvent(const ui::Event& event, | 780 bool GtkUi::MatchEvent(const ui::Event& event, |
| 774 std::vector<ui::TextEditCommandAuraLinux>* commands) { | 781 std::vector<ui::TextEditCommandAuraLinux>* commands) { |
| 775 // Ensure that we have a keyboard handler. | 782 // Ensure that we have a keyboard handler. |
| 776 if (!key_bindings_handler_) | 783 if (!key_bindings_handler_) |
| 777 key_bindings_handler_.reset(new Gtk2KeyBindingsHandler); | 784 key_bindings_handler_.reset(new Gtk2KeyBindingsHandler); |
| 778 | 785 |
| 779 return key_bindings_handler_->MatchEvent(event, commands); | 786 return key_bindings_handler_->MatchEvent(event, commands); |
| 780 } | 787 } |
| 781 | 788 |
| 789 void GtkUi::OnDeviceScaleFactorMaybeChanged(void*, GParamSpec*) { |
| 790 UpdateDeviceScaleFactor(); |
| 791 } |
| 792 |
| 782 void GtkUi::SetScrollbarColors() { | 793 void GtkUi::SetScrollbarColors() { |
| 783 thumb_active_color_ = SkColorSetRGB(244, 244, 244); | 794 thumb_active_color_ = SkColorSetRGB(244, 244, 244); |
| 784 thumb_inactive_color_ = SkColorSetRGB(234, 234, 234); | 795 thumb_inactive_color_ = SkColorSetRGB(234, 234, 234); |
| 785 track_color_ = SkColorSetRGB(211, 211, 211); | 796 track_color_ = SkColorSetRGB(211, 211, 211); |
| 786 | 797 |
| 787 GetChromeStyleColor("scrollbar-slider-prelight-color", &thumb_active_color_); | 798 GetChromeStyleColor("scrollbar-slider-prelight-color", &thumb_active_color_); |
| 788 GetChromeStyleColor("scrollbar-slider-normal-color", &thumb_inactive_color_); | 799 GetChromeStyleColor("scrollbar-slider-normal-color", &thumb_inactive_color_); |
| 789 GetChromeStyleColor("scrollbar-trough-color", &track_color_); | 800 GetChromeStyleColor("scrollbar-trough-color", &track_color_); |
| 790 } | 801 } |
| 791 | 802 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 #endif | 1041 #endif |
| 1031 | 1042 |
| 1032 return false; | 1043 return false; |
| 1033 } | 1044 } |
| 1034 | 1045 |
| 1035 void GtkUi::ResetStyle() { | 1046 void GtkUi::ResetStyle() { |
| 1036 LoadGtkValues(); | 1047 LoadGtkValues(); |
| 1037 native_theme_->NotifyObservers(); | 1048 native_theme_->NotifyObservers(); |
| 1038 } | 1049 } |
| 1039 | 1050 |
| 1051 float GtkUi::GetRawDeviceScaleFactor() { |
| 1052 if (display::Display::HasForceDeviceScaleFactor()) |
| 1053 return display::Display::GetForcedDeviceScaleFactor(); |
| 1054 |
| 1055 GdkScreen* screen = gdk_screen_get_default(); |
| 1056 gint scale = gtk_widget_get_scale_factor(fake_window_); |
| 1057 gdouble resolution = gdk_screen_get_resolution(screen); |
| 1058 const float scale_factor = |
| 1059 resolution <= 0 ? scale : resolution * scale / kDefaultDPI; |
| 1060 // Blacklist scaling factors <120% (crbug.com/484400) and round |
| 1061 // to 1 decimal to prevent rendering problems (crbug.com/485183). |
| 1062 return scale_factor < 1.2f ? 1.0f : roundf(scale_factor * 10) / 10; |
| 1063 } |
| 1064 |
| 1040 void GtkUi::UpdateDeviceScaleFactor() { | 1065 void GtkUi::UpdateDeviceScaleFactor() { |
| 1041 // Note: Linux chrome currently does not support dynamic DPI | 1066 float old_device_scale_factor = device_scale_factor_; |
| 1042 // changes. This is to allow flags to override the DPI settings | |
| 1043 // during startup. | |
| 1044 device_scale_factor_ = GetRawDeviceScaleFactor(); | 1067 device_scale_factor_ = GetRawDeviceScaleFactor(); |
| 1068 if (device_scale_factor_ != old_device_scale_factor) { |
| 1069 for (views::DeviceScaleFactorObserver& observer : |
| 1070 device_scale_factor_observer_list_) { |
| 1071 observer.OnDeviceScaleFactorChanged(); |
| 1072 } |
| 1073 } |
| 1045 UpdateDefaultFont(); | 1074 UpdateDefaultFont(); |
| 1046 } | 1075 } |
| 1047 | 1076 |
| 1048 float GtkUi::GetDeviceScaleFactor() const { | 1077 float GtkUi::GetDeviceScaleFactor() const { |
| 1049 return device_scale_factor_; | 1078 return device_scale_factor_; |
| 1050 } | 1079 } |
| 1051 | 1080 |
| 1052 } // namespace libgtkui | 1081 } // namespace libgtkui |
| 1053 | 1082 |
| 1054 views::LinuxUI* BuildGtkUi() { | 1083 views::LinuxUI* BuildGtkUi() { |
| 1055 return new libgtkui::GtkUi; | 1084 return new libgtkui::GtkUi; |
| 1056 } | 1085 } |
| OLD | NEW |