Flutter Engine
The Flutter Engine
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
9namespace flutter {
10
11namespace {
12
13constexpr 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.
18constexpr UINT kEffectiveDpiMonitorType = 0;
19
20template <typename T>
21
22/// Retrieves a function |name| from a given |comBaseModule| into |outProc|.
23/// Returns a bool indicating whether the function was found.
24bool 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.
31class 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
65};
66
67DpiHelper::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
78DpiHelper::~DpiHelper() {
79 if (user32_module_ != nullptr) {
80 FreeLibrary(user32_module_);
81 }
82 if (shlib_module_ != nullptr) {
83 FreeLibrary(shlib_module_);
84 }
85}
86
87UINT 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
108UINT 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
124DpiHelper* GetHelper() {
125 static DpiHelper* dpi_helper = new DpiHelper();
126 return dpi_helper;
127}
128} // namespace
129
130UINT GetDpiForHWND(HWND hwnd) {
131 return GetHelper()->GetDpiForWindow(hwnd);
132}
133
134UINT GetDpiForMonitor(HMONITOR monitor) {
135 return GetHelper()->GetDpiForMonitor(monitor);
136}
137} // namespace flutter
GAsyncResult * result
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
UINT GetDpiForHWND(HWND hwnd)
Definition: dpi_utils.cc:130
UINT GetDpiForMonitor(HMONITOR monitor)
Definition: dpi_utils.cc:134
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
#define T
Definition: precompiler.cc:65
int BOOL
Definition: windows_types.h:37
#define SUCCEEDED(hr)
unsigned int UINT
Definition: windows_types.h:32
HINSTANCE HMODULE
Definition: windows_types.h:96