Browse Source

Handle DPI change on Windows 8.1+, add dpi-window-resize config option

rdb 10 years ago
parent
commit
042dc82416

+ 8 - 0
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 "
           "that is introduced in Windows 8.1.  Set this to false if you are "
           "experiencing problems with this setting."));
           "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
 ConfigVariableBool swapbuffer_framelock
 ("swapbuffer-framelock", false,
 ("swapbuffer-framelock", false,
  PRC_DESC("Set this true to enable HW swapbuffer frame-lock on 3dlabs cards"));
  PRC_DESC("Set this true to enable HW swapbuffer frame-lock on 3dlabs cards"));

+ 1 - 0
panda/src/windisplay/config_windisplay.h

@@ -31,6 +31,7 @@ extern ConfigVariableBool ime_aware;
 extern ConfigVariableBool ime_hide;
 extern ConfigVariableBool ime_hide;
 extern ConfigVariableBool request_dxdisplay_information;
 extern ConfigVariableBool request_dxdisplay_information;
 extern ConfigVariableBool dpi_aware;
 extern ConfigVariableBool dpi_aware;
+extern ConfigVariableBool dpi_window_resize;
 
 
 extern EXPCL_PANDAWIN ConfigVariableBool swapbuffer_framelock;
 extern EXPCL_PANDAWIN ConfigVariableBool swapbuffer_framelock;
 
 

+ 18 - 6
panda/src/windisplay/winGraphicsPipe.cxx

@@ -32,6 +32,12 @@ TypeHandle WinGraphicsPipe::_type_handle;
 #define MAXIMUM_PROCESSORS 32
 #define MAXIMUM_PROCESSORS 32
 #endif
 #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 {
 typedef struct _PROCESSOR_POWER_INFORMATION {
   ULONG Number;
   ULONG Number;
   ULONG MaxMhz;
   ULONG MaxMhz;
@@ -686,7 +692,6 @@ WinGraphicsPipe() {
   // these fns arent defined on win95, so get dynamic ptrs to them
   // these fns arent defined on win95, so get dynamic ptrs to them
   // to avoid ugly DLL loader failures on w95
   // to avoid ugly DLL loader failures on w95
   _pfnTrackMouseEvent = NULL;
   _pfnTrackMouseEvent = NULL;
-  _pfnSetProcessDPIAware = NULL;
 
 
   _hUser32 = (HINSTANCE)LoadLibrary("user32.dll");
   _hUser32 = (HINSTANCE)LoadLibrary("user32.dll");
   if (_hUser32 != NULL) {
   if (_hUser32 != NULL) {
@@ -694,13 +699,20 @@ WinGraphicsPipe() {
       (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent");
       (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent");
 
 
     if (dpi_aware) {
     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();
     }
     }
   }
   }
 
 

+ 0 - 3
panda/src/windisplay/winGraphicsPipe.h

@@ -45,9 +45,6 @@ private:
   typedef BOOL (WINAPI *PFN_TRACKMOUSEEVENT)(LPTRACKMOUSEEVENT);
   typedef BOOL (WINAPI *PFN_TRACKMOUSEEVENT)(LPTRACKMOUSEEVENT);
   PFN_TRACKMOUSEEVENT _pfnTrackMouseEvent;
   PFN_TRACKMOUSEEVENT _pfnTrackMouseEvent;
 
 
-  typedef BOOL (WINAPI *PFN_SETPROCESSDPIAWARE)(void);
-  PFN_SETPROCESSDPIAWARE _pfnSetProcessDPIAware;
-
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 26 - 0
panda/src/windisplay/winGraphicsWindow.cxx

@@ -26,6 +26,10 @@
 
 
 #include <tchar.h>
 #include <tchar.h>
 
 
+#ifndef WM_DPICHANGED
+#define WM_DPICHANGED 0x02E0
+#endif
+
 TypeHandle WinGraphicsWindow::_type_handle;
 TypeHandle WinGraphicsWindow::_type_handle;
 TypeHandle WinGraphicsWindow::WinWindowHandle::_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);
     system_changed_properties(properties);
     break;
     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
 #ifdef HAVE_WIN_TOUCHINPUT
   case WM_TOUCH:
   case WM_TOUCH:
         _numTouches = LOWORD(wparam);
         _numTouches = LOWORD(wparam);