Flutter Engine
 
Loading...
Searching...
No Matches
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
8
9namespace flutter {
10
11namespace {
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.
16constexpr UINT kEffectiveDpiMonitorType = 0;
17
18template <typename T>
19
20/// Retrieves a function |name| from a given |comBaseModule| into |outProc|.
21/// Returns a bool indicating whether the function was found.
22bool 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.
29class 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
63};
64
65DpiHelper::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
76DpiHelper::~DpiHelper() {
77 if (user32_module_ != nullptr) {
78 FreeLibrary(user32_module_);
79 }
80 if (shlib_module_ != nullptr) {
81 FreeLibrary(shlib_module_);
82 }
83}
84
85UINT 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
106UINT 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
122DpiHelper* GetHelper() {
123 static DpiHelper* dpi_helper = new DpiHelper();
124 return dpi_helper;
125}
126} // namespace
127
128UINT GetDpiForHWND(HWND hwnd) {
129 return GetHelper()->GetDpiForWindow(hwnd);
130}
131
132UINT GetDpiForMonitor(HMONITOR monitor) {
133 return GetHelper()->GetDpiForMonitor(monitor);
134}
135} // namespace flutter
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
UINT GetDpiForHWND(HWND hwnd)
Definition dpi_utils.cc:128
UINT GetDpiForMonitor(HMONITOR monitor)
Definition dpi_utils.cc:132
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
constexpr UINT kDefaultDpi
Definition dpi_utils.h:12
int BOOL
#define SUCCEEDED(hr)
unsigned int UINT
HINSTANCE HMODULE