Skip to content

Commit bac380c

Browse files
franciscojma86NoamDev
authored andcommitted
Expose DPI helper functions for Runner apps to use (flutter#16313)
1 parent 3bd4051 commit bac380c

16 files changed

+338
-181
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,9 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flu
11161116
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
11171117
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h
11181118
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
1119+
FILE: ../../../flutter/shell/platform/windows/dpi_utils.cc
1120+
FILE: ../../../flutter/shell/platform/windows/dpi_utils.h
1121+
FILE: ../../../flutter/shell/platform/windows/dpi_utils_unittests.cc
11191122
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
11201123
FILE: ../../../flutter/shell/platform/windows/key_event_handler.cc
11211124
FILE: ../../../flutter/shell/platform/windows/key_event_handler.h
@@ -1125,10 +1128,9 @@ FILE: ../../../flutter/shell/platform/windows/platform_handler.h
11251128
FILE: ../../../flutter/shell/platform/windows/public/flutter_windows.h
11261129
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.cc
11271130
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.h
1128-
FILE: ../../../flutter/shell/platform/windows/win32_dpi_helper.cc
1129-
FILE: ../../../flutter/shell/platform/windows/win32_dpi_helper.h
11301131
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.cc
11311132
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.h
1133+
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window_unittests.cc
11321134
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.cc
11331135
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.h
11341136
FILE: ../../../flutter/shell/platform/windows/win32_window.cc

shell/platform/windows/BUILD.gn

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ source_set("flutter_windows_source") {
4141
sources = [
4242
"angle_surface_manager.cc",
4343
"angle_surface_manager.h",
44+
"dpi_utils.cc",
45+
"dpi_utils.h",
4446
"flutter_windows.cc",
4547
"key_event_handler.cc",
4648
"key_event_handler.h",
@@ -49,8 +51,6 @@ source_set("flutter_windows_source") {
4951
"platform_handler.h",
5052
"text_input_plugin.cc",
5153
"text_input_plugin.h",
52-
"win32_dpi_helper.cc",
53-
"win32_dpi_helper.h",
5454
"win32_flutter_window.cc",
5555
"win32_flutter_window.h",
5656
"win32_task_runner.cc",
@@ -109,8 +109,12 @@ executable("flutter_windows_unittests") {
109109
testonly = true
110110

111111
sources = [
112+
"dpi_utils_unittests.cc",
112113
"testing/win32_flutter_window_test.cc",
113114
"testing/win32_flutter_window_test.h",
115+
"testing/win32_window_test.cc",
116+
"testing/win32_window_test.h",
117+
"win32_flutter_window_unittests.cc",
114118
"win32_window_unittests.cc",
115119
]
116120

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

shell/platform/windows/dpi_utils.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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 "Windows.h"
6+
7+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_
8+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_
9+
10+
namespace flutter {
11+
12+
/// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is
13+
/// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns the
14+
/// DPI for the primary monitor. If Per-Monitor DPI awareness is not available,
15+
/// returns the system's DPI.
16+
UINT GetDpiForHWND(HWND hwnd);
17+
18+
/// Returns the DPI of a given monitor. Defaults to 96 if the API is not
19+
/// available.
20+
UINT GetDpiForMonitor(HMONITOR monitor);
21+
22+
} // namespace flutter
23+
24+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <windows.h>
2+
3+
#include "flutter/shell/platform/windows/dpi_utils.h"
4+
#include "gtest/gtest.h"
5+
6+
namespace flutter {
7+
namespace testing {
8+
9+
TEST(DpiUtilsTest, NonZero) {
10+
ASSERT_GT(GetDpiForHWND(nullptr), 0);
11+
ASSERT_GT(GetDpiForMonitor(nullptr), 0);
12+
};
13+
14+
TEST(DpiUtilsTest, NullHwndUsesPrimaryMonitor) {
15+
const POINT target_point = {0, 0};
16+
HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY);
17+
ASSERT_EQ(GetDpiForHWND(nullptr), GetDpiForMonitor(monitor));
18+
};
19+
20+
} // namespace testing
21+
} // namespace flutter

shell/platform/windows/flutter_windows.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
1616
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
1717
#include "flutter/shell/platform/embedder/embedder.h"
18+
#include "flutter/shell/platform/windows/dpi_utils.h"
1819
#include "flutter/shell/platform/windows/key_event_handler.h"
1920
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
2021
#include "flutter/shell/platform/windows/platform_handler.h"
@@ -182,6 +183,14 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) {
182183
return view->window->GetWindowHandle();
183184
}
184185

186+
UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
187+
return flutter::GetDpiForHWND(hwnd);
188+
}
189+
190+
UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
191+
return flutter::GetDpiForMonitor(monitor);
192+
}
193+
185194
FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
186195
const char* icu_data_path,
187196
const char** arguments,

shell/platform/windows/public/flutter_windows.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ FlutterDesktopProcessMessages(FlutterDesktopViewControllerRef controller);
7777
// Return backing HWND for manipulation in host application.
7878
FLUTTER_EXPORT HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view);
7979

