OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/gfx/win/dpi.h" | 5 #include "ui/gfx/dpi.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "base/win/registry.h" |
8 #include "base/win/scoped_hdc.h" | 11 #include "base/win/scoped_hdc.h" |
9 #include "base/win/windows_version.h" | 12 #include "base/win/windows_version.h" |
10 #include "base/win/registry.h" | |
11 #include "ui/gfx/display.h" | 13 #include "ui/gfx/display.h" |
12 #include "ui/gfx/point_conversions.h" | 14 #include "ui/gfx/point_conversions.h" |
13 #include "ui/gfx/rect_conversions.h" | 15 #include "ui/gfx/rect_conversions.h" |
14 #include "ui/gfx/size_conversions.h" | 16 #include "ui/gfx/size_conversions.h" |
15 | 17 |
16 namespace { | 18 namespace { |
17 | 19 |
18 int kDefaultDPIX = 96; | 20 DWORD ReadRegistryValue(HKEY root, |
19 int kDefaultDPIY = 96; | 21 const wchar_t* base_key, |
20 | 22 const wchar_t* value_name, |
21 bool force_highdpi_for_testing = false; | 23 DWORD default_value) { |
22 | 24 base::win::RegKey reg_key(HKEY_CURRENT_USER, |
23 BOOL IsProcessDPIAwareWrapper() { | 25 base_key, |
24 typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID); | 26 KEY_QUERY_VALUE); |
25 IsProcessDPIAwarePtr is_process_dpi_aware_func = | 27 DWORD value; |
26 reinterpret_cast<IsProcessDPIAwarePtr>( | 28 if (reg_key.Valid() && |
27 GetProcAddress(GetModuleHandleA("user32.dll"), "IsProcessDPIAware")); | 29 reg_key.ReadValueDW(value_name, &value) == ERROR_SUCCESS) { |
28 if (is_process_dpi_aware_func) | 30 return value; |
29 return is_process_dpi_aware_func(); | 31 } |
30 return FALSE; | 32 return default_value; |
31 } | |
32 | |
33 float g_device_scale_factor = 0.0f; | |
34 | |
35 float GetUnforcedDeviceScaleFactor() { | |
36 // If the global device scale factor is initialized use it. This is to ensure | |
37 // we use the same scale factor across all callsites. We don't use the | |
38 // GetDeviceScaleFactor function here because it fires a DCHECK if the | |
39 // g_device_scale_factor global is 0. | |
40 if (g_device_scale_factor) | |
41 return g_device_scale_factor; | |
42 return static_cast<float>(gfx::GetDPI().width()) / | |
43 static_cast<float>(kDefaultDPIX); | |
44 } | 33 } |
45 | 34 |
46 // Duplicated from Win8.1 SDK ShellScalingApi.h | 35 // Duplicated from Win8.1 SDK ShellScalingApi.h |
47 typedef enum PROCESS_DPI_AWARENESS { | 36 typedef enum PROCESS_DPI_AWARENESS { |
48 PROCESS_DPI_UNAWARE = 0, | 37 PROCESS_DPI_UNAWARE = 0, |
49 PROCESS_SYSTEM_DPI_AWARE = 1, | 38 PROCESS_SYSTEM_DPI_AWARE = 1, |
50 PROCESS_PER_MONITOR_DPI_AWARE = 2 | 39 PROCESS_PER_MONITOR_DPI_AWARE = 2 |
51 } PROCESS_DPI_AWARENESS; | 40 } PROCESS_DPI_AWARENESS; |
52 | 41 |
53 typedef enum MONITOR_DPI_TYPE { | 42 typedef enum MONITOR_DPI_TYPE { |
(...skipping 28 matching lines...) Expand all Loading... |
82 BOOL SetProcessDPIAwareWrapper() { | 71 BOOL SetProcessDPIAwareWrapper() { |
83 typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID); | 72 typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID); |
84 SetProcessDPIAwarePtr set_process_dpi_aware_func = | 73 SetProcessDPIAwarePtr set_process_dpi_aware_func = |
85 reinterpret_cast<SetProcessDPIAwarePtr>( | 74 reinterpret_cast<SetProcessDPIAwarePtr>( |
86 GetProcAddress(GetModuleHandleA("user32.dll"), | 75 GetProcAddress(GetModuleHandleA("user32.dll"), |
87 "SetProcessDPIAware")); | 76 "SetProcessDPIAware")); |
88 return set_process_dpi_aware_func && | 77 return set_process_dpi_aware_func && |
89 set_process_dpi_aware_func(); | 78 set_process_dpi_aware_func(); |
90 } | 79 } |
91 | 80 |
92 DWORD ReadRegistryValue(HKEY root, | |
93 const wchar_t* base_key, | |
94 const wchar_t* value_name, | |
95 DWORD default_value) { | |
96 base::win::RegKey reg_key(HKEY_CURRENT_USER, | |
97 base_key, | |
98 KEY_QUERY_VALUE); | |
99 DWORD value; | |
100 if (reg_key.Valid() && | |
101 reg_key.ReadValueDW(value_name, &value) == ERROR_SUCCESS) { | |
102 return value; | |
103 } | |
104 return default_value; | |
105 } | |
106 | |
107 } // namespace | 81 } // namespace |
108 | 82 |
109 namespace gfx { | 83 namespace gfx { |
110 | 84 |
111 void InitDeviceScaleFactor(float scale) { | |
112 DCHECK_NE(0.0f, scale); | |
113 g_device_scale_factor = scale; | |
114 } | |
115 | |
116 Size GetDPI() { | 85 Size GetDPI() { |
117 static int dpi_x = 0; | 86 static int dpi_x = 0; |
118 static int dpi_y = 0; | 87 static int dpi_y = 0; |
119 static bool should_initialize = true; | 88 static bool should_initialize = true; |
120 | 89 |
121 if (should_initialize) { | 90 if (should_initialize) { |
122 should_initialize = false; | 91 should_initialize = false; |
123 base::win::ScopedGetDC screen_dc(NULL); | 92 base::win::ScopedGetDC screen_dc(NULL); |
124 // This value is safe to cache for the life time of the app since the | 93 // This value is safe to cache for the life time of the app since the |
125 // user must logout to change the DPI setting. This value also applies | 94 // user must logout to change the DPI setting. This value also applies |
126 // to all screens. | 95 // to all screens. |
127 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); | 96 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); |
128 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); | 97 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); |
129 } | 98 } |
130 return Size(dpi_x, dpi_y); | 99 return Size(dpi_x, dpi_y); |
131 } | 100 } |
132 | 101 |
133 float GetDPIScale() { | 102 bool IsHighDPIEnabled() { |
134 if (IsHighDPIEnabled()) { | 103 static const wchar_t kRegistryProfilePath[] = |
135 if (gfx::Display::HasForceDeviceScaleFactor()) | 104 L"Software\\Google\\Chrome\\Profile"; |
136 return gfx::Display::GetForcedDeviceScaleFactor(); | 105 static const wchar_t kHighDPISupportW[] = L"high-dpi-support"; |
137 float dpi_scale = GetUnforcedDeviceScaleFactor(); | |
138 if (dpi_scale <= 1.25) { | |
139 // Force 125% and below to 100% scale. We do this to maintain previous | |
140 // (non-DPI-aware) behavior where only the font size was boosted. | |
141 dpi_scale = 1.0; | |
142 } | |
143 return dpi_scale; | |
144 } | |
145 return 1.0; | |
146 } | |
147 | 106 |
148 void ForceHighDPISupportForTesting(float scale) { | |
149 g_device_scale_factor = scale; | |
150 } | |
151 | |
152 bool IsHighDPIEnabled() { | |
153 // Flag stored in HKEY_CURRENT_USER\SOFTWARE\\Google\\Chrome\\Profile, | 107 // Flag stored in HKEY_CURRENT_USER\SOFTWARE\\Google\\Chrome\\Profile, |
154 // under the DWORD value high-dpi-support. | 108 // under the DWORD value high-dpi-support. |
155 // Default is disabled. | 109 // Default is disabled. |
156 static DWORD value = ReadRegistryValue( | 110 static DWORD value = ReadRegistryValue( |
157 HKEY_CURRENT_USER, gfx::win::kRegistryProfilePath, | 111 HKEY_CURRENT_USER, kRegistryProfilePath, kHighDPISupportW, TRUE); |
158 gfx::win::kHighDPISupportW, TRUE); | |
159 return value != 0; | 112 return value != 0; |
160 } | 113 } |
161 | 114 |
162 bool IsInHighDPIMode() { | 115 namespace win { |
163 return GetDPIScale() > 1.0; | |
164 } | |
165 | 116 |
166 void EnableHighDPISupport() { | 117 void EnableHighDPISupport() { |
167 if (IsHighDPIEnabled() && | 118 if (IsHighDPIEnabled() && |
168 !SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) { | 119 !SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) { |
169 SetProcessDPIAwareWrapper(); | 120 SetProcessDPIAwareWrapper(); |
170 } | 121 } |
171 } | 122 } |
172 | 123 |
173 namespace win { | |
174 | |
175 GFX_EXPORT const wchar_t kRegistryProfilePath[] = | |
176 L"Software\\Google\\Chrome\\Profile"; | |
177 GFX_EXPORT const wchar_t kHighDPISupportW[] = L"high-dpi-support"; | |
178 | |
179 float GetDeviceScaleFactor() { | |
180 DCHECK_NE(0.0f, g_device_scale_factor); | |
181 return g_device_scale_factor; | |
182 } | |
183 | |
184 Point ScreenToDIPPoint(const Point& pixel_point) { | |
185 return ToFlooredPoint(ScalePoint(pixel_point, | |
186 1.0f / GetDeviceScaleFactor())); | |
187 } | |
188 | |
189 Point DIPToScreenPoint(const Point& dip_point) { | |
190 return ToFlooredPoint(ScalePoint(dip_point, GetDeviceScaleFactor())); | |
191 } | |
192 | |
193 Rect ScreenToDIPRect(const Rect& pixel_bounds) { | |
194 // It's important we scale the origin and size separately. If we instead | |
195 // calculated the size from the floored origin and ceiled right the size could | |
196 // vary depending upon where the two points land. That would cause problems | |
197 // for the places this code is used (in particular mapping from native window | |
198 // bounds to DIPs). | |
199 return Rect(ScreenToDIPPoint(pixel_bounds.origin()), | |
200 ScreenToDIPSize(pixel_bounds.size())); | |
201 } | |
202 | |
203 Rect DIPToScreenRect(const Rect& dip_bounds) { | |
204 // See comment in ScreenToDIPRect for why we calculate size like this. | |
205 return Rect(DIPToScreenPoint(dip_bounds.origin()), | |
206 DIPToScreenSize(dip_bounds.size())); | |
207 } | |
208 | |
209 Size ScreenToDIPSize(const Size& size_in_pixels) { | |
210 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | |
211 return ToCeiledSize( | |
212 ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor())); | |
213 } | |
214 | |
215 Size DIPToScreenSize(const Size& dip_size) { | |
216 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | |
217 return ToCeiledSize(ScaleSize(dip_size, GetDeviceScaleFactor())); | |
218 } | |
219 | |
220 int GetSystemMetricsInDIP(int metric) { | 124 int GetSystemMetricsInDIP(int metric) { |
221 return static_cast<int>(GetSystemMetrics(metric) / | 125 return static_cast<int>(GetSystemMetrics(metric) / |
222 GetDeviceScaleFactor() + 0.5); | 126 GetDeviceScaleFactor() + 0.5); |
223 } | 127 } |
224 | 128 |
225 bool IsDeviceScaleFactorSet() { | |
226 return g_device_scale_factor != 0.0f; | |
227 } | |
228 | |
229 } // namespace win | 129 } // namespace win |
230 } // namespace gfx | 130 } // namespace gfx |
OLD | NEW |