diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs index 6caf7f651..57aeccbc7 100644 --- a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs +++ b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs @@ -124,7 +124,7 @@ namespace FlaxEditor.GUI.ContextMenu PerformLayout(); // Calculate popup direction and initial location (fit on a single monitor) - var dpiScale = Platform.DpiScale; + var dpiScale = parentWin.Window.DpiScale; Vector2 dpiSize = Size * dpiScale; Vector2 locationWS = parent.PointToWindow(location); Vector2 locationSS = parentWin.PointToScreen(locationWS); @@ -275,7 +275,7 @@ namespace FlaxEditor.GUI.ContextMenu { if (_window != null) { - _window.ClientSize = Size * Platform.DpiScale; + _window.ClientSize = Size * _window.DpiScale; } } diff --git a/Source/Editor/GUI/Dialogs/Dialog.cs b/Source/Editor/GUI/Dialogs/Dialog.cs index 173dd9128..c33429609 100644 --- a/Source/Editor/GUI/Dialogs/Dialog.cs +++ b/Source/Editor/GUI/Dialogs/Dialog.cs @@ -143,7 +143,7 @@ namespace FlaxEditor.GUI.Dialogs // Setup initial window settings CreateWindowSettings settings = CreateWindowSettings.Default; settings.Title = _title; - settings.Size = _dialogSize * Platform.DpiScale; + settings.Size = _dialogSize * parentWindow.DpiScale; settings.AllowMaximize = false; settings.AllowMinimize = false; settings.HasSizingFrame = false; diff --git a/Source/Editor/GUI/Docking/DockPanel.cs b/Source/Editor/GUI/Docking/DockPanel.cs index f6e10e653..23b70f719 100644 --- a/Source/Editor/GUI/Docking/DockPanel.cs +++ b/Source/Editor/GUI/Docking/DockPanel.cs @@ -123,9 +123,8 @@ namespace FlaxEditor.GUI.Docking if (parentWin == null) throw new InvalidOperationException("Missing parent window."); var control = _tabsProxy != null ? (Control)_tabsProxy : this; - var dpiScale = Platform.DpiScale; var clientPos = control.PointToWindow(Vector2.Zero); - return new Rectangle(parentWin.PointToScreen(clientPos), control.Size * dpiScale); + return new Rectangle(parentWin.PointToScreen(clientPos), control.Size * RootWindow.Window.DpiScale); } } diff --git a/Source/Editor/GUI/MainMenu.cs b/Source/Editor/GUI/MainMenu.cs index 7c49d85ac..f0f9458e7 100644 --- a/Source/Editor/GUI/MainMenu.cs +++ b/Source/Editor/GUI/MainMenu.cs @@ -185,14 +185,14 @@ namespace FlaxEditor.GUI private WindowHitCodes OnHitTest(ref Vector2 mouse) { - var pos = _window.ScreenToClient(mouse * Platform.DpiScale); + var dpiScale = _window.DpiScale; + var pos = _window.ScreenToClient(mouse * dpiScale); if (_window.IsMinimized) return WindowHitCodes.NoWhere; if (!_window.IsMaximized) { - var dpiScale = Platform.DpiScale; var winSize = RootWindow.Size * dpiScale; // Distance from which the mouse is considered to be on the border/corner @@ -227,7 +227,7 @@ namespace FlaxEditor.GUI var controlUnderMouse = GetChildAt(menuPos); var isMouseOverSth = controlUnderMouse != null && controlUnderMouse != _title; var rb = GetRightButton(); - if (rb != null && _minimizeButton != null && new Rectangle(rb.UpperRight * Platform.DpiScale, (_minimizeButton.BottomLeft - rb.UpperRight) * Platform.DpiScale).Contains(ref menuPos) && !isMouseOverSth) + if (rb != null && _minimizeButton != null && new Rectangle(rb.UpperRight * dpiScale, (_minimizeButton.BottomLeft - rb.UpperRight) * dpiScale).Contains(ref menuPos) && !isMouseOverSth) return WindowHitCodes.Caption; return WindowHitCodes.Client; diff --git a/Source/Editor/Modules/WindowsModule.cs b/Source/Editor/Modules/WindowsModule.cs index a8058b9d8..9dc6d4f93 100644 --- a/Source/Editor/Modules/WindowsModule.cs +++ b/Source/Editor/Modules/WindowsModule.cs @@ -709,7 +709,7 @@ namespace FlaxEditor.Modules var dpiScale = Platform.DpiScale; var settings = CreateWindowSettings.Default; settings.Title = "Flax Editor"; - settings.Size = new Vector2(1300 * dpiScale, 900 * dpiScale); + settings.Size = new Vector2(1300 * dpiScale, 900 * dpiScale); // TODO: Place the window on the correct screen (and use that screen's size) settings.StartPosition = WindowStartPosition.CenterScreen; if (!Editor.Instance.Options.Options.Interface.UseNativeWindowSystem) diff --git a/Source/Editor/Surface/ContextMenu/ContentFinder.cs b/Source/Editor/Surface/ContextMenu/ContentFinder.cs index 76e8d2e33..fd986f4f5 100644 --- a/Source/Editor/Surface/ContextMenu/ContentFinder.cs +++ b/Source/Editor/Surface/ContextMenu/ContentFinder.cs @@ -108,11 +108,13 @@ namespace FlaxEditor.Surface.ContextMenu { _resultPanel.DisposeChildren(); + var dpiScale = RootWindow.Window.DpiScale; + if (items.Count == 0) { Height = _searchBox.Height + 1; _resultPanel.ScrollBars = ScrollBars.None; - RootWindow.Window.ClientSize = new Vector2(RootWindow.Window.ClientSize.X, Height * Platform.DpiScale); + RootWindow.Window.ClientSize = new Vector2(RootWindow.Window.ClientSize.X, Height * dpiScale); return; } @@ -146,7 +148,7 @@ namespace FlaxEditor.Surface.ContextMenu MatchedItems.Add(searchItem); } - RootWindow.Window.ClientSize = new Vector2(RootWindow.Window.ClientSize.X, Height * Platform.DpiScale); + RootWindow.Window.ClientSize = new Vector2(RootWindow.Window.ClientSize.X, Height * dpiScale); PerformLayout(); } diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index ac34d9e45..18dff245f 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1657,7 +1657,7 @@ namespace FlaxEditor.Utilities settings.AllowMinimize = false; settings.HasSizingFrame = false; settings.StartPosition = WindowStartPosition.CenterScreen; - settings.Size = new Vector2(500, 600) * Platform.DpiScale; + settings.Size = new Vector2(500, 600) * Platform.DpiScale; // TODO: Place the window on the correct screen (and use that screen's size) settings.Title = title; var dialog = Platform.CreateWindow(ref settings); diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h index 3da48bb7a..6fab84504 100644 --- a/Source/Engine/Platform/Base/WindowBase.h +++ b/Source/Engine/Platform/Base/WindowBase.h @@ -281,6 +281,8 @@ protected: String _title; CursorType _cursor; Vector2 _clientSize; + int _dpi; + float _dpiScale; Vector2 _trackingMouseOffset; bool _isUsingMouseOffset; @@ -541,6 +543,22 @@ public: /// The screen space position. API_FUNCTION() virtual Vector2 ClientToScreen(const Vector2& clientPos) const = 0; + /// + /// Gets the window DPI setting. + /// + API_PROPERTY() int GetDpi() const + { + return _dpi; + } + + // TODO: This doesn't actually include the custom DPI scale + /// + /// Gets the window DPI scale factor (1 is default). Includes custom DPI scale + /// + API_PROPERTY() float GetDpiScale() const + { + return Platform::CustomDpiScale * _dpiScale; + } public: /// diff --git a/Source/Engine/Platform/Window.cs b/Source/Engine/Platform/Window.cs index 8a8a19c01..d000c6f90 100644 --- a/Source/Engine/Platform/Window.cs +++ b/Source/Engine/Platform/Window.cs @@ -7,8 +7,6 @@ namespace FlaxEngine { partial class Window { - internal float _dpiScale; - /// /// Window closing delegate. /// @@ -176,7 +174,6 @@ namespace FlaxEngine private Window() { GUI = new WindowRootControl(this); - _dpiScale = Platform.DpiScale; } internal void Internal_OnShow() @@ -192,7 +189,7 @@ namespace FlaxEngine internal void Internal_OnDraw() { - Matrix3x3.Scaling(_dpiScale, out var scale); + Matrix3x3.Scaling(DpiScale, out var scale); Render2D.PushTransform(ref scale); GUI.Draw(); Render2D.PopTransform(); @@ -200,7 +197,7 @@ namespace FlaxEngine internal void Internal_OnResize(int width, int height) { - GUI.Size = new Vector2(width / _dpiScale, height / _dpiScale); + GUI.Size = new Vector2(width / DpiScale, height / DpiScale); } internal void Internal_OnCharInput(char c) @@ -223,7 +220,7 @@ namespace FlaxEngine internal void Internal_OnMouseDown(ref Vector2 mousePos, MouseButton button) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; bool handled = false; MouseDown?.Invoke(ref pos, button, ref handled); @@ -235,7 +232,7 @@ namespace FlaxEngine internal void Internal_OnMouseUp(ref Vector2 mousePos, MouseButton button) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; bool handled = false; MouseUp?.Invoke(ref pos, button, ref handled); @@ -247,7 +244,7 @@ namespace FlaxEngine internal void Internal_OnMouseDoubleClick(ref Vector2 mousePos, MouseButton button) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; bool handled = false; MouseDoubleClick?.Invoke(ref pos, button, ref handled); @@ -259,7 +256,7 @@ namespace FlaxEngine internal void Internal_OnMouseWheel(ref Vector2 mousePos, float delta) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; bool handled = false; MouseWheel?.Invoke(ref pos, delta, ref handled); @@ -271,7 +268,7 @@ namespace FlaxEngine internal void Internal_OnMouseMove(ref Vector2 mousePos) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; MouseMove?.Invoke(ref pos); GUI.OnMouseMove(pos); @@ -285,7 +282,7 @@ namespace FlaxEngine internal void Internal_OnTouchDown(ref Vector2 pointerPosition, int pointerId) { - Vector2 pos = pointerPosition / _dpiScale; + Vector2 pos = pointerPosition / DpiScale; bool handled = false; TouchDown?.Invoke(ref pos, pointerId, ref handled); @@ -297,7 +294,7 @@ namespace FlaxEngine internal void Internal_OnTouchMove(ref Vector2 pointerPosition, int pointerId) { - Vector2 pos = pointerPosition / _dpiScale; + Vector2 pos = pointerPosition / DpiScale; bool handled = false; TouchMove?.Invoke(ref pos, pointerId, ref handled); @@ -309,7 +306,7 @@ namespace FlaxEngine internal void Internal_OnTouchUp(ref Vector2 pointerPosition, int pointerId) { - Vector2 pos = pointerPosition / _dpiScale; + Vector2 pos = pointerPosition / DpiScale; bool handled = false; TouchUp?.Invoke(ref pos, pointerId, ref handled); @@ -335,7 +332,7 @@ namespace FlaxEngine { if (HitTest != null) { - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; result = HitTest(ref pos); handled = true; } @@ -356,7 +353,7 @@ namespace FlaxEngine dragData = new DragDataText(data[0]); else dragData = new DragDataFiles(data); - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; return GUI.OnDragEnter(ref pos, dragData); } @@ -367,7 +364,7 @@ namespace FlaxEngine dragData = new DragDataText(data[0]); else dragData = new DragDataFiles(data); - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; return GUI.OnDragMove(ref pos, dragData); } @@ -378,7 +375,7 @@ namespace FlaxEngine dragData = new DragDataText(data[0]); else dragData = new DragDataFiles(data); - Vector2 pos = mousePos / _dpiScale; + Vector2 pos = mousePos / DpiScale; return GUI.OnDragDrop(ref pos, dragData); } diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 0b1f70989..fae4add2d 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -58,7 +58,7 @@ int32 CalculateDpi(HMODULE shCoreDll) if (getDPIForMonitor) { - HMONITOR monitor = GetPrimaryMonitorHandle(); + HMONITOR monitor = GetPrimaryMonitorHandle(); // TODO: Use the game window monitor UINT x = 0, y = 0; HRESULT hr = getDPIForMonitor(monitor, 0, &x, &y); @@ -659,7 +659,7 @@ void WindowsPlatform::SetHighDpiAwarenessEnabled(bool enable) if (setProcessDpiAwareness) { - setProcessDpiAwareness(enable ? PROCESS_SYSTEM_DPI_AWARE : PROCESS_DPI_UNAWARE); + setProcessDpiAwareness(enable ? PROCESS_PER_MONITOR_DPI_AWARE : PROCESS_DPI_UNAWARE); } SystemDpi = CalculateDpi(shCoreDll); diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp index dc130949c..1b270d80b 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp @@ -16,6 +16,8 @@ // TODO: finish better borderless window on windows (fix mouse pos offset when maximized and fix white flicker on window show) #define WINDOWS_USE_NEW_BORDER_LESS 0 +#define DefaultDPI 96 + #if WINDOWS_USE_NEW_BORDER_LESS #pragma comment(lib, "Gdi32.lib") #endif @@ -95,6 +97,23 @@ WindowsWindow::WindowsWindow(const CreateWindowSettings& settings) nullptr, (HINSTANCE)Platform::Instance, nullptr); + + _dpi = DefaultDPI; + // TODO: Is this the correct way of doing this? + const HMODULE user32Dll = LoadLibraryW(L"user32.dll"); + if (user32Dll) + { + typedef UINT(STDAPICALLTYPE* GetDpiForWindowProc)(HWND hwnd); + const GetDpiForWindowProc getDpiForWindowProc = (GetDpiForWindowProc)GetProcAddress(user32Dll, "GetDpiForWindow"); + + if (getDpiForWindowProc) + { + _dpi = getDpiForWindowProc(_handle); + } + FreeLibrary(user32Dll); + } + + _dpiScale = (float)_dpi / (float)DefaultDPI; // Validate result if (!HasHWND()) @@ -966,6 +985,28 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) break; } + case WM_DPICHANGED: + { + // Maybe https://stackoverflow.com/a/45110656 + _dpi = HIWORD(wParam); + _dpiScale = (float)_dpi / (float)DefaultDPI; + + + RECT* windowRect = (RECT*)lParam; + SetWindowPos(_handle, + nullptr, + windowRect->left, + windowRect->top, + windowRect->right - windowRect->left, + windowRect->bottom - windowRect->top, + SWP_NOZORDER | SWP_NOACTIVATE); + + + // Todo: Recalculate fonts + + return 0; + } + case WM_ENTERSIZEMOVE: { _isResizing = true; diff --git a/Source/Engine/Render2D/FontManager.cpp b/Source/Engine/Render2D/FontManager.cpp index ec7a61257..8eda2d5ba 100644 --- a/Source/Engine/Render2D/FontManager.cpp +++ b/Source/Engine/Render2D/FontManager.cpp @@ -67,7 +67,7 @@ bool FontManagerService::Init() ASSERT(Library == nullptr); // Scale UI fonts to match the monitor DPI - FontManager::FontScale = (float)Platform::GetDpi() / (float)DefaultDPI; + FontManager::FontScale = (float)Platform::GetDpi() / (float)DefaultDPI; // TODO: Adjust this at runtime // Init Free Type FreeTypeMemory.user = nullptr; diff --git a/Source/Engine/UI/GUI/Control.cs b/Source/Engine/UI/GUI/Control.cs index 1c4eda965..6f4603e1a 100644 --- a/Source/Engine/UI/GUI/Control.cs +++ b/Source/Engine/UI/GUI/Control.cs @@ -310,7 +310,7 @@ namespace FlaxEngine.GUI /// /// Gets the GUI window root control which contains that control (or null if not linked to any). /// - public virtual WindowRootControl RootWindow => _parent?.RootWindow; + public virtual WindowRootControl RootWindow => _parent?.RootWindow; // TODO: Why doesn't this just go "_root?.RootWindow" or something? /// /// Gets screen position of the control (upper left corner). diff --git a/Source/Engine/UI/GUI/RenderOutputControl.cs b/Source/Engine/UI/GUI/RenderOutputControl.cs index 74210c9df..fb6897516 100644 --- a/Source/Engine/UI/GUI/RenderOutputControl.cs +++ b/Source/Engine/UI/GUI/RenderOutputControl.cs @@ -221,7 +221,7 @@ namespace FlaxEngine.GUI /// public void SyncBackbufferSize() { - float scale = ResolutionScale * Platform.DpiScale; + float scale = ResolutionScale * (Root?.RootWindow?.Window?.DpiScale ?? 1); // TODO: Figure this out int width = Mathf.CeilToInt(Width * scale); int height = Mathf.CeilToInt(Height * scale); if (_customResolution.HasValue) diff --git a/Source/Engine/UI/GUI/Tooltip.cs b/Source/Engine/UI/GUI/Tooltip.cs index 24c0651ed..fca4bd645 100644 --- a/Source/Engine/UI/GUI/Tooltip.cs +++ b/Source/Engine/UI/GUI/Tooltip.cs @@ -68,7 +68,7 @@ namespace FlaxEngine.GUI var parentWin = target.Root; if (parentWin == null) return; - float dpiScale = Platform.DpiScale; + float dpiScale = target.RootWindow.Window.DpiScale; Vector2 dpiSize = Size * dpiScale; Vector2 locationWS = target.PointToWindow(location); Vector2 locationSS = parentWin.PointToScreen(locationWS); @@ -185,7 +185,7 @@ namespace FlaxEngine.GUI { if (_window) { - _window.ClientSize = Size * Platform.DpiScale; + _window.ClientSize = Size * _window.DpiScale; } } diff --git a/Source/Engine/UI/GUI/WindowRootControl.cs b/Source/Engine/UI/GUI/WindowRootControl.cs index 02c996b68..1e9785195 100644 --- a/Source/Engine/UI/GUI/WindowRootControl.cs +++ b/Source/Engine/UI/GUI/WindowRootControl.cs @@ -151,7 +151,7 @@ namespace FlaxEngine.GUI } /// - public override Vector2 TrackingMouseOffset => _window.TrackingMouseOffset / _window._dpiScale; + public override Vector2 TrackingMouseOffset => _window.TrackingMouseOffset / _window.DpiScale; /// public override WindowRootControl RootWindow => this; @@ -159,8 +159,8 @@ namespace FlaxEngine.GUI /// public override Vector2 MousePosition { - get => _window.MousePosition / _window._dpiScale; - set => _window.MousePosition = value * _window._dpiScale; + get => _window.MousePosition / _window.DpiScale; + set => _window.MousePosition = value * _window.DpiScale; } /// @@ -234,13 +234,13 @@ namespace FlaxEngine.GUI /// public override Vector2 PointFromScreen(Vector2 location) { - return _window.ScreenToClient(location) / _window._dpiScale; + return _window.ScreenToClient(location) / _window.DpiScale; } /// public override Vector2 PointToScreen(Vector2 location) { - return _window.ClientToScreen(location * _window._dpiScale); + return _window.ClientToScreen(location * _window.DpiScale); } ///