• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsProcessDPIAwareWrapper()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 
GetUnforcedDeviceScaleFactor()35 float GetUnforcedDeviceScaleFactor() {
36   return static_cast<float>(gfx::GetDPI().width()) /
37       static_cast<float>(kDefaultDPIX);
38 }
39 
GetModernUIScaleWrapper()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 }  // namespace
56 
57 namespace gfx {
58 
GetModernUIScale()59 float GetModernUIScale() {
60   return GetModernUIScaleWrapper();
61 }
62 
InitDeviceScaleFactor(float scale)63 void InitDeviceScaleFactor(float scale) {
64   DCHECK_NE(0.0f, scale);
65   g_device_scale_factor = scale;
66 }
67 
GetDPI()68 Size GetDPI() {
69   static int dpi_x = 0;
70   static int dpi_y = 0;
71   static bool should_initialize = true;
72 
73   if (should_initialize) {
74     should_initialize = false;
75     base::win::ScopedGetDC screen_dc(NULL);
76     // This value is safe to cache for the life time of the app since the
77     // user must logout to change the DPI setting. This value also applies
78     // to all screens.
79     dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
80     dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY);
81   }
82   return Size(dpi_x, dpi_y);
83 }
84 
GetDPIScale()85 float GetDPIScale() {
86   if (IsHighDPIEnabled()) {
87     return gfx::Display::HasForceDeviceScaleFactor() ?
88         gfx::Display::GetForcedDeviceScaleFactor() :
89         GetUnforcedDeviceScaleFactor();
90   }
91   return 1.0;
92 }
93 
IsHighDPIEnabled()94 bool IsHighDPIEnabled() {
95   // Default is disabled.
96   if (CommandLine::ForCurrentProcess()->HasSwitch(
97       switches::kHighDPISupport)) {
98     return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
99         switches::kHighDPISupport).compare("1") == 0;
100   }
101   return false;
102 }
103 
IsInHighDPIMode()104 bool IsInHighDPIMode() {
105   return GetDPIScale() > 1.0;
106 }
107 
EnableHighDPISupport()108 void EnableHighDPISupport() {
109   if (IsHighDPIEnabled() &&
110       (base::win::GetVersion() < base::win::VERSION_WIN8_1)) {
111     typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
112     SetProcessDPIAwarePtr set_process_dpi_aware_func =
113         reinterpret_cast<SetProcessDPIAwarePtr>(
114             GetProcAddress(GetModuleHandleA("user32.dll"),
115                            "SetProcessDPIAware"));
116     if (set_process_dpi_aware_func)
117       set_process_dpi_aware_func();
118   }
119 }
120 
121 namespace win {
122 
GetDeviceScaleFactor()123 float GetDeviceScaleFactor() {
124   DCHECK_NE(0.0f, g_device_scale_factor);
125   return g_device_scale_factor;
126 }
127 
ScreenToDIPPoint(const Point & pixel_point)128 Point ScreenToDIPPoint(const Point& pixel_point) {
129   static float scaling_factor =
130       GetDeviceScaleFactor() > GetUnforcedDeviceScaleFactor() ?
131       1.0f / GetDeviceScaleFactor() :
132       1.0f;
133   return ToFlooredPoint(ScalePoint(pixel_point,
134       scaling_factor));
135 }
136 
DIPToScreenPoint(const Point & dip_point)137 Point DIPToScreenPoint(const Point& dip_point) {
138   return ToFlooredPoint(ScalePoint(dip_point, GetDeviceScaleFactor()));
139 }
140 
ScreenToDIPRect(const Rect & pixel_bounds)141 Rect ScreenToDIPRect(const Rect& pixel_bounds) {
142   // TODO(kevers): Switch to non-deprecated method for float to int conversions.
143   return ToFlooredRectDeprecated(
144       ScaleRect(pixel_bounds, 1.0f / GetDeviceScaleFactor()));
145 }
146 
DIPToScreenRect(const Rect & dip_bounds)147 Rect DIPToScreenRect(const Rect& dip_bounds) {
148   // TODO(kevers): Switch to non-deprecated method for float to int conversions.
149   return ToFlooredRectDeprecated(
150       ScaleRect(dip_bounds, GetDeviceScaleFactor()));
151 }
152 
ScreenToDIPSize(const Size & size_in_pixels)153 Size ScreenToDIPSize(const Size& size_in_pixels) {
154   return ToFlooredSize(
155       ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor()));
156 }
157 
DIPToScreenSize(const Size & dip_size)158 Size DIPToScreenSize(const Size& dip_size) {
159   return ToFlooredSize(ScaleSize(dip_size, GetDeviceScaleFactor()));
160 }
161 
GetSystemMetricsInDIP(int metric)162 int GetSystemMetricsInDIP(int metric) {
163   return static_cast<int>(GetSystemMetrics(metric) /
164       GetDeviceScaleFactor() + 0.5);
165 }
166 
GetUndocumentedDPIScale()167 double GetUndocumentedDPIScale() {
168   // TODO(girard): Remove this code when chrome is DPIAware.
169   static double scale = -1.0;
170   if (scale == -1.0) {
171     scale = 1.0;
172     if (!IsProcessDPIAwareWrapper()) {
173       base::win::RegKey key(HKEY_CURRENT_USER,
174                             L"Control Panel\\Desktop\\WindowMetrics",
175                             KEY_QUERY_VALUE);
176       if (key.Valid()) {
177         DWORD value = 0;
178         if (key.ReadValueDW(L"AppliedDPI", &value) == ERROR_SUCCESS) {
179           scale = static_cast<double>(value) / kDefaultDPIX;
180         }
181       }
182     }
183   }
184   return scale;
185 }
186 
GetUndocumentedDPITouchScale()187 double GetUndocumentedDPITouchScale() {
188   static double scale =
189       (base::win::GetVersion() < base::win::VERSION_WIN8_1) ?
190       GetUndocumentedDPIScale() : 1.0;
191   return scale;
192 }
193 
194 }  // namespace win
195 }  // namespace gfx
196