Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(891)

Side by Side Diff: chrome/browser/ui/libgtkui/gtk_ui.cc

Issue 2963033002: Linux UI: Dynamically respond to changes in the scale factor (Closed)
Patch Set: Call OnHostResizedInPixels() when scale factor changes Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698