From b4f720e13af42ab8067464bb677410d364af7365 Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Tue, 1 Oct 2019 15:38:30 -0700 Subject: [PATCH 1/6] Support system dpi awareness for older versions of Windows --- shell/platform/windows/win32_dpi_helper.cc | 28 ++++++++++++++++++++-- shell/platform/windows/win32_dpi_helper.h | 15 ++++++++++++ shell/platform/windows/win32_window.cc | 25 ++++++++++++------- shell/platform/windows/win32_window.h | 2 +- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.cc b/shell/platform/windows/win32_dpi_helper.cc index c31044ce2c767..1b23430ca9ec2 100644 --- a/shell/platform/windows/win32_dpi_helper.cc +++ b/shell/platform/windows/win32_dpi_helper.cc @@ -1,5 +1,7 @@ #include "flutter/shell/platform/windows/win32_dpi_helper.h" +#include + namespace flutter { namespace { @@ -18,7 +20,6 @@ Win32DpiHelper::Win32DpiHelper() { if (user32_module_ == nullptr) { return; } - if (!AssignProcAddress(user32_module_, "EnableNonClientDpiScaling", enable_non_client_dpi_scaling_)) { return; @@ -33,7 +34,6 @@ Win32DpiHelper::Win32DpiHelper() { set_process_dpi_awareness_context_)) { return; } - permonitorv2_supported_ = true; } @@ -43,6 +43,22 @@ Win32DpiHelper::~Win32DpiHelper() { } } +// SetAwareness +// Check the available api. Start with v2, then fall back. +void Win32DpiHelper::SetDpiAwerenessAllVersions() { + if (permonitorv2_supported_) { + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + } else { + std::cerr << "Per Monitor V2 DPI awareness is not supported on this " + "version of Windows. Setting System DPI awareness\n"; + AssignProcAddress(user32_module_, "GetDpiForSystem", get_dpi_for_system_); + AssignProcAddress(user32_module_, "SetProcessDpiAware", + set_process_dpi_aware_); + + SetProcessDPIAware(); + } +} + bool Win32DpiHelper::IsPerMonitorV2Available() { return permonitorv2_supported_; } @@ -61,6 +77,10 @@ UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) { return get_dpi_for_window_(hwnd); } +UINT Win32DpiHelper::GetDpiForSystem() { + return get_dpi_for_system_(); +} + BOOL Win32DpiHelper::SetProcessDpiAwarenessContext( DPI_AWARENESS_CONTEXT context) { if (!permonitorv2_supported_) { @@ -69,4 +89,8 @@ BOOL Win32DpiHelper::SetProcessDpiAwarenessContext( return set_process_dpi_awareness_context_(context); } +BOOL Win32DpiHelper::SetProcessDpiAware() { + return set_process_dpi_aware_(); +} + } // namespace flutter diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index ddf51184bf956..8ba635cee0859 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -28,17 +28,32 @@ class Win32DpiHelper { // Wrapper for OS functionality to return the DPI for |HWND| UINT GetDpiForWindow(HWND); + // Wrapper for OS functionality to return the DPI for the System. Only used if + // Per Monitor V2 is not supported by the current Windows version. + UINT GetDpiForSystem(); + // Sets the current process to a specified DPI awareness context. BOOL SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT); + // Sets the current process to System-level DPI awareness. + BOOL SetProcessDpiAware(); + + // Sets the DPI awareness for the application. For versions >= Windows 1703, + // use Per Monitor V2. For any older versions, use System. + void SetDpiAwerenessAllVersions(); + 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; diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index 43690efec2753..3462bd5067b09 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/win32_window.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flutter/shell/platform/windows/win32_window.h" +#include namespace flutter { @@ -26,7 +27,11 @@ 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. + dpi_helper_->SetDpiAwerenessAllVersions(); + + WNDCLASS window_class = RegisterWindowClass(converted_title); auto* result = CreateWindowEx( 0, window_class.lpszClassName, converted_title.c_str(), @@ -54,7 +59,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{}; @@ -83,13 +88,17 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, auto that = static_cast(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()) { + // 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); + } else { + that->current_dpi_ = that->dpi_helper_->GetDpiForSystem(); } - that->current_dpi_ = that->dpi_helper_->GetDpiForWindow(window); that->window_handle_ = window; } else if (Win32Window* that = GetThisFromHandle(window)) { return that->MessageHandler(window, message, wparam, lparam); diff --git a/shell/platform/windows/win32_window.h b/shell/platform/windows/win32_window.h index e670a52519308..63a00c355dea6 100644 --- a/shell/platform/windows/win32_window.h +++ b/shell/platform/windows/win32_window.h @@ -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 From e6db1e65567742c28f967bff1a9cea815a82cd2e Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Tue, 1 Oct 2019 18:42:24 -0700 Subject: [PATCH 2/6] Fix documentation --- shell/platform/windows/win32_dpi_helper.cc | 2 -- shell/platform/windows/win32_window.cc | 1 - 2 files changed, 3 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.cc b/shell/platform/windows/win32_dpi_helper.cc index 1b23430ca9ec2..eaa6be5765e01 100644 --- a/shell/platform/windows/win32_dpi_helper.cc +++ b/shell/platform/windows/win32_dpi_helper.cc @@ -43,8 +43,6 @@ Win32DpiHelper::~Win32DpiHelper() { } } -// SetAwareness -// Check the available api. Start with v2, then fall back. void Win32DpiHelper::SetDpiAwerenessAllVersions() { if (permonitorv2_supported_) { SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index 3462bd5067b09..1cda8cba0fb6b 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/win32_window.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "flutter/shell/platform/windows/win32_window.h" -#include namespace flutter { From c9b6c58a515e2ee8c0993b7fe265938656cb5cd0 Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Tue, 1 Oct 2019 18:46:26 -0700 Subject: [PATCH 3/6] Fix documentation --- shell/platform/windows/win32_dpi_helper.h | 3 +++ shell/platform/windows/win32_window.cc | 12 ++---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index 8ba635cee0859..196affab9f2e2 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -40,6 +40,9 @@ class Win32DpiHelper { // 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. void SetDpiAwerenessAllVersions(); private: diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index 1cda8cba0fb6b..702827da2915b 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/win32_window.cc @@ -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(); } From a1ff82e77a7e6c5e84083dade38b37eee1435d31 Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Wed, 2 Oct 2019 09:46:16 -0700 Subject: [PATCH 4/6] Address comments --- shell/platform/windows/win32_dpi_helper.cc | 34 +++++----------------- shell/platform/windows/win32_dpi_helper.h | 11 +++---- shell/platform/windows/win32_window.cc | 11 +++---- 3 files changed, 18 insertions(+), 38 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.cc b/shell/platform/windows/win32_dpi_helper.cc index eaa6be5765e01..5843def87e43f 100644 --- a/shell/platform/windows/win32_dpi_helper.cc +++ b/shell/platform/windows/win32_dpi_helper.cc @@ -1,7 +1,5 @@ #include "flutter/shell/platform/windows/win32_dpi_helper.h" -#include - namespace flutter { namespace { @@ -43,17 +41,17 @@ Win32DpiHelper::~Win32DpiHelper() { } } -void Win32DpiHelper::SetDpiAwerenessAllVersions() { +BOOL Win32DpiHelper::SetDpiAwareness() { if (permonitorv2_supported_) { - SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + return set_process_dpi_awareness_context_( + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + } else { - std::cerr << "Per Monitor V2 DPI awareness is not supported on this " - "version of Windows. Setting System DPI awareness\n"; AssignProcAddress(user32_module_, "GetDpiForSystem", get_dpi_for_system_); AssignProcAddress(user32_module_, "SetProcessDpiAware", set_process_dpi_aware_); - SetProcessDPIAware(); + return set_process_dpi_aware_(); } } @@ -68,27 +66,11 @@ BOOL Win32DpiHelper::EnableNonClientDpiScaling(HWND hwnd) { return enable_non_client_dpi_scaling_(hwnd); } -UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) { - if (!permonitorv2_supported_) { - return false; +UINT Win32DpiHelper::GetDpi(HWND hwnd) { + if (permonitorv2_supported_) { + return get_dpi_for_window_(hwnd); } - return get_dpi_for_window_(hwnd); -} - -UINT Win32DpiHelper::GetDpiForSystem() { return get_dpi_for_system_(); } -BOOL Win32DpiHelper::SetProcessDpiAwarenessContext( - DPI_AWARENESS_CONTEXT context) { - if (!permonitorv2_supported_) { - return false; - } - return set_process_dpi_awareness_context_(context); -} - -BOOL Win32DpiHelper::SetProcessDpiAware() { - return set_process_dpi_aware_(); -} - } // namespace flutter diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index 196affab9f2e2..3d55f72f6c9f2 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -25,12 +25,9 @@ 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 the System. Only used if - // Per Monitor V2 is not supported by the current Windows version. - UINT GetDpiForSystem(); + // 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); @@ -43,7 +40,7 @@ class Win32DpiHelper { // // This call is overriden if DPI awareness is stated in the application // manifest. - void SetDpiAwerenessAllVersions(); + BOOL SetDpiAwareness(); private: using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND); diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index 702827da2915b..2b1c2bdc12141 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/win32_window.cc @@ -20,7 +20,9 @@ void Win32Window::InitializeChild(const char* title, // Set DPI awareness for all Windows versions. This call has to be made before // the HWND is created. - dpi_helper_->SetDpiAwerenessAllVersions(); + if (!dpi_helper_->SetDpiAwareness()) { + OutputDebugString(L"Failed to set DPI awareness"); + } WNDCLASS window_class = RegisterWindowClass(converted_title); @@ -86,10 +88,9 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, if (result != TRUE) { OutputDebugString(L"Failed to enable non-client area autoscaling"); } - that->current_dpi_ = that->dpi_helper_->GetDpiForWindow(window); - } else { - that->current_dpi_ = that->dpi_helper_->GetDpiForSystem(); } + 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); @@ -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); From 924e8cea08b08312e3b00fff6bd5b6060590e2e0 Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Wed, 2 Oct 2019 09:46:57 -0700 Subject: [PATCH 5/6] Remove unused call --- shell/platform/windows/win32_dpi_helper.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index 3d55f72f6c9f2..6f06d8024d79e 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -29,9 +29,6 @@ class Win32DpiHelper { // 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 current process to System-level DPI awareness. BOOL SetProcessDpiAware(); From 2b900a07a22703b00a2c5241af2ff7972b0d0e47 Mon Sep 17 00:00:00 2001 From: Francisco Madgaleno Date: Wed, 2 Oct 2019 09:51:04 -0700 Subject: [PATCH 6/6] Another one --- shell/platform/windows/win32_dpi_helper.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index 6f06d8024d79e..013f215e540ae 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -29,9 +29,6 @@ class Win32DpiHelper { // awareness has been set. Otherwise, returns the DPI for the System. UINT GetDpi(HWND); - // Sets the current process to System-level DPI awareness. - BOOL SetProcessDpiAware(); - // Sets the DPI awareness for the application. For versions >= Windows 1703, // use Per Monitor V2. For any older versions, use System. //