1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/win/dpi.h"
#include <windows.h>
#include "base/command_line.h"
#include "base/win/scoped_hdc.h"
#include "base/win/windows_version.h"
#include "ui/base/layout.h"
#include "base/win/registry.h"
#include "ui/gfx/display.h"
#include "ui/gfx/switches.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
namespace {
int kDefaultDPIX = 96;
int kDefaultDPIY = 96;
// Tests to see if the command line flag "--high-dpi-support" is set.
bool IsHighDPIEnabled() {
// Default is disabled.
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kHighDPISupport)) {
return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kHighDPISupport).compare("1") == 0;
}
return false;
}
// Gets the device scale factor. If support is enabled, this will return the
// best available scale based on the screen's pixel density. This can be
// affected (overridden) by --force-device-scale-factor=x
float GetDeviceScaleFactorImpl() {
if (IsHighDPIEnabled()) {
float scale = gfx::Display::HasForceDeviceScaleFactor() ?
gfx::Display::GetForcedDeviceScaleFactor() : gfx::GetDPIScale();
// Quantize to nearest supported scale factor.
scale = ui::GetScaleFactorScale(ui::GetScaleFactorFromScale(scale));
return scale;
}
return 1.0f;
}
BOOL IsProcessDPIAwareWrapper() {
typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID);
IsProcessDPIAwarePtr is_process_dpi_aware_func =
reinterpret_cast<IsProcessDPIAwarePtr>(
GetProcAddress(GetModuleHandleA("user32.dll"), "IsProcessDPIAware"));
if (is_process_dpi_aware_func)
return is_process_dpi_aware_func();
return FALSE;
}
} // namespace
namespace gfx {
Size GetDPI() {
static int dpi_x = 0;
static int dpi_y = 0;
static bool should_initialize = true;
if (should_initialize) {
should_initialize = false;
base::win::ScopedGetDC screen_dc(NULL);
// This value is safe to cache for the life time of the app since the
// user must logout to change the DPI setting. This value also applies
// to all screens.
dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY);
}
return Size(dpi_x, dpi_y);
}
float GetDPIScale() {
if (IsHighDPIEnabled()) {
return static_cast<float>(GetDPI().width()) /
static_cast<float>(kDefaultDPIX);
}
return 1.0;
}
bool IsInHighDPIMode() {
return GetDPIScale() > 1.0;
}
void EnableHighDPISupport() {
if (IsHighDPIEnabled()) {
typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
SetProcessDPIAwarePtr set_process_dpi_aware_func =
reinterpret_cast<SetProcessDPIAwarePtr>(
GetProcAddress(GetModuleHandleA("user32.dll"),
"SetProcessDPIAware"));
if (set_process_dpi_aware_func)
set_process_dpi_aware_func();
}
}
namespace win {
float GetDeviceScaleFactor() {
static const float device_scale_factor = GetDeviceScaleFactorImpl();
return device_scale_factor;
}
Point ScreenToDIPPoint(const Point& pixel_point) {
return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDeviceScaleFactor()));
}
Point DIPToScreenPoint(const Point& dip_point) {
return ToFlooredPoint(ScalePoint(dip_point, GetDeviceScaleFactor()));
}
Rect ScreenToDIPRect(const Rect& pixel_bounds) {
// TODO(kevers): Switch to non-deprecated method for float to int conversions.
return ToFlooredRectDeprecated(
ScaleRect(pixel_bounds, 1.0f / GetDeviceScaleFactor()));
}
Rect DIPToScreenRect(const Rect& dip_bounds) {
// TODO(kevers): Switch to non-deprecated method for float to int conversions.
return ToFlooredRectDeprecated(
ScaleRect(dip_bounds, GetDeviceScaleFactor()));
}
Size ScreenToDIPSize(const Size& size_in_pixels) {
return ToFlooredSize(
ScaleSize(size_in_pixels, 1.0f / GetDeviceScaleFactor()));
}
Size DIPToScreenSize(const Size& dip_size) {
return ToFlooredSize(ScaleSize(dip_size, GetDeviceScaleFactor()));
}
int GetSystemMetricsInDIP(int metric) {
return static_cast<int>(GetSystemMetrics(metric) /
GetDeviceScaleFactor() + 0.5);
}
double GetUndocumentedDPIScale() {
// TODO(girard): Remove this code when chrome is DPIAware.
static double scale = -1.0;
if (scale == -1.0) {
scale = 1.0;
if (!IsProcessDPIAwareWrapper()) {
base::win::RegKey key(HKEY_CURRENT_USER,
L"Control Panel\\Desktop\\WindowMetrics",
KEY_QUERY_VALUE);
if (key.Valid()) {
DWORD value = 0;
if (key.ReadValueDW(L"AppliedDPI", &value) == ERROR_SUCCESS) {
scale = static_cast<double>(value) / kDefaultDPIX;
}
}
}
}
return scale;
}
double GetUndocumentedDPITouchScale() {
static double scale =
(base::win::GetVersion() < base::win::VERSION_WIN8_1) ?
GetUndocumentedDPIScale() : 1.0;
return scale;
}
} // namespace win
} // namespace gfx
|