| @@ -102,17 +102,38 @@ bool Desktop::canUseSemiTransparentWindows() noexcept | |||
| #endif | |||
| #ifndef MONITOR_DPI_TYPE | |||
| enum Monitor_DPI_Type | |||
| { | |||
| MDT_Effective_DPI = 0, | |||
| MDT_Angular_DPI = 1, | |||
| MDT_Raw_DPI = 2, | |||
| MDT_Default = MDT_Effective_DPI | |||
| }; | |||
| enum Process_DPI_Awareness | |||
| { | |||
| Process_DPI_Unaware = 0, | |||
| Process_System_DPI_Aware = 1, | |||
| Process_Per_Monitor_DPI_Aware = 2 | |||
| }; | |||
| #endif | |||
| typedef BOOL (WINAPI* RegisterTouchWindowFunc) (HWND, ULONG); | |||
| typedef BOOL (WINAPI* GetTouchInputInfoFunc) (HTOUCHINPUT, UINT, TOUCHINPUT*, int); | |||
| typedef BOOL (WINAPI* CloseTouchInputHandleFunc) (HTOUCHINPUT); | |||
| typedef BOOL (WINAPI* GetGestureInfoFunc) (HGESTUREINFO, GESTUREINFO*); | |||
| typedef BOOL (WINAPI* SetProcessDPIAwareFunc)(); | |||
| typedef BOOL (WINAPI* SetProcessDPIAwarenessFunc) (Process_DPI_Awareness); | |||
| typedef HRESULT (WINAPI* GetDPIForMonitorFunc) (HMONITOR, Monitor_DPI_Type, UINT*, UINT*); | |||
| static RegisterTouchWindowFunc registerTouchWindow = nullptr; | |||
| static GetTouchInputInfoFunc getTouchInputInfo = nullptr; | |||
| static CloseTouchInputHandleFunc closeTouchInputHandle = nullptr; | |||
| static GetGestureInfoFunc getGestureInfo = nullptr; | |||
| static SetProcessDPIAwareFunc setProcessDPIAware = nullptr; | |||
| static RegisterTouchWindowFunc registerTouchWindow = nullptr; | |||
| static GetTouchInputInfoFunc getTouchInputInfo = nullptr; | |||
| static CloseTouchInputHandleFunc closeTouchInputHandle = nullptr; | |||
| static GetGestureInfoFunc getGestureInfo = nullptr; | |||
| static SetProcessDPIAwareFunc setProcessDPIAware = nullptr; | |||
| static SetProcessDPIAwarenessFunc setProcessDPIAwareness = nullptr; | |||
| static GetDPIForMonitorFunc getDPIForMonitor = nullptr; | |||
| static bool hasCheckedForMultiTouch = false; | |||
| @@ -158,17 +179,33 @@ static void setDPIAwareness() | |||
| { | |||
| if (JUCEApplicationBase::isStandaloneApp()) | |||
| { | |||
| if (setProcessDPIAware == nullptr) | |||
| if (setProcessDPIAwareness == nullptr) | |||
| { | |||
| setProcessDPIAware = (SetProcessDPIAwareFunc) getUser32Function ("SetProcessDPIAware"); | |||
| HMODULE shcoreModule = GetModuleHandleA ("SHCore.dll"); | |||
| if (shcoreModule != 0) | |||
| { | |||
| setProcessDPIAwareness = (SetProcessDPIAwarenessFunc) GetProcAddress (shcoreModule, "SetProcessDpiAwareness"); | |||
| getDPIForMonitor = (GetDPIForMonitorFunc) GetProcAddress (shcoreModule, "GetDpiForMonitor"); | |||
| if (setProcessDPIAwareness != nullptr && getDPIForMonitor != nullptr | |||
| // && SUCCEEDED (setProcessDPIAwareness (Process_Per_Monitor_DPI_Aware))) | |||
| && SUCCEEDED (setProcessDPIAwareness (Process_System_DPI_Aware))) // (keep using this mode temporarily..) | |||
| return; | |||
| } | |||
| if (setProcessDPIAware == nullptr) | |||
| { | |||
| setProcessDPIAware = (SetProcessDPIAwareFunc) getUser32Function ("SetProcessDPIAware"); | |||
| if (setProcessDPIAware != nullptr) | |||
| setProcessDPIAware(); | |||
| if (setProcessDPIAware != nullptr) | |||
| setProcessDPIAware(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| static double getDPI() | |||
| static double getGlobalDPI() | |||
| { | |||
| setDPIAwareness(); | |||
| @@ -181,7 +218,7 @@ static double getDPI() | |||
| double Desktop::getDefaultMasterScale() | |||
| { | |||
| return JUCEApplicationBase::isStandaloneApp() ? getDPI() / 96.0 | |||
| return JUCEApplicationBase::isStandaloneApp() ? getGlobalDPI() / 96.0 | |||
| : 1.0; | |||
| } | |||
| @@ -2246,6 +2283,10 @@ private: | |||
| } | |||
| } | |||
| void handleDPIChange() // happens when a window moves to a screen with a different DPI. | |||
| { | |||
| } | |||
| //============================================================================== | |||
| public: | |||
| static LRESULT CALLBACK windowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) | |||
| @@ -2488,6 +2529,10 @@ private: | |||
| doSettingChange(); | |||
| break; | |||
| case 0x2e0: // WM_DPICHANGED | |||
| handleDPIChange(); | |||
| break; | |||
| case WM_INITMENU: | |||
| initialiseSysMenu ((HMENU) wParam); | |||
| break; | |||
| @@ -3183,10 +3228,12 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis | |||
| //============================================================================== | |||
| struct MonitorInfo | |||
| { | |||
| MonitorInfo (Rectangle<int> rect, bool main) noexcept : isMain (main), bounds (rect) {} | |||
| MonitorInfo (Rectangle<int> rect, bool main, double d) noexcept | |||
| : isMain (main), bounds (rect), dpi (d) {} | |||
| Rectangle<int> bounds; | |||
| bool isMain; | |||
| double dpi; | |||
| }; | |||
| static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userInfo) | |||
| @@ -3195,7 +3242,17 @@ static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userIn | |||
| info.cbSize = sizeof (info); | |||
| GetMonitorInfo (hm, &info); | |||
| const bool isMain = (info.dwFlags & 1 /* MONITORINFOF_PRIMARY */) != 0; | |||
| ((Array<MonitorInfo>*) userInfo)->add (MonitorInfo (rectangleFromRECT (*r), isMain)); | |||
| double dpi = 0; | |||
| if (getDPIForMonitor != nullptr) | |||
| { | |||
| UINT dpiX = 0, dpiY = 0; | |||
| if (SUCCEEDED (getDPIForMonitor (hm, MDT_Default, &dpiX, &dpiY))) | |||
| dpi = (dpiX + dpiY) / 2.0; | |||
| } | |||
| ((Array<MonitorInfo>*) userInfo)->add (MonitorInfo (rectangleFromRECT (*r), isMain, dpi)); | |||
| return TRUE; | |||
| } | |||
| @@ -3207,8 +3264,10 @@ void Desktop::Displays::findDisplays (float masterScale) | |||
| Array<MonitorInfo> monitors; | |||
| EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitors); | |||
| const double globalDPI = getGlobalDPI(); | |||
| if (monitors.size() == 0) | |||
| monitors.add (MonitorInfo (rectangleFromRECT (getWindowRect (GetDesktopWindow())), true)); | |||
| monitors.add (MonitorInfo (rectangleFromRECT (getWindowRect (GetDesktopWindow())), true, globalDPI)); | |||
| // make sure the first in the list is the main monitor | |||
| for (int i = 1; i < monitors.size(); ++i) | |||
| @@ -3218,15 +3277,22 @@ void Desktop::Displays::findDisplays (float masterScale) | |||
| RECT workArea; | |||
| SystemParametersInfo (SPI_GETWORKAREA, 0, &workArea, 0); | |||
| const double dpi = getDPI(); // (this has only one value for all monitors) | |||
| for (int i = 0; i < monitors.size(); ++i) | |||
| { | |||
| Display d; | |||
| d.userArea = d.totalArea = monitors.getReference(i).bounds / masterScale; | |||
| d.isMain = monitors.getReference(i).isMain; | |||
| d.scale = masterScale; | |||
| d.dpi = dpi; | |||
| d.dpi = monitors.getReference(i).dpi; | |||
| if (d.dpi == 0) | |||
| { | |||
| d.scale = masterScale; | |||
| d.dpi = globalDPI; | |||
| } | |||
| else | |||
| { | |||
| d.scale = d.dpi / 96.0; | |||
| } | |||
| if (d.isMain) | |||
| d.userArea = d.userArea.getIntersection (rectangleFromRECT (workArea) / masterScale); | |||