Merge lp:~kaihengfeng/unity/set-hidpi-scale-factor into lp:unity

Proposed by Kai-Heng Feng
Status: Superseded
Proposed branch: lp:~kaihengfeng/unity/set-hidpi-scale-factor
Merge into: lp:unity
Diff against target: 148 lines (+59/-1)
3 files modified
unity-shared/UScreen.cpp (+10/-0)
unity-shared/UScreen.h (+2/-0)
unity-shared/UnitySettings.cpp (+47/-1)
To merge this branch: bzr merge lp:~kaihengfeng/unity/set-hidpi-scale-factor
Reviewer Review Type Date Requested Status
Unity Team Pending
Review via email: mp+298408@code.launchpad.net

This proposal has been superseded by a proposal from 2016-07-04.

To post a comment you must log in.
Revision history for this message
Kai-Heng Feng (kaihengfeng) wrote :

Set gsettings value is needed, otherwise Unity Control Center's Display will reset it because scale-factor is empty.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Mh, this is something I always wanted to do, so thanks.

However I'm not sure is something that should be done at unity level, since it could cause to override the user setting.
Maybe this should be done only if the value is not the default one, I guess.

The preferred way to do this, would be using a migration script though. You can write it in python and follow the same we do for ./tools/migration-scripts/*.

I'd like to discuss about the algorithm to find the proper scaling value. Since we also support non-integer values, it would be nicer to define a scaling to be proportional to display size by using some thresholds.

Revision history for this message
Kai-Heng Feng (kaihengfeng) wrote :

I think this won't override user setting, as long as it's greater than 0.

With this algorithm, a 27 inches 4K display will have scale factor 1.
So yes, I think if the scale can be proportional to display size would be great.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Ok, overriding a 0 value is fine then.

As for the thresholds calculations, can we do some testing?

Revision history for this message
Kai-Heng Feng (kaihengfeng) wrote :

Sure.

I think we can make the scale factor being proportional to the DPI, if the DPI is in range of DEFAULT_DPI to DEFAULT_DPI * 2. Your thought?

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Yeah, I agree.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'unity-shared/UScreen.cpp'
2--- unity-shared/UScreen.cpp 2014-12-18 18:43:36 +0000
3+++ unity-shared/UScreen.cpp 2016-07-04 04:24:40 +0000
4@@ -88,6 +88,11 @@
5 return monitors_[monitor];
6 }
7
8+nux::Size const& UScreen::GetMonitorPhysicalSize(int monitor) const
9+{
10+ return physical_monitors_[monitor];
11+}
12+
13 std::vector<nux::Geometry> const& UScreen::GetMonitors() const
14 {
15 return monitors_;
16@@ -154,6 +159,7 @@
17
18 nux::Geometry last_geo;
19 monitors_.clear();
20+ physical_monitors_.clear();
21 primary_ = gdk_screen_get_primary_monitor(screen_);
22 int monitors = gdk_screen_get_n_monitors(screen_);
23
24@@ -164,6 +170,9 @@
25
26 float scale = gdk_screen_get_monitor_scale_factor(screen_, i);
27 nux::Geometry geo(rect.x, rect.y, rect.width, rect.height);
28+
29+ nux::Size physical_size(gdk_screen_get_monitor_width_mm(screen_, i),
30+ gdk_screen_get_monitor_height_mm(screen_, i));
31
32 if (scale != 1.0)
33 geo = geo * scale;
34@@ -174,6 +183,7 @@
35
36 last_geo = geo;
37 monitors_.push_back(geo);
38+ physical_monitors_.push_back(physical_size);
39
40 LOG_DEBUG(logger) << "Monitor " << i << " has geometry " << geo.x << "x"
41 << geo.y << "x" << geo.width << "x" << geo.height;
42
43=== modified file 'unity-shared/UScreen.h'
44--- unity-shared/UScreen.h 2014-10-21 15:43:16 +0000
45+++ unity-shared/UScreen.h 2016-07-04 04:24:40 +0000
46@@ -45,6 +45,7 @@
47 int GetMonitorWithMouse() const;
48 int GetMonitorAtPosition(int x, int y) const;
49 nux::Geometry const& GetMonitorGeometry(int monitor) const;
50+ nux::Size const& GetMonitorPhysicalSize(int monitor) const;
51
52 std::vector<nux::Geometry> const& GetMonitors() const;
53 nux::Geometry GetScreenGeometry() const;
54@@ -63,6 +64,7 @@
55 protected:
56 static UScreen* default_screen_;
57 std::vector<nux::Geometry> monitors_;
58+ std::vector<nux::Size> physical_monitors_;
59 int primary_;
60
61 private:
62
63=== modified file 'unity-shared/UnitySettings.cpp'
64--- unity-shared/UnitySettings.cpp 2016-06-17 12:05:17 +0000
65+++ unity-shared/UnitySettings.cpp 2016-07-04 04:24:40 +0000
66@@ -76,6 +76,7 @@
67 const int MINIMUM_DESKTOP_HEIGHT = 800;
68 const int GNOME_SETTINGS_CHANGED_WAIT_SECONDS = 1;
69 const double DEFAULT_DPI = 96.0f;
70+const double DPI_SCALE_LIMIT = 140.0f;
71 }
72
73 //
74@@ -323,6 +324,31 @@
75 return em_converters_[monitor];
76 }
77
78+ int FindOptimalScale(const UScreen* uscreen, const int monitor)
79+ {
80+ auto const& geo = uscreen->GetMonitorGeometry(monitor);
81+ auto const& size = uscreen->GetMonitorPhysicalSize(monitor);
82+ int scale = 8;
83+
84+ if ((size.width == 160 && size.height == 90) ||
85+ (size.width == 160 && size.height == 100) ||
86+ (size.width == 16 && size.height == 9) ||
87+ (size.width == 16 && size.height == 10))
88+ return scale;
89+
90+ if (size.width > 0 && size.height > 0) {
91+ const double dpi_x = static_cast<double>(geo.width) / (size.width / 25.4);
92+ const double dpi_y = static_cast<double>(geo.height) / (size.height / 25.4);
93+
94+ const auto dpi = std::max(dpi_x, dpi_y);
95+
96+ if (dpi > DPI_SCALE_LIMIT)
97+ scale = static_cast<int>(std::lround(scale * dpi / DPI_SCALE_LIMIT));
98+ }
99+
100+ return scale;
101+ }
102+
103 void UpdateDPI()
104 {
105 auto* uscreen = UScreen::GetDefault();
106@@ -333,6 +359,10 @@
107 glib::Variant dict;
108 g_settings_get(ubuntu_ui_settings_, SCALE_FACTOR.c_str(), "@a{si}", &dict);
109
110+ bool dict_changed = false;
111+ GVariantBuilder builder;
112+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{si}"));
113+
114 glib::String app_target_monitor(g_settings_get_string(ui_settings_, APP_SCALE_MONITOR.c_str()));
115 double app_target_scale = 0;
116
117@@ -346,8 +376,18 @@
118 double ui_scale = 1.0f;
119 int value;
120
121- if (g_variant_lookup(dict, monitor_name.c_str(), "i", &value) && value > 0)
122+ if (g_variant_lookup(dict, monitor_name.c_str(), "i", &value))
123+ {
124+ if (value > 0)
125+ ui_scale = static_cast<double>(value)/8.0f;
126+ }
127+ else
128+ {
129+ value = FindOptimalScale(uscreen, monitor);
130 ui_scale = static_cast<double>(value)/8.0f;
131+ dict_changed = true;
132+ }
133+ g_variant_builder_add(&builder, "{si}", monitor_name.c_str(), value);
134
135 if (app_target_monitor.Str() == monitor_name)
136 app_target_scale = ui_scale;
137@@ -361,6 +401,12 @@
138 any_changed = true;
139 }
140
141+ glib::Variant new_dict(g_variant_builder_end(&builder));
142+ if (dict_changed)
143+ {
144+ g_settings_set_value(ubuntu_ui_settings_, SCALE_FACTOR.c_str(), new_dict);
145+ }
146+
147 if (app_target_scale == 0)
148 app_target_scale = (g_settings_get_boolean(ui_settings_, APP_USE_MAX_SCALE.c_str())) ? max_scale : min_scale;
149