From 348783d394f86bddb30ec5321a9935eba5ea7433 Mon Sep 17 00:00:00 2001 From: goat Date: Tue, 21 Jan 2020 01:30:17 +0900 Subject: [PATCH] hack: workaround for ffxiv trying to take over hardware cursor --- Dalamud/Interface/InterfaceManager.cs | 29 ++++++++++++++++++++++++++- lib/ImGuiScene | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Dalamud/Interface/InterfaceManager.cs b/Dalamud/Interface/InterfaceManager.cs index 7bf76fc68..1787717d9 100644 --- a/Dalamud/Interface/InterfaceManager.cs +++ b/Dalamud/Interface/InterfaceManager.cs @@ -1,10 +1,12 @@ using System; using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; using Dalamud.Game; using Dalamud.Game.Internal; using Dalamud.Game.Internal.DXGI; using Dalamud.Hooking; +using EasyHook; using ImGuiNET; using ImGuiScene; using Serilog; @@ -29,6 +31,11 @@ namespace Dalamud.Interface private readonly Hook presentHook; + private readonly Hook setCursorHook; + + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate IntPtr SetCursorDelegate(IntPtr hCursor); + private ISwapChainAddressResolver Address { get; } private RawDX11Scene scene; @@ -59,9 +66,14 @@ namespace Dalamud.Interface Address = vtableResolver; } + var setCursorAddr = LocalHook.GetProcAddress("user32.dll", "SetCursor"); + Log.Verbose("===== S W A P C H A I N ====="); + Log.Verbose("SetCursor address {SetCursor}", setCursorAddr); Log.Verbose("Present address {Present}", Address.Present); + this.setCursorHook = new Hook(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this); + this.presentHook = new Hook(Address.Present, new PresentDelegate(PresentDetour), @@ -70,6 +82,7 @@ namespace Dalamud.Interface public void Enable() { + this.setCursorHook.Enable(); this.presentHook.Enable(); this.scene?.Enable(); @@ -77,6 +90,7 @@ namespace Dalamud.Interface private void Disable() { + this.setCursorHook.Disable(); this.presentHook.Disable(); this.scene?.Disable(); @@ -110,6 +124,18 @@ namespace Dalamud.Interface return this.presentHook.Original(swapChain, syncInterval, presentFlags); } + // can't access imgui IO before first present call + private bool lastWantCapture = false; + + private IntPtr SetCursorDetour(IntPtr hCursor) { + Log.Debug($"hCursor: {hCursor.ToInt64():X} WantCapture: {this.lastWantCapture}"); + + if (this.lastWantCapture == true && ImGui_Input_Impl_Direct.Cursors != null && !ImGui_Input_Impl_Direct.Cursors.Contains(hCursor)) + return IntPtr.Zero; + + return this.setCursorHook.Original(hCursor); + } + private void Display() { // this is more or less part of what reshade/etc do to avoid having to manually @@ -119,7 +145,8 @@ namespace Dalamud.Interface // If the player has the game software cursor enabled, we can't really do anything about that and // they will see both cursors. // Doing this here because it's somewhat application-specific behavior - ImGui.GetIO().MouseDrawCursor = ImGui.GetIO().WantCaptureMouse; + //ImGui.GetIO().MouseDrawCursor = ImGui.GetIO().WantCaptureMouse; + this.lastWantCapture = ImGui.GetIO().WantCaptureMouse; OnDraw?.Invoke(); } diff --git a/lib/ImGuiScene b/lib/ImGuiScene index 04bd99314..f1a6ea14c 160000 --- a/lib/ImGuiScene +++ b/lib/ImGuiScene @@ -1 +1 @@ -Subproject commit 04bd99314d74d62b3c6f979aa3ffcc6db33858fd +Subproject commit f1a6ea14c354ecc65d36ab212de3d3ce91b60556