Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions shell/platform/windows/win32_dpi_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Win32DpiHelper::Win32DpiHelper() {
if (user32_module_ == nullptr) {
return;
}

if (!AssignProcAddress(user32_module_, "EnableNonClientDpiScaling",
enable_non_client_dpi_scaling_)) {
return;
Expand All @@ -33,7 +32,6 @@ Win32DpiHelper::Win32DpiHelper() {
set_process_dpi_awareness_context_)) {
return;
}

permonitorv2_supported_ = true;
}

Expand All @@ -43,6 +41,20 @@ Win32DpiHelper::~Win32DpiHelper() {
}
}

BOOL Win32DpiHelper::SetDpiAwareness() {
if (permonitorv2_supported_) {
return set_process_dpi_awareness_context_(
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);

} else {
AssignProcAddress(user32_module_, "GetDpiForSystem", get_dpi_for_system_);
AssignProcAddress(user32_module_, "SetProcessDpiAware",
set_process_dpi_aware_);

return set_process_dpi_aware_();
}
}

bool Win32DpiHelper::IsPerMonitorV2Available() {
return permonitorv2_supported_;
}
Expand All @@ -54,19 +66,11 @@ BOOL Win32DpiHelper::EnableNonClientDpiScaling(HWND hwnd) {
return enable_non_client_dpi_scaling_(hwnd);
}

UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) {
if (!permonitorv2_supported_) {
return false;
}
return get_dpi_for_window_(hwnd);
}

BOOL Win32DpiHelper::SetProcessDpiAwarenessContext(
DPI_AWARENESS_CONTEXT context) {
if (!permonitorv2_supported_) {
return false;
UINT Win32DpiHelper::GetDpi(HWND hwnd) {
if (permonitorv2_supported_) {
return get_dpi_for_window_(hwnd);
}
return set_process_dpi_awareness_context_(context);
return get_dpi_for_system_();
}

} // namespace flutter
17 changes: 13 additions & 4 deletions shell/platform/windows/win32_dpi_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,29 @@ class Win32DpiHelper {
// Wrapper for OS functionality to turn on automatic window non-client scaling
BOOL EnableNonClientDpiScaling(HWND);

// Wrapper for OS functionality to return the DPI for |HWND|
UINT GetDpiForWindow(HWND);
// Wrapper for OS functionality to return the DPI for |HWND| if Per Monitor V2
// awareness has been set. Otherwise, returns the DPI for the System.
UINT GetDpi(HWND);

// Sets the current process to a specified DPI awareness context.
BOOL SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT);
// Sets the DPI awareness for the application. For versions >= Windows 1703,
// use Per Monitor V2. For any older versions, use System.
//
// This call is overriden if DPI awareness is stated in the application
// manifest.
BOOL SetDpiAwareness();

private:
using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND);
using GetDpiForWindow_ = UINT __stdcall(HWND);
using SetProcessDpiAwarenessContext_ = BOOL __stdcall(DPI_AWARENESS_CONTEXT);
using SetProcessDpiAware_ = BOOL __stdcall();
using GetDpiForSystem_ = UINT __stdcall();

EnableNonClientDpiScaling_* enable_non_client_dpi_scaling_ = nullptr;
GetDpiForWindow_* get_dpi_for_window_ = nullptr;
SetProcessDpiAwarenessContext_* set_process_dpi_awareness_context_ = nullptr;
SetProcessDpiAware_* set_process_dpi_aware_ = nullptr;
GetDpiForSystem_* get_dpi_for_system_ = nullptr;

HMODULE user32_module_ = nullptr;
bool permonitorv2_supported_ = false;
Expand Down
39 changes: 20 additions & 19 deletions shell/platform/windows/win32_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,8 @@

namespace flutter {

Win32Window::Win32Window() {
// Assume Windows 10 1703 or greater for DPI handling. When running on a
// older release of Windows where this context doesn't exist, DPI calls will
// fail and Flutter rendering will be impacted until this is fixed.
// To handle downlevel correctly, dpi_helper must use the most recent DPI
// context available should be used: Windows 1703: Per-Monitor V2, 8.1:
// Per-Monitor V1, Windows 7: System See
// https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
// for more information.
}
Win32Window::Win32Window() {}

Win32Window::~Win32Window() {
Destroy();
}
Expand All @@ -26,7 +18,13 @@ void Win32Window::InitializeChild(const char* title,
Destroy();
std::wstring converted_title = NarrowToWide(title);

WNDCLASS window_class = ResgisterWindowClass(converted_title);
// Set DPI awareness for all Windows versions. This call has to be made before
// the HWND is created.
if (!dpi_helper_->SetDpiAwareness()) {
OutputDebugString(L"Failed to set DPI awareness");
}

WNDCLASS window_class = RegisterWindowClass(converted_title);

auto* result = CreateWindowEx(
0, window_class.lpszClassName, converted_title.c_str(),
Expand Down Expand Up @@ -54,7 +52,7 @@ std::wstring Win32Window::NarrowToWide(const char* source) {
return wideTitle;
}

WNDCLASS Win32Window::ResgisterWindowClass(std::wstring& title) {
WNDCLASS Win32Window::RegisterWindowClass(std::wstring& title) {
window_class_name_ = title;

WNDCLASS window_class{};
Expand Down Expand Up @@ -83,13 +81,16 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window,

auto that = static_cast<Win32Window*>(cs->lpCreateParams);

// Since the application is running in Per-monitor V2 mode, turn on
// automatic titlebar scaling
BOOL result = that->dpi_helper_->EnableNonClientDpiScaling(window);
if (result != TRUE) {
OutputDebugString(L"Failed to enable non-client area autoscaling");
if (that->dpi_helper_->IsPerMonitorV2Available()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming you move the DPI mode setting logic into the client app, this would become a getter for the current DPI mode

// Since the application is running in Per-monitor V2 mode, turn on
// automatic titlebar scaling
BOOL result = that->dpi_helper_->EnableNonClientDpiScaling(window);
if (result != TRUE) {
OutputDebugString(L"Failed to enable non-client area autoscaling");
}
}
that->current_dpi_ = that->dpi_helper_->GetDpiForWindow(window);
that->current_dpi_ = that->dpi_helper_->GetDpi(window);

that->window_handle_ = window;
} else if (Win32Window* that = GetThisFromHandle(window)) {
return that->MessageHandler(window, message, wparam, lparam);
Expand Down Expand Up @@ -282,7 +283,7 @@ Win32Window::HandleDpiChange(HWND hwnd,
// The DPI is only passed for DPI change messages on top level windows,
// hence call function to get DPI if needed.
if (uDpi == 0) {
uDpi = dpi_helper_->GetDpiForWindow(hwnd);
uDpi = dpi_helper_->GetDpi(hwnd);
}
current_dpi_ = uDpi;
window->OnDpiScale(uDpi);
Expand Down
2 changes: 1 addition & 1 deletion shell/platform/windows/win32_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Win32Window {

// Registers a window class with default style attributes, cursor and
// icon.
WNDCLASS ResgisterWindowClass(std::wstring& title);
WNDCLASS RegisterWindowClass(std::wstring& title);

// OS callback called by message pump. Handles the WM_NCCREATE message which
// is passed when the non-client area is being created and enables automatic
Expand Down