diff --git a/shell/platform/windows/win32_dpi_helper.cc b/shell/platform/windows/win32_dpi_helper.cc index c31044ce2c767..5843def87e43f 100644 --- a/shell/platform/windows/win32_dpi_helper.cc +++ b/shell/platform/windows/win32_dpi_helper.cc @@ -18,7 +18,6 @@ Win32DpiHelper::Win32DpiHelper() { if (user32_module_ == nullptr) { return; } - if (!AssignProcAddress(user32_module_, "EnableNonClientDpiScaling", enable_non_client_dpi_scaling_)) { return; @@ -33,7 +32,6 @@ Win32DpiHelper::Win32DpiHelper() { set_process_dpi_awareness_context_)) { return; } - permonitorv2_supported_ = true; } @@ -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_; } @@ -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 diff --git a/shell/platform/windows/win32_dpi_helper.h b/shell/platform/windows/win32_dpi_helper.h index ddf51184bf956..013f215e540ae 100644 --- a/shell/platform/windows/win32_dpi_helper.h +++ b/shell/platform/windows/win32_dpi_helper.h @@ -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; diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index 43690efec2753..2b1c2bdc12141 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(); } @@ -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(), @@ -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{}; @@ -83,13 +81,16 @@ 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); + 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); 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