From 5037ace00b01416ea7018bfad1e56972028d9980 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Wed, 8 Jan 2020 02:50:25 -0800 Subject: [PATCH] Fix mouse input on HiDPI monitors (#927) --- OpenToolkit.GraphicsLibraryFramework/GLFW.cs | 68 +++++++++++++++++++ .../GLFWCallbacks.cs | 11 ++- .../GLFWNative.cs | 8 ++- .../Graphics/Clyde/Clyde.Windowing.cs | 16 ++++- 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/OpenToolkit.GraphicsLibraryFramework/GLFW.cs b/OpenToolkit.GraphicsLibraryFramework/GLFW.cs index ad8c785e02..0380c8e054 100644 --- a/OpenToolkit.GraphicsLibraryFramework/GLFW.cs +++ b/OpenToolkit.GraphicsLibraryFramework/GLFW.cs @@ -1099,6 +1099,49 @@ namespace OpenToolkit.GraphicsLibraryFramework bottom = b; } + /// + /// + /// This function retrieves the content scale for the specified window. + /// + /// + /// The content scale is the ratio between the current DPI and the platform's default DPI. + /// This is especially important for text and any UI elements. + /// If the pixel dimensions of your UI scaled by this look appropriate on your machine then it should + /// appear at a reasonable size on other machines regardless of their DPI and scaling settings. + /// This relies on the system DPI and scaling settings being somewhat correct. + /// + /// + /// + /// On systems where each monitors can have its own content scale, + /// the window content scale will depend on which monitor the system considers the window to be on. + /// + /// + /// The window to query. + /// + /// Where to store the x-axis content scale, or out _. + /// + /// + /// Where to store the y-axis content scale, or out _. + /// + /// + /// + /// This function must only be called from the main thread. + /// + /// + /// Possible errors include and . + /// + /// + public static unsafe void GetWindowContentScale( + Window* window, + out float xScale, + out float yScale) + { + float x, y; + glfwGetWindowContentScale(window, &x, &y); + xScale = x; + yScale = y; + } + /// /// /// This function returns the opacity of the window, including any decorations. @@ -4422,6 +4465,31 @@ namespace OpenToolkit.GraphicsLibraryFramework return glfwSetWindowIconifyCallback(window, Marshal.GetFunctionPointerForDelegate(callback)); } + /// + /// + /// This function sets the window content scale callback of the specified window, + /// which is called when the content scale of the specified window changes. + /// + /// + /// The window whose content scale changed. + /// The new x-axis content scale of the window. + /// The new y-axis content scale of the window. + /// + /// + /// This function must only be called from the main thread. + /// + /// + /// Possible errors include . + /// + /// + /// + public static unsafe IntPtr SetWindowContentScaleCallback( + Window* window, + GLFWCallbacks.WindowContentScaleCallback callback) + { + return glfwSetWindowContentScaleCallback(window, Marshal.GetFunctionPointerForDelegate(callback)); + } + /// /// /// This function sets the monitor that the window uses for full screen mode or, diff --git a/OpenToolkit.GraphicsLibraryFramework/GLFWCallbacks.cs b/OpenToolkit.GraphicsLibraryFramework/GLFWCallbacks.cs index 27ceb4197d..ebf7b7c7db 100644 --- a/OpenToolkit.GraphicsLibraryFramework/GLFWCallbacks.cs +++ b/OpenToolkit.GraphicsLibraryFramework/GLFWCallbacks.cs @@ -1,4 +1,4 @@ -// +// // GLFWCallbacks.cs // // Copyright (C) 2019 OpenTK @@ -167,5 +167,14 @@ namespace OpenToolkit.GraphicsLibraryFramework /// /// The window that needs to be refreshed. public delegate void WindowRefreshCallback(Window* window); + + /// + /// This is the function pointer type for window content scale callbacks. + /// + /// The window whose content scale changed. + /// The new x-axis content scale of the window. + /// The new y-axis content scale of the window. + /// + public delegate void WindowContentScaleCallback(Window* window, float xscale, float yscale); } } diff --git a/OpenToolkit.GraphicsLibraryFramework/GLFWNative.cs b/OpenToolkit.GraphicsLibraryFramework/GLFWNative.cs index 9dcc1a1e77..914a4fefc0 100644 --- a/OpenToolkit.GraphicsLibraryFramework/GLFWNative.cs +++ b/OpenToolkit.GraphicsLibraryFramework/GLFWNative.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; namespace OpenToolkit.GraphicsLibraryFramework @@ -103,6 +103,9 @@ namespace OpenToolkit.GraphicsLibraryFramework [DllImport(LibraryName)] public static extern void glfwGetWindowFrameSize(Window* window, int* left, int* top, int* right, int* bottom); + [DllImport(LibraryName)] + public static extern void glfwGetWindowContentScale(Window* window, float* xscale, float* yscale); + [DllImport(LibraryName)] public static extern float glfwGetWindowOpacity(Window* window); @@ -340,6 +343,9 @@ namespace OpenToolkit.GraphicsLibraryFramework [DllImport(LibraryName)] public static extern IntPtr glfwSetWindowIconifyCallback(Window* window, IntPtr callback); + [DllImport(LibraryName)] + public static extern IntPtr glfwSetWindowContentScaleCallback(Window* window, IntPtr callback); + [DllImport(LibraryName)] public static extern void glfwSetWindowTitle(Window* window, byte* title); diff --git a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs index 592429a768..9671b116e8 100644 --- a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs +++ b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -36,6 +36,7 @@ namespace Robust.Client.Graphics.Clyde private GLFWCallbacks.ScrollCallback _scrollCallback; private GLFWCallbacks.WindowCloseCallback _windowCloseCallback; private GLFWCallbacks.WindowSizeCallback _windowSizeCallback; + private GLFWCallbacks.WindowContentScaleCallback _windowContentScaleCallback; private bool _glfwInitialized = false; @@ -43,6 +44,7 @@ namespace Robust.Client.Graphics.Clyde private Window* _glfwWindow; private Vector2i _screenSize; + private Vector2 _windowScale; private Thread _mainThread; private Vector2 _lastMousePos; @@ -118,6 +120,7 @@ namespace Robust.Client.Graphics.Clyde GLFW.SetWindowSizeCallback(_glfwWindow, _windowSizeCallback); GLFW.SetScrollCallback(_glfwWindow, _scrollCallback); GLFW.SetMouseButtonCallback(_glfwWindow, _mouseButtonCallback); + GLFW.SetWindowContentScaleCallback(_glfwWindow, _windowContentScaleCallback); GLFW.MakeContextCurrent(_glfwWindow); @@ -126,6 +129,9 @@ namespace Robust.Client.Graphics.Clyde GLFW.GetFramebufferSize(_glfwWindow, out var fbW, out var fbH); _screenSize = (fbW, fbH); + GLFW.GetWindowContentScale(_glfwWindow, out var scaleX, out var scaleY); + _windowScale = (scaleX, scaleY); + InitGLContext(); // Initializing OTK 3 seems to mess with the current context, so ensure it's still set. @@ -218,7 +224,7 @@ namespace Robust.Client.Graphics.Clyde private void OnGlfwCursorPos(Window* window, double x, double y) { - var newPos = new Vector2((float) x, (float) y); + var newPos = new Vector2((float) x, (float) y) * _windowScale; var delta = newPos - _lastMousePos; _lastMousePos = newPos; @@ -288,6 +294,11 @@ namespace Robust.Client.Graphics.Clyde OnWindowResized?.Invoke(new WindowResizedEventArgs(oldSize, _screenSize)); } + private void OnGlfwWindownContentScale(Window *window, float xScale, float yScale) + { + _windowScale = (xScale, yScale); + } + private void StoreCallbacks() { _errorCallback = OnGlfwError; @@ -298,6 +309,7 @@ namespace Robust.Client.Graphics.Clyde _scrollCallback = OnGlfwScroll; _windowCloseCallback = OnGlfwWindowClose; _windowSizeCallback = OnGlfwWindowSize; + _windowContentScaleCallback = OnGlfwWindownContentScale; } public override void SetWindowTitle(string title)