hack: workaround for ffxiv trying to take over hardware cursor

This commit is contained in:
goat 2020-01-21 01:30:17 +09:00
parent a8714df33b
commit 348783d394
2 changed files with 29 additions and 2 deletions

View file

@ -1,10 +1,12 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Game.Internal; using Dalamud.Game.Internal;
using Dalamud.Game.Internal.DXGI; using Dalamud.Game.Internal.DXGI;
using Dalamud.Hooking; using Dalamud.Hooking;
using EasyHook;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;
using Serilog; using Serilog;
@ -29,6 +31,11 @@ namespace Dalamud.Interface
private readonly Hook<PresentDelegate> presentHook; private readonly Hook<PresentDelegate> presentHook;
private readonly Hook<SetCursorDelegate> setCursorHook;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr SetCursorDelegate(IntPtr hCursor);
private ISwapChainAddressResolver Address { get; } private ISwapChainAddressResolver Address { get; }
private RawDX11Scene scene; private RawDX11Scene scene;
@ -59,9 +66,14 @@ namespace Dalamud.Interface
Address = vtableResolver; Address = vtableResolver;
} }
var setCursorAddr = LocalHook.GetProcAddress("user32.dll", "SetCursor");
Log.Verbose("===== S W A P C H A I N ====="); Log.Verbose("===== S W A P C H A I N =====");
Log.Verbose("SetCursor address {SetCursor}", setCursorAddr);
Log.Verbose("Present address {Present}", Address.Present); Log.Verbose("Present address {Present}", Address.Present);
this.setCursorHook = new Hook<SetCursorDelegate>(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this);
this.presentHook = this.presentHook =
new Hook<PresentDelegate>(Address.Present, new Hook<PresentDelegate>(Address.Present,
new PresentDelegate(PresentDetour), new PresentDelegate(PresentDetour),
@ -70,6 +82,7 @@ namespace Dalamud.Interface
public void Enable() public void Enable()
{ {
this.setCursorHook.Enable();
this.presentHook.Enable(); this.presentHook.Enable();
this.scene?.Enable(); this.scene?.Enable();
@ -77,6 +90,7 @@ namespace Dalamud.Interface
private void Disable() private void Disable()
{ {
this.setCursorHook.Disable();
this.presentHook.Disable(); this.presentHook.Disable();
this.scene?.Disable(); this.scene?.Disable();
@ -110,6 +124,18 @@ namespace Dalamud.Interface
return this.presentHook.Original(swapChain, syncInterval, presentFlags); 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() private void Display()
{ {
// this is more or less part of what reshade/etc do to avoid having to manually // 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 // If the player has the game software cursor enabled, we can't really do anything about that and
// they will see both cursors. // they will see both cursors.
// Doing this here because it's somewhat application-specific behavior // 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(); OnDraw?.Invoke();
} }

@ -1 +1 @@
Subproject commit 04bd99314d74d62b3c6f979aa3ffcc6db33858fd Subproject commit f1a6ea14c354ecc65d36ab212de3d3ce91b60556