80+
// Gets the DPI for a given |hwnd|, depending on the supported APIs per
81+
// windows version and DPI awareness mode. If nullptr is passed, returns the DPI
82+
// of the primary monitor.
83+
FLUTTER_EXPORT UINT FlutterDesktopGetDpiForHWND(HWND hwnd);
84+
85+
// Gets the DPI for a given |monitor|. If the API is not available, a default
86+
// DPI of 96 is returned.
87+
FLUTTER_EXPORT UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor);
88+
8089
// Runs an instance of a headless Flutter engine.
8190
//
8291
// The |assets_path| is the path to the flutter_assets folder for the Flutter

shell/platform/windows/testing/win32_flutter_window_test.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,28 @@
44

55
#include <windowsx.h>
66

7-
#include "flutter/fml/macros.h"
87
#include "flutter/shell/platform/windows/win32_flutter_window.h"
98

109
namespace flutter {
1110
namespace testing {
1211

12+
/// Test class for Win32FlutterWindow.
1313
class Win32FlutterWindowTest : public Win32FlutterWindow {
1414
public:
1515
Win32FlutterWindowTest(int width, int height);
16-
1716
virtual ~Win32FlutterWindowTest();
1817

18+
// Prevent copying.
19+
Win32FlutterWindowTest(Win32FlutterWindowTest const&) = delete;
20+
Win32FlutterWindowTest& operator=(Win32FlutterWindowTest const&) = delete;
21+
1922
// |Win32Window|
2023
void OnFontChange() override;
2124

2225
bool OnFontChangeWasCalled();
2326

2427
private:
2528
bool on_font_change_called_ = false;
26-
27-
FML_DISALLOW_COPY_AND_ASSIGN(Win32FlutterWindowTest);
2829
};
2930

3031
} // namespace testing
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "flutter/shell/platform/windows/testing/win32_window_test.h"
2+
3+
namespace flutter {
4+
namespace testing {
5+
6+
Win32WindowTest::Win32WindowTest() : Win32Window(){};
7+
8+
Win32WindowTest::~Win32WindowTest() = default;
9+
10+
void Win32WindowTest::OnDpiScale(unsigned int dpi){};
11+
12+
void Win32WindowTest::OnResize(unsigned int width, unsigned int height) {}
13+
14+
void Win32WindowTest::OnPointerMove(double x, double y) {}
15+
16+
void Win32WindowTest::OnPointerDown(double x, double y, UINT button) {}
17+
18+
void Win32WindowTest::OnPointerUp(double x, double y, UINT button) {}
19+
20+
void Win32WindowTest::OnPointerLeave() {}
21+
22+
void Win32WindowTest::OnChar(char32_t code_point) {}
23+
24+
void Win32WindowTest::OnKey(int key, int scancode, int action, int mods) {}
25+
26+
void Win32WindowTest::OnScroll(double delta_x, double delta_y) {}
27+
28+
void Win32WindowTest::OnFontChange() {}
29+
30+
UINT Win32WindowTest::GetDpi() {
31+
return GetCurrentDPI();
32+
}
33+
34+
} // namespace testing
35+
} // namespace flutter
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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 <windowsx.h>
6+
7+
#include "flutter/shell/platform/windows/win32_window.h"
8+
9+
namespace flutter {
10+
namespace testing {
11+
12+
/// Test class for the Win32Window base class. Used to access protected methods
13+
/// for testing.
14+
class Win32WindowTest : public Win32Window {
15+
public:
16+
Win32WindowTest();
17+
virtual ~Win32WindowTest();
18+
19+
// Prevent copying.
20+
Win32WindowTest(Win32WindowTest const&) = delete;
21+
Win32WindowTest& operator=(Win32WindowTest const&) = delete;
22+
23+
// Wrapper for GetCurrentDPI() which is a protected method.
24+
UINT GetDpi();
25+
26+
// |Win32Window|
27+
void OnDpiScale(unsigned int dpi) override;
28+
29+
// |Win32Window|
30+
void OnResize(unsigned int width, unsigned int height) override;
31+
32+
// |Win32Window|
33+
void OnPointerMove(double x, double y) override;
34+
35+
// |Win32Window|
36+
void OnPointerDown(double x, double y, UINT button) override;
37+
38+
// |Win32Window|
39+
void OnPointerUp(double x, double y, UINT button) override;
40+
41+
// |Win32Window|
42+
void OnPointerLeave() override;
43+
44+
// |Win32Window|
45+
void OnChar(char32_t code_point) override;
46+
47+
// |Win32Window|
48+
void OnKey(int key, int scancode, int action, int mods) override;
49+
50+
// |Win32Window|
51+
void OnScroll(double delta_x, double delta_y) override;
52+
53+
// |Win32Window|
54+
void OnFontChange() override;
55+
};
56+
57+
} // namespace testing
58+
} // namespace flutter

0 commit comments

Comments
 (0)