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