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 "ui/gfx/win/dpi.h" | 5 #include "ui/gfx/win/dpi.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include "base/win/scoped_hdc.h" | 8 #include "base/win/scoped_hdc.h" |
9 #include "base/win/windows_version.h" | |
10 #include "base/win/registry.h" | |
11 #include "ui/gfx/display.h" | 9 #include "ui/gfx/display.h" |
12 #include "ui/gfx/point_conversions.h" | 10 #include "ui/gfx/point_conversions.h" |
13 #include "ui/gfx/rect_conversions.h" | 11 #include "ui/gfx/rect_conversions.h" |
14 #include "ui/gfx/size_conversions.h" | 12 #include "ui/gfx/size_conversions.h" |
15 | 13 |
16 namespace { | 14 namespace { |
17 | 15 |
18 int kDefaultDPIX = 96; | 16 int kDefaultDPIX = 96; |
19 int kDefaultDPIY = 96; | 17 int kDefaultDPIY = 96; |
20 | 18 |
21 bool force_highdpi_for_testing = false; | 19 bool force_highdpi_for_testing = false; |
22 | 20 |
23 BOOL IsProcessDPIAwareWrapper() { | |
24 typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID); | |
25 IsProcessDPIAwarePtr is_process_dpi_aware_func = | |
26 reinterpret_cast<IsProcessDPIAwarePtr>( | |
27 GetProcAddress(GetModuleHandleA("user32.dll"), "IsProcessDPIAware")); | |
28 if (is_process_dpi_aware_func) | |
29 return is_process_dpi_aware_func(); | |
30 return FALSE; | |
31 } | |
32 | |
33 float g_device_scale_factor = 0.0f; | 21 float g_device_scale_factor = 0.0f; |
34 | 22 |
35 float GetUnforcedDeviceScaleFactor() { | 23 float GetUnforcedDeviceScaleFactor() { |
36 // If the global device scale factor is initialized use it. This is to ensure | 24 // If the global device scale factor is initialized use it. This is to ensure |
37 // we use the same scale factor across all callsites. | 25 // we use the same scale factor across all callsites. |
38 if (g_device_scale_factor) | 26 if (g_device_scale_factor) |
39 return g_device_scale_factor; | 27 return g_device_scale_factor; |
40 return static_cast<float>(gfx::GetDPI().width()) / | 28 return static_cast<float>(gfx::GetDPI().width()) / |
41 static_cast<float>(kDefaultDPIX); | 29 static_cast<float>(kDefaultDPIX); |
42 } | 30 } |
43 | 31 |
44 // Duplicated from Win8.1 SDK ShellScalingApi.h | |
45 typedef enum PROCESS_DPI_AWARENESS { | |
46 PROCESS_DPI_UNAWARE = 0, | |
47 PROCESS_SYSTEM_DPI_AWARE = 1, | |
48 PROCESS_PER_MONITOR_DPI_AWARE = 2 | |
49 } PROCESS_DPI_AWARENESS; | |
50 | |
51 typedef enum MONITOR_DPI_TYPE { | |
52 MDT_EFFECTIVE_DPI = 0, | |
53 MDT_ANGULAR_DPI = 1, | |
54 MDT_RAW_DPI = 2, | |
55 MDT_DEFAULT = MDT_EFFECTIVE_DPI | |
56 } MONITOR_DPI_TYPE; | |
57 | |
58 // Win8.1 supports monitor-specific DPI scaling. | |
59 bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) { | |
60 typedef BOOL(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS); | |
61 SetProcessDpiAwarenessPtr set_process_dpi_awareness_func = | |
62 reinterpret_cast<SetProcessDpiAwarenessPtr>( | |
63 GetProcAddress(GetModuleHandleA("user32.dll"), | |
64 "SetProcessDpiAwarenessInternal")); | |
65 if (set_process_dpi_awareness_func) { | |
66 HRESULT hr = set_process_dpi_awareness_func(value); | |
67 if (SUCCEEDED(hr)) { | |
68 VLOG(1) << "SetProcessDpiAwareness succeeded."; | |
69 return true; | |
70 } else if (hr == E_ACCESSDENIED) { | |
71 LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. " | |
72 "Function called twice, or manifest was used."; | |
73 } | |
74 } | |
75 return false; | |
76 } | |
77 | |
78 // This function works for Windows Vista through Win8. Win8.1 must use | |
79 // SetProcessDpiAwareness[Wrapper] | |
80 BOOL SetProcessDPIAwareWrapper() { | |
81 typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID); | |
82 SetProcessDPIAwarePtr set_process_dpi_aware_func = | |
83 reinterpret_cast<SetProcessDPIAwarePtr>( | |
84 GetProcAddress(GetModuleHandleA("user32.dll"), | |
85 "SetProcessDPIAware")); | |
86 return set_process_dpi_aware_func && | |
87 set_process_dpi_aware_func(); | |
88 } | |
89 | |
90 DWORD ReadRegistryValue(HKEY root, | |
91 const wchar_t* base_key, | |
92 const wchar_t* value_name, | |
93 DWORD default_value) { | |
94 base::win::RegKey reg_key(HKEY_CURRENT_USER, | |
95 base_key, | |
96 KEY_QUERY_VALUE); | |
97 DWORD value; | |
98 if (reg_key.Valid() && | |
99 reg_key.ReadValueDW(value_name, &value) == ERROR_SUCCESS) { | |
100 return value; | |
101 } | |
102 return default_value; | |
103 } | |
104 | |
105 } // namespace | 32 } // namespace |
106 | 33 |
107 namespace gfx { | 34 namespace gfx { |
108 | 35 |
109 void InitDeviceScaleFactor(float scale) { | 36 void InitDeviceScaleFactor(float scale) { |
110 DCHECK_NE(0.0f, scale); | 37 DCHECK_NE(0.0f, scale); |
111 g_device_scale_factor = scale; | 38 g_device_scale_factor = scale; |
112 } | 39 } |
113 | 40 |
114 Size GetDPI() { | 41 Size GetDPI() { |
115 static int dpi_x = 0; | 42 static int dpi_x = 0; |
116 static int dpi_y = 0; | 43 static int dpi_y = 0; |
117 static bool should_initialize = true; | 44 static bool should_initialize = true; |
118 | 45 |
119 if (should_initialize) { | 46 if (should_initialize) { |
120 should_initialize = false; | 47 should_initialize = false; |
121 base::win::ScopedGetDC screen_dc(NULL); | 48 base::win::ScopedGetDC screen_dc(NULL); |
122 // This value is safe to cache for the life time of the app since the | 49 // This value is safe to cache for the life time of the app since the |
123 // user must logout to change the DPI setting. This value also applies | 50 // user must logout to change the DPI setting. This value also applies |
124 // to all screens. | 51 // to all screens. |
125 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); | 52 dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX); |
126 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); | 53 dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY); |
127 } | 54 } |
128 return Size(dpi_x, dpi_y); | 55 return Size(dpi_x, dpi_y); |
129 } | 56 } |
130 | 57 |
131 float GetDPIScale() { | 58 float GetDPIScale() { |
132 if (IsHighDPIEnabled()) { | 59 if (gfx::Display::HasForceDeviceScaleFactor()) |
133 if (gfx::Display::HasForceDeviceScaleFactor()) | 60 return gfx::Display::GetForcedDeviceScaleFactor(); |
134 return gfx::Display::GetForcedDeviceScaleFactor(); | 61 float dpi_scale = GetUnforcedDeviceScaleFactor(); |
135 float dpi_scale = GetUnforcedDeviceScaleFactor(); | 62 if (dpi_scale <= 1.25) { |
136 if (dpi_scale <= 1.25) { | 63 // Force 125% and below to 100% scale. We do this to maintain previous |
137 // Force 125% and below to 100% scale. We do this to maintain previous | 64 // (non-DPI-aware) behavior where only the font size was boosted. |
138 // (non-DPI-aware) behavior where only the font size was boosted. | 65 dpi_scale = 1.0; |
139 dpi_scale = 1.0; | |
140 } | |
141 return dpi_scale; | |
142 } | 66 } |
143 return 1.0; | 67 return dpi_scale; |
144 } | |
145 | |
146 void ForceHighDPISupportForTesting(float scale) { | |
147 g_device_scale_factor = scale; | |
148 } | |
149 | |
150 bool IsHighDPIEnabled() { | |
151 // Flag stored in HKEY_CURRENT_USER\SOFTWARE\\Google\\Chrome\\Profile, | |
152 // under the DWORD value high-dpi-support. | |
153 // Default is disabled. | |
154 static DWORD value = ReadRegistryValue( | |
155 HKEY_CURRENT_USER, gfx::win::kRegistryProfilePath, | |
156 gfx::win::kHighDPISupportW, TRUE); | |
157 return value != 0; | |
158 } | |
159 | |
160 void EnableHighDPISupport() { | |
161 if (IsHighDPIEnabled() && | |
162 !SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) { | |
163 SetProcessDPIAwareWrapper(); | |
164 } | |
165 } | 68 } |
166 | 69 |
167 namespace win { | 70 namespace win { |
168 | 71 |
169 GFX_EXPORT const wchar_t kRegistryProfilePath[] = | |
170 L"Software\\Google\\Chrome\\Profile"; | |
171 GFX_EXPORT const wchar_t kHighDPISupportW[] = L"high-dpi-support"; | |
172 | |
173 Point ScreenToDIPPoint(const Point& pixel_point) { | 72 Point ScreenToDIPPoint(const Point& pixel_point) { |
174 return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDPIScale())); | 73 return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDPIScale())); |
175 } | 74 } |
176 | 75 |
177 Point DIPToScreenPoint(const Point& dip_point) { | 76 Point DIPToScreenPoint(const Point& dip_point) { |
178 return ToFlooredPoint(ScalePoint(dip_point, GetDPIScale())); | 77 return ToFlooredPoint(ScalePoint(dip_point, GetDPIScale())); |
179 } | 78 } |
180 | 79 |
181 Rect ScreenToDIPRect(const Rect& pixel_bounds) { | 80 Rect ScreenToDIPRect(const Rect& pixel_bounds) { |
182 // It's important we scale the origin and size separately. If we instead | 81 // It's important we scale the origin and size separately. If we instead |
(...skipping 18 matching lines...) Expand all Loading... |
201 | 100 |
202 Size DIPToScreenSize(const Size& dip_size) { | 101 Size DIPToScreenSize(const Size& dip_size) { |
203 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. | 102 // Always ceil sizes. Otherwise we may be leaving off part of the bounds. |
204 return ToCeiledSize(ScaleSize(dip_size, GetDPIScale())); | 103 return ToCeiledSize(ScaleSize(dip_size, GetDPIScale())); |
205 } | 104 } |
206 | 105 |
207 int GetSystemMetricsInDIP(int metric) { | 106 int GetSystemMetricsInDIP(int metric) { |
208 return static_cast<int>(GetSystemMetrics(metric) / GetDPIScale() + 0.5); | 107 return static_cast<int>(GetSystemMetrics(metric) / GetDPIScale() + 0.5); |
209 } | 108 } |
210 | 109 |
211 bool IsDeviceScaleFactorSet() { | |
212 return g_device_scale_factor != 0.0f; | |
213 } | |
214 | |
215 } // namespace win | 110 } // namespace win |
216 } // namespace gfx | 111 } // namespace gfx |
OLD | NEW |