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