| Flutter Windows Embedder |

dpi_utils.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 "dpi_utils.h"
6
7 #include "flutter/fml/macros.h"
8
9 namespace flutter {
10
11 namespace {
12
13 constexpr UINT kDefaultDpi = 96;
14
15 // This is the MDT_EFFECTIVE_DPI value from MONITOR_DPI_TYPE, an enum declared
16 // in ShellScalingApi.h. Replicating here to avoid importing the library
17 // directly.
18 constexpr UINT kEffectiveDpiMonitorType = 0;
19
20 template <typename T>
21
22 /// Retrieves a function |name| from a given |comBaseModule| into |outProc|.
23 /// Returns a bool indicating whether the function was found.
24 bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) {
25 outProc = reinterpret_cast<T*>(GetProcAddress(comBaseModule, name));
26 return *outProc != nullptr;
27 }
28
29 /// A helper class for abstracting various Windows DPI related functions across
30 /// Windows OS versions.
31 class DpiHelper {
32 public:
33 DpiHelper();
34
35 ~DpiHelper();
36
37 /// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is
38 /// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns
39 /// the DPI for the primary monitor. If Per-Monitor DPI awareness is not
40 /// available, returns the system's DPI.
41 UINT GetDpiForWindow(HWND);
42
43 /// Returns the DPI of a given monitor. Defaults to 96 if the API is not
44 /// available.
45 UINT GetDpiForMonitor(HMONITOR);
46
47 private:
48 using GetDpiForWindow_ = UINT __stdcall(HWND);
49 using GetDpiForMonitor_ = HRESULT __stdcall(HMONITOR hmonitor,
50 UINT dpiType,
51 UINT* dpiX,
52 UINT* dpiY);
53 using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND hwnd);
54
55 GetDpiForWindow_* get_dpi_for_window_ = nullptr;
56 GetDpiForMonitor_* get_dpi_for_monitor_ = nullptr;
57 EnableNonClientDpiScaling_* enable_non_client_dpi_scaling_ = nullptr;
58
59 HMODULE user32_module_ = nullptr;
60 HMODULE shlib_module_ = nullptr;
61 bool dpi_for_window_supported_ = false;
62 bool dpi_for_monitor_supported_ = false;
63
64 FML_DISALLOW_COPY_AND_ASSIGN(DpiHelper);
65 };
66
67 DpiHelper::DpiHelper() {
68 if ((user32_module_ = LoadLibraryA("User32.dll")) != nullptr) {
69 dpi_for_window_supported_ = (AssignProcAddress(
70 user32_module_, "GetDpiForWindow", get_dpi_for_window_));
71 }
72 if ((shlib_module_ = LoadLibraryA("Shcore.dll")) != nullptr) {
73 dpi_for_monitor_supported_ = AssignProcAddress(
74 shlib_module_, "GetDpiForMonitor", get_dpi_for_monitor_);
75 }
76 }
77
78 DpiHelper::~DpiHelper() {
79 if (user32_module_ != nullptr) {
80 FreeLibrary(user32_module_);
81 }
82 if (shlib_module_ != nullptr) {
83 FreeLibrary(shlib_module_);
84 }
85 }
86
87 UINT DpiHelper::GetDpiForWindow(HWND hwnd) {
88 // GetDpiForWindow returns the DPI for any awareness mode. If not available,
89 // or no |hwnd| is provided, fallback to a per monitor, system, or default
90 // DPI.
91 if (dpi_for_window_supported_ && hwnd != nullptr) {
92 return get_dpi_for_window_(hwnd);
93 }
94
95 if (dpi_for_monitor_supported_) {
96 HMONITOR monitor = nullptr;
97 if (hwnd != nullptr) {
98 monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
99 }
100 return GetDpiForMonitor(monitor);
101 }
102 HDC hdc = GetDC(hwnd);
103 UINT dpi = GetDeviceCaps(hdc, LOGPIXELSX);
104 ReleaseDC(hwnd, hdc);
105 return dpi;
106 }
107
108 UINT DpiHelper::GetDpiForMonitor(HMONITOR monitor) {
109 if (dpi_for_monitor_supported_) {
110 if (monitor == nullptr) {
111 const POINT target_point = {0, 0};
112 monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY);
113 }
114 UINT dpi_x = 0, dpi_y = 0;
115 HRESULT result =
116 get_dpi_for_monitor_(monitor, kEffectiveDpiMonitorType, &dpi_x, &dpi_y);
117 if (SUCCEEDED(result)) {
118 return dpi_x;
119 }
120 }
121 return kDefaultDpi;
122 } // namespace
123
124 DpiHelper* GetHelper() {
125 static DpiHelper* dpi_helper = new DpiHelper();
126 return dpi_helper;
127 }
128 } // namespace
129
130 UINT GetDpiForHWND(HWND hwnd) {
131 return GetHelper()->GetDpiForWindow(hwnd);
132 }
133
134 UINT GetDpiForMonitor(HMONITOR monitor) {
135 return GetHelper()->GetDpiForMonitor(monitor);
136 }
137 } // namespace flutter
dpi_utils.h
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::GetDpiForHWND
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:130
flutter::GetDpiForMonitor
UINT GetDpiForMonitor(HMONITOR monitor)
Definition: dpi_utils.cc:134