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 |