From e8e9fa24185ca476c5a219b3ae12730e1501bf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20M=C3=B6hlmann?= Date: Thu, 2 Aug 2018 19:03:15 +0200 Subject: [PATCH] fix assertion failed: validate_hidpi_factor(dpi_factor) (#607) (#618) * fix assertion failed: validate_hidpi_factor(dpi_factor) (#607) * added changelog entry --- CHANGELOG.md | 1 + src/platform/windows/dpi.rs | 19 ++++++------------- src/platform/windows/window.rs | 18 ++++++------------ 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0370646..315cfd37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - On iOS, the `UIApplication` is not started until `Window::new` is called. - Fixed thread unsafety with cursor hiding on macOS. - On iOS, fixed the size of the `JmpBuf` type used for `setjmp`/`longjmp` calls. Previously this was a buffer overflow on most architectures. +- On Windows, use cached window DPI instead of repeatedly querying the system. This fixes sporadic crashes on Windows 7. # Version 0.16.2 (2018-07-07) diff --git a/src/platform/windows/dpi.rs b/src/platform/windows/dpi.rs index 9238d20c..ea4bc655 100644 --- a/src/platform/windows/dpi.rs +++ b/src/platform/windows/dpi.rs @@ -8,7 +8,6 @@ use winapi::shared::minwindef::{BOOL, UINT, FALSE}; use winapi::shared::windef::{ DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, - HDC, HMONITOR, HWND, }; @@ -145,7 +144,11 @@ pub fn dpi_to_scale_factor(dpi: u32) -> f64 { dpi as f64 / BASE_DPI as f64 } -pub unsafe fn get_window_dpi(hwnd: HWND, hdc: HDC) -> u32 { +pub unsafe fn get_hwnd_dpi(hwnd: HWND) -> u32 { + let hdc = winuser::GetDC(hwnd); + if hdc.is_null() { + panic!("[winit] `GetDC` returned null!"); + } if let Some(GetDpiForWindow) = *GET_DPI_FOR_WINDOW { // We are on Windows 10 Anniversary Update (1607) or later. match GetDpiForWindow(hwnd) { @@ -181,16 +184,6 @@ pub unsafe fn get_window_dpi(hwnd: HWND, hdc: HDC) -> u32 { } } -// Use this when you have both the HWND and HDC on hand (i.e. window methods) -pub fn get_window_scale_factor(hwnd: HWND, hdc: HDC) -> f64 { - dpi_to_scale_factor(unsafe { get_window_dpi(hwnd, hdc) }) -} - -// Use this when you only have the HWND (i.e. event handling) pub fn get_hwnd_scale_factor(hwnd: HWND) -> f64 { - let hdc = unsafe { winuser::GetDC(hwnd) }; - if hdc.is_null() { - panic!("[winit] `GetDC` returned null!"); - } - unsafe { get_window_scale_factor(hwnd, hdc) } + dpi_to_scale_factor(unsafe { get_hwnd_dpi(hwnd) }) } diff --git a/src/platform/windows/window.rs b/src/platform/windows/window.rs index d961fc38..230eb452 100644 --- a/src/platform/windows/window.rs +++ b/src/platform/windows/window.rs @@ -9,7 +9,7 @@ use std::sync::mpsc::channel; use winapi::ctypes::c_int; use winapi::shared::minwindef::{BOOL, DWORD, FALSE, LPARAM, TRUE, UINT, WORD, WPARAM}; -use winapi::shared::windef::{HDC, HWND, LPPOINT, POINT, RECT}; +use winapi::shared::windef::{HWND, LPPOINT, POINT, RECT}; use winapi::um::{combaseapi, dwmapi, libloaderapi, winuser}; use winapi::um::objbase::COINIT_MULTITHREADED; use winapi::um::shobjidl_core::{CLSID_TaskbarList, ITaskbarList2}; @@ -26,7 +26,7 @@ use { WindowAttributes, }; use platform::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId}; -use platform::platform::dpi::{dpi_to_scale_factor, get_window_dpi, get_window_scale_factor}; +use platform::platform::dpi::{dpi_to_scale_factor, get_hwnd_dpi}; use platform::platform::events_loop::{self, EventsLoop, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID}; use platform::platform::events_loop::WindowState; use platform::platform::icon::{self, IconType, WinIcon}; @@ -417,7 +417,7 @@ impl Window { #[inline] pub fn get_hidpi_factor(&self) -> f64 { - get_window_scale_factor(self.window.0, self.window.1) + self.window_state.lock().unwrap().dpi_factor } fn set_cursor_position_physical(&self, x: i32, y: i32) -> Result<(), String> { @@ -773,7 +773,7 @@ impl Drop for Window { /// A simple non-owning wrapper around a window. #[doc(hidden)] #[derive(Clone)] -pub struct WindowWrapper(HWND, HDC); +pub struct WindowWrapper(HWND); // Send and Sync are not implemented for HWND and HDC, we have to wrap it and implement them manually. // For more info see: @@ -954,13 +954,7 @@ unsafe fn init( format!("{}", io::Error::last_os_error())))); } - let hdc = winuser::GetDC(handle); - if hdc.is_null() { - return Err(CreationError::OsError(format!("GetDC function failed: {}", - format!("{}", io::Error::last_os_error())))); - } - - WindowWrapper(handle, hdc) + WindowWrapper(handle) }; // Set up raw input @@ -974,7 +968,7 @@ unsafe fn init( } } - let dpi = get_window_dpi(real_window.0, real_window.1); + let dpi = get_hwnd_dpi(real_window.0); let dpi_factor = dpi_to_scale_factor(dpi); if dpi_factor != guessed_dpi_factor { let (width, height): (u32, u32) = dimensions.into();