Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / gfx / win / dpi.cc
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
3 // found in the LICENSE file.
4
5 #include "ui/gfx/win/dpi.h"
6
7 #include <windows.h>
8 #include "base/command_line.h"
9 #include "base/win/scoped_hdc.h"
10 #include "base/win/windows_version.h"
11 #include "base/win/registry.h"
12 #include "ui/gfx/display.h"
13 #include "ui/gfx/switches.h"
14 #include "ui/gfx/point_conversions.h"
15 #include "ui/gfx/rect_conversions.h"
16 #include "ui/gfx/size_conversions.h"
17
18 namespace {
19
20 int kDefaultDPIX = 96;
21 int kDefaultDPIY = 96;
22
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;
34
35 float GetUnforcedDeviceScaleFactor() {
36   return static_cast<float>(gfx::GetDPI().width()) /
37       static_cast<float>(kDefaultDPIX);
38 }
39
40 float GetModernUIScaleWrapper() {
41   float result = 1.0f;
42   typedef float(WINAPI *GetModernUIScalePtr)(VOID);
43   HMODULE lib = LoadLibraryA("metro_driver.dll");
44   if (lib) {
45     GetModernUIScalePtr func =
46         reinterpret_cast<GetModernUIScalePtr>(
47         GetProcAddress(lib, "GetModernUIScale"));
48     if (func)
49       result = func();
50     FreeLibrary(lib);
51   }
52   return result;
53 }
54
55 // Duplicated from Win8.1 SDK ShellScalingApi.h
56 typedef enum PROCESS_DPI_AWARENESS {
57     PROCESS_DPI_UNAWARE = 0,
58     PROCESS_SYSTEM_DPI_AWARE = 1,
59     PROCESS_PER_MONITOR_DPI_AWARE = 2
60 } PROCESS_DPI_AWARENESS;
61
62 typedef enum MONITOR_DPI_TYPE {
63     MDT_EFFECTIVE_DPI = 0,
64     MDT_ANGULAR_DPI = 1,
65     MDT_RAW_DPI = 2,
66     MDT_DEFAULT = MDT_EFFECTIVE_DPI
67 } MONITOR_DPI_TYPE;
68
69 // Win8.1 supports monitor-specific DPI scaling.
70 bool SetProcessDpiAwarenessWrapper(PROCESS_DPI_AWARENESS value) {
71   typedef BOOL(WINAPI *SetProcessDpiAwarenessPtr)(PROCESS_DPI_AWARENESS);
72   SetProcessDpiAwarenessPtr set_process_dpi_awareness_func =
73       reinterpret_cast<SetProcessDpiAwarenessPtr>(
74           GetProcAddress(GetModuleHandleA("user32.dll"),
75                           "SetProcessDpiAwarenessInternal"));
76   if (set_process_dpi_awareness_func) {
77     HRESULT hr = set_process_dpi_awareness_func(value);
78     if (SUCCEEDED(hr)) {
79       VLOG(1) << "SetProcessDpiAwareness succeeded.";
80       return true;
81     } else if (hr == E_ACCESSDENIED) {
82       LOG(ERROR) << "Access denied error from SetProcessDpiAwareness. "
83           "Function called twice, or manifest was used.";
84     }
85   }
86   return false;
87 }
88
89 // This function works for Windows Vista through Win8. Win8.1 must use
90 // SetProcessDpiAwareness[Wrapper]
91 BOOL SetProcessDPIAwareWrapper() {
92   typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
93   SetProcessDPIAwarePtr set_process_dpi_aware_func =
94       reinterpret_cast<SetProcessDPIAwarePtr>(
95       GetProcAddress(GetModuleHandleA("user32.dll"),
96                       "SetProcessDPIAware"));
97   return set_process_dpi_aware_func &&
98     set_process_dpi_aware_func();
99 }
100
101 }  // namespace
102
103 namespace gfx {
104
105 float GetModernUIScale() {
106   return GetModernUIScaleWrapper();
107 }
108
109 void InitDeviceScaleFactor(float scale) {
110   DCHECK_NE(0.0f, scale);
111   g_device_scale_factor = scale;
112 }
113
114 Size GetDPI() {
115   static int dpi_x = 0;
116   static int dpi_y = 0;
117   static bool should_initialize = true;
118
119   if (should_initialize) {
120     should_initialize = false;
121     base::win::ScopedGetDC screen_dc(NULL);
122     // 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
124     // to all screens.
125     dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
126     dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY);
127   }
128   return Size(dpi_x, dpi_y);
129 }
130
131 float GetDPIScale() {
132   if (IsHighDPIEnabled()) {
133     return gfx::Display::HasForceDeviceScaleFactor() ?
134         gfx::Display::GetForcedDeviceScaleFactor() :
135         GetUnforcedDeviceScaleFactor();
136   }
137   return 1.0;
138 }
139
140 bool IsHighDPIEnabled() {
141   // Default is disabled.
142   if (CommandLine::ForCurrentProcess()->HasSwitch(
143       switches::kHighDPISupport)) {
144     return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
145         switches::kHighDPISupport).compare("1") == 0;
146   }
147   return false;
148 }
149
150 bool IsInHighDPIMode() {
151   return GetDPIScale() > 1.0;
152 }
153
154 void EnableHighDPISupport() {
155   if (IsHighDPIEnabled() &&
156       (base::win::GetVersion() < base::win::VERSION_WIN8_1)) {
157     if (!SetProcessDpiAwarenessWrapper(PROCESS_SYSTEM_DPI_AWARE)) {
158       SetProcessDPIAwareWrapper();
159     }
160   }
161 }
162
163 namespace win {
164
165 float GetDeviceScaleFactor() {
166   DCHECK_NE(0.0f, g_device_scale_factor);
167   return g_device_scale_factor;
168 }
169
170 Point ScreenToDIPPoint(const Point& pixel_point) {
171   static float scaling_factor =
172       GetDeviceScaleFactor() > GetUnforcedDeviceScaleFactor() ?
173       1.0f / GetDeviceScaleFactor() :
174       1.0f;
175   return ToFlooredPoint(ScalePoint(pixel_point,
176       scaling_factor));
177 }
178
179 Point DIPToScreenPoint(const Point& dip_point) {
180   return ToFlooredPoint(ScalePoint(dip_point, GetDeviceScaleFactor()));
181 }
182
183 Rect ScreenToDIPRect(const Rect& pixel_bounds) {
184   // TODO(kevers): Switch to non-deprecated method for float to int conversions.
185   return ToFlooredRectDeprecated(
186       ScaleRect(pixel_bounds, 1.0f / GetDeviceScaleFactor()));
187 }
188
189 Rect DIPToScreenRect(const Rect& dip_bounds) {
190   // TODO(kevers): Switch to non-deprecated method for float to int conversions.
191   return ToFlooredRectDeprecated(
192       ScaleRect(dip_bounds, GetDeviceScaleFactor()));
193 }
194
195 Size ScreenToDIPSize(const Size& size_in_pixels) {
196   return ToFlooredSize(
197       ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor()));
198 }
199
200 Size DIPToScreenSize(const Size& dip_size) {
201   return ToFlooredSize(ScaleSize(dip_size, GetDeviceScaleFactor()));
202 }
203
204 int GetSystemMetricsInDIP(int metric) {
205   return static_cast<int>(GetSystemMetrics(metric) /
206       GetDeviceScaleFactor() + 0.5);
207 }
208
209 double GetUndocumentedDPIScale() {
210   // TODO(girard): Remove this code when chrome is DPIAware.
211   static double scale = -1.0;
212   if (scale == -1.0) {
213     scale = 1.0;
214     if (!IsProcessDPIAwareWrapper()) {
215       base::win::RegKey key(HKEY_CURRENT_USER,
216                             L"Control Panel\\Desktop\\WindowMetrics",
217                             KEY_QUERY_VALUE);
218       if (key.Valid()) {
219         DWORD value = 0;
220         if (key.ReadValueDW(L"AppliedDPI", &value) == ERROR_SUCCESS) {
221           scale = static_cast<double>(value) / kDefaultDPIX;
222         }
223       }
224     }
225   }
226   return scale;
227 }
228
229 double GetUndocumentedDPITouchScale() {
230   static double scale =
231       (base::win::GetVersion() < base::win::VERSION_WIN8_1) ?
232       GetUndocumentedDPIScale() : 1.0;
233   return scale;
234 }
235
236 }  // namespace win
237 }  // namespace gfx