From 042dc824163f7bd9b31cb966bd72543c12c18745 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 5 Nov 2015 20:43:33 +0100 Subject: [PATCH] Handle DPI change on Windows 8.1+, add dpi-window-resize config option --- panda/src/windisplay/config_windisplay.cxx | 8 +++++++ panda/src/windisplay/config_windisplay.h | 1 + panda/src/windisplay/winGraphicsPipe.cxx | 24 +++++++++++++++----- panda/src/windisplay/winGraphicsPipe.h | 3 --- panda/src/windisplay/winGraphicsWindow.cxx | 26 ++++++++++++++++++++++ 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/panda/src/windisplay/config_windisplay.cxx b/panda/src/windisplay/config_windisplay.cxx index e0bda2979e..4d8f8efc5b 100644 --- a/panda/src/windisplay/config_windisplay.cxx +++ b/panda/src/windisplay/config_windisplay.cxx @@ -71,6 +71,14 @@ ConfigVariableBool dpi_aware "that is introduced in Windows 8.1. Set this to false if you are " "experiencing problems with this setting.")); +ConfigVariableBool dpi_window_resize +("dpi-window-resize", false, + PRC_DESC("Set this to true to let Panda3D resize the window according to the " + "DPI settings whenever the window is dragged to a monitor with " + "different DPI, or when the DPI setting is changed in the control " + "panel. Only available in Windows 8.1 and later, and requires " + "dpi-aware to be set as well.")); + ConfigVariableBool swapbuffer_framelock ("swapbuffer-framelock", false, PRC_DESC("Set this true to enable HW swapbuffer frame-lock on 3dlabs cards")); diff --git a/panda/src/windisplay/config_windisplay.h b/panda/src/windisplay/config_windisplay.h index f3f7cb1ea4..a620b4e64a 100644 --- a/panda/src/windisplay/config_windisplay.h +++ b/panda/src/windisplay/config_windisplay.h @@ -31,6 +31,7 @@ extern ConfigVariableBool ime_aware; extern ConfigVariableBool ime_hide; extern ConfigVariableBool request_dxdisplay_information; extern ConfigVariableBool dpi_aware; +extern ConfigVariableBool dpi_window_resize; extern EXPCL_PANDAWIN ConfigVariableBool swapbuffer_framelock; diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index eb56ec2f10..8fd031ffef 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -32,6 +32,12 @@ TypeHandle WinGraphicsPipe::_type_handle; #define MAXIMUM_PROCESSORS 32 #endif +typedef enum _Process_DPI_Awareness { + Process_DPI_Unaware = 0, + Process_System_DPI_Aware = 1, + Process_Per_Monitor_DPI_Aware = 2 +} Process_DPI_Awareness; + typedef struct _PROCESSOR_POWER_INFORMATION { ULONG Number; ULONG MaxMhz; @@ -686,7 +692,6 @@ WinGraphicsPipe() { // these fns arent defined on win95, so get dynamic ptrs to them // to avoid ugly DLL loader failures on w95 _pfnTrackMouseEvent = NULL; - _pfnSetProcessDPIAware = NULL; _hUser32 = (HINSTANCE)LoadLibrary("user32.dll"); if (_hUser32 != NULL) { @@ -694,13 +699,20 @@ WinGraphicsPipe() { (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent"); if (dpi_aware) { - _pfnSetProcessDPIAware = - (PFN_SETPROCESSDPIAWARE)GetProcAddress(_hUser32, "SetProcessDPIAware"); + typedef HRESULT (WINAPI *PFN_SETPROCESSDPIAWARENESS)(Process_DPI_Awareness); + PFN_SETPROCESSDPIAWARENESS pfnSetProcessDpiAwareness = + (PFN_SETPROCESSDPIAWARENESS)GetProcAddress(_hUser32, "SetProcessDpiAwarenessInternal"); - if (windisplay_cat.is_debug()) { - windisplay_cat.debug() << "Calling SetProcessDPIAware().\n"; + if (pfnSetProcessDpiAwareness == NULL) { + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() << "Unable to find SetProcessDpiAwareness in user32.dll.\n"; + } + } else { + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() << "Calling SetProcessDpiAwareness().\n"; + } + pfnSetProcessDpiAwareness(Process_Per_Monitor_DPI_Aware); } - _pfnSetProcessDPIAware(); } } diff --git a/panda/src/windisplay/winGraphicsPipe.h b/panda/src/windisplay/winGraphicsPipe.h index 2afeaf0b94..88d3e264d6 100644 --- a/panda/src/windisplay/winGraphicsPipe.h +++ b/panda/src/windisplay/winGraphicsPipe.h @@ -45,9 +45,6 @@ private: typedef BOOL (WINAPI *PFN_TRACKMOUSEEVENT)(LPTRACKMOUSEEVENT); PFN_TRACKMOUSEEVENT _pfnTrackMouseEvent; - typedef BOOL (WINAPI *PFN_SETPROCESSDPIAWARE)(void); - PFN_SETPROCESSDPIAWARE _pfnSetProcessDPIAware; - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 5018fb8a4a..f270a70f61 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -26,6 +26,10 @@ #include +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif + TypeHandle WinGraphicsWindow::_type_handle; TypeHandle WinGraphicsWindow::WinWindowHandle::_type_handle; @@ -2151,6 +2155,28 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { system_changed_properties(properties); break; + case WM_DPICHANGED: + // The window moved to a monitor of different DPI, or someone changed + // the DPI setting in the configuration panel. + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() << "DPI changed to " << LOWORD(wparam); + + if (LOWORD(wparam) != HIWORD(wparam)) { + windisplay_cat.debug(false) << "x" << HIWORD(wparam) << "\n"; + } else { + windisplay_cat.debug(false) << "\n"; + } + } + // Resize the window if requested to match the new DPI. + // Obviously, don't do this if a fixed size was requested. + if (!_properties.get_fixed_size() && dpi_window_resize) { + RECT &rect = *(LPRECT)lparam; + SetWindowPos(_hWnd, HWND_TOP, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_NOZORDER | SWP_NOACTIVATE); + } + break; + #ifdef HAVE_WIN_TOUCHINPUT case WM_TOUCH: _numTouches = LOWORD(wparam);