Move mostly away from D3D resize to fake window size (fix ReShade)
This commit is contained in:
parent
3a54a2781f
commit
80ca36b0a8
5 changed files with 153 additions and 43 deletions
|
@ -73,4 +73,5 @@ public sealed unsafe class CursorPosHooks : IDisposable
|
|||
|
||||
return _setCursorPosHook.Original(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
81
CustomResolution/Hooks/WindowRectHooks.cs
Normal file
81
CustomResolution/Hooks/WindowRectHooks.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
using CustomResolution.WndProcHookManagerProxyApi;
|
||||
using Dalamud.Hooking;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.InteropServices;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
|
||||
namespace CustomResolution.Hooks;
|
||||
|
||||
// THIS. IS. UGLY.
|
||||
public sealed unsafe class WindowRectHooks : IDisposable
|
||||
{
|
||||
private readonly Hook<GetClientRectDelegate> _getClientRectHook;
|
||||
private readonly Hook<SetWindowPosDelegate> _setWindowPosHook;
|
||||
|
||||
public WindowRectHooks()
|
||||
{
|
||||
_getClientRectHook = Service.GameInteropProvider.HookFromSymbol<GetClientRectDelegate>("user32.dll", "GetClientRect", GetClientRectDetour);
|
||||
_getClientRectHook.Enable();
|
||||
|
||||
_setWindowPosHook = Service.GameInteropProvider.HookFromSymbol<SetWindowPosDelegate>("user32.dll", "SetWindowPos", SetWindowPosDetour);
|
||||
_setWindowPosHook.Enable();
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
private unsafe delegate bool GetClientRectDelegate(HWND hWnd, RECT* lpRect);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
private unsafe delegate bool SetWindowPosDelegate(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_getClientRectHook.Dispose();
|
||||
}
|
||||
|
||||
public bool GetClientRectOrig(HWND hWnd, RECT* lpRect)
|
||||
{
|
||||
return _getClientRectHook.Original(hWnd, lpRect);
|
||||
}
|
||||
|
||||
private bool GetClientRectDetour(HWND hWnd, RECT* lpRect)
|
||||
{
|
||||
var rv = _getClientRectHook.Original(hWnd, lpRect);
|
||||
|
||||
if (!rv)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if false
|
||||
Service.PluginLog.Debug($"GetClientRectDetour A @ {lpRect->left} {lpRect->top} {lpRect->right} {lpRect->bottom}");
|
||||
#endif
|
||||
|
||||
Service.Plugin.ConvertCoordsWinToGame(ref lpRect->right, ref lpRect->bottom);
|
||||
|
||||
#if false
|
||||
Service.PluginLog.Debug($"GetClientRectDetour B @ {lpRect->left} {lpRect->top} {lpRect->right} {lpRect->bottom}");
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
private bool SetWindowPosDetour(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags)
|
||||
{
|
||||
#if false
|
||||
Service.PluginLog.Debug($"SetWindowPosDetour A @ {X} {Y} {cx} {cy}");
|
||||
#endif
|
||||
|
||||
Service.Plugin.ConvertCoordsGameToWin(ref cx, ref cy);
|
||||
|
||||
#if false
|
||||
Service.PluginLog.Debug($"SetWindowPosDetour B @ {X} {Y} {cx} {cy}");
|
||||
#endif
|
||||
|
||||
return _setWindowPosHook.Original(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
|
||||
}
|
||||
|
||||
}
|
|
@ -71,6 +71,21 @@ public sealed unsafe class WndProcHook : IDisposable
|
|||
return value;
|
||||
}
|
||||
|
||||
private static void ParamToSize(LPARAM param, out uint x, out uint y)
|
||||
{
|
||||
x = (ushort) (param.Value & 0xFFFF);
|
||||
y = (ushort) (param.Value >> 16 & 0xFFFF);
|
||||
}
|
||||
|
||||
private static LPARAM SizeToParam(uint x, uint y)
|
||||
{
|
||||
nint value = 0;
|
||||
value |= ((ushort) x) & 0xFFFF;
|
||||
value |= ((ushort) y) >> 16 & 0xFFFF;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private void Invoke(WndProcEventArgs args)
|
||||
{
|
||||
if (Service.Plugin is not { } plugin)
|
||||
|
@ -78,6 +93,14 @@ public sealed unsafe class WndProcHook : IDisposable
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.Message == WM.WM_SIZE)
|
||||
{
|
||||
ParamToCoords(args.LParam, out int x, out int y);
|
||||
Service.PluginLog.Debug($"WM_SIZE {x} x {y}");
|
||||
Service.Plugin.Update();
|
||||
args.LParam = SizeToParam(Service.Plugin.CurrentWidth, Service.Plugin.CurrentHeight);
|
||||
}
|
||||
|
||||
if (WM.WM_MOUSEFIRST <= args.Message && args.Message <= WM.WM_MOUSELAST)
|
||||
{
|
||||
ParamToCoords(args.LParam, out int x, out int y);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using Dalamud.Game.ClientState.Keys;
|
||||
using CustomResolution.Hooks;
|
||||
using Dalamud.Game.ClientState.Keys;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using FFXIVClientStructs.FFXIV.Common.Lua;
|
||||
using FFXIVClientStructs.Interop;
|
||||
|
@ -11,6 +13,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static Dalamud.Interface.Utility.Raii.ImRaii;
|
||||
using static TerraFX.Interop.Windows.Windows;
|
||||
|
||||
namespace CustomResolution;
|
||||
|
@ -23,10 +26,9 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
|
||||
private readonly List<Cmd> _cmds;
|
||||
private bool _unloading = false;
|
||||
private int _tickCount = 0;
|
||||
private bool _wasEnabled = false;
|
||||
private HWND _currentHwnd;
|
||||
private RECT _currentClientRect;
|
||||
private RECT _currentWindowRect;
|
||||
private DXVKDWMHackMode _currentDXVKDWMHackMode = DXVKDWMHackMode.Off;
|
||||
|
||||
public Plugin(IDalamudPluginInterface pluginInterface)
|
||||
|
@ -44,6 +46,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
|
||||
Service.WndProcHook = new();
|
||||
Service.CursorPosHooks = new();
|
||||
Service.WindowRectHooks = new();
|
||||
|
||||
_cmds = typeof(Plugin).Assembly.GetTypes()
|
||||
.Where(t => !t.IsAbstract && typeof(Cmd).IsAssignableFrom(t))
|
||||
|
@ -77,8 +80,6 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
|
||||
lock (_disposeLock)
|
||||
{
|
||||
_tickCount = 0;
|
||||
|
||||
Service.Framework.Update -= OnFrameworkUpdate;
|
||||
|
||||
Service.Framework.RunOnFrameworkThread(Update);
|
||||
|
@ -89,6 +90,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
cmd.Dispose();
|
||||
}
|
||||
|
||||
Service.WindowRectHooks.Dispose();
|
||||
Service.CursorPosHooks.Dispose();
|
||||
Service.WndProcHook.Dispose();
|
||||
|
||||
|
@ -174,6 +176,15 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
public void Update()
|
||||
{
|
||||
var dev = Device.Instance();
|
||||
var framework = Framework.Instance();
|
||||
var win = framework->GameWindow;
|
||||
|
||||
_currentHwnd = (HWND) (IntPtr) dev->hWnd;
|
||||
|
||||
fixed (RECT* currentClientRectPtr = &_currentClientRect)
|
||||
{
|
||||
Service.WindowRectHooks.GetClientRectOrig(_currentHwnd, currentClientRectPtr);
|
||||
}
|
||||
|
||||
int rectWidth = _currentClientRect.right - _currentClientRect.left;
|
||||
int rectHeight = _currentClientRect.bottom - _currentClientRect.top;
|
||||
|
@ -185,11 +196,16 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
|
||||
uint width, height;
|
||||
|
||||
bool disabled = _unloading || !Service.Config.IsEnabled;
|
||||
|
||||
if (Service.Config.IsScale || disabled)
|
||||
bool enabled = !_unloading && Service.Config.IsEnabled;
|
||||
if (_wasEnabled != enabled)
|
||||
{
|
||||
var scale = disabled ? 1f : Service.Config.Scale;
|
||||
Service.PluginLog.Info($"Changing state to: {enabled}");
|
||||
_wasEnabled = enabled;
|
||||
}
|
||||
|
||||
if (Service.Config.IsScale || !enabled)
|
||||
{
|
||||
var scale = enabled ? Service.Config.Scale : 1f;
|
||||
|
||||
width = (uint) Math.Round(rectWidth * scale);
|
||||
height = (uint) Math.Round(rectHeight * scale);
|
||||
|
@ -200,10 +216,6 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
height = Service.Config.Height;
|
||||
}
|
||||
|
||||
if (width != dev->Width || height != dev->Height)
|
||||
{
|
||||
Service.PluginLog.Info($"Changing resolution to {width} x {height}");
|
||||
|
||||
if (width < 256)
|
||||
{
|
||||
width = 256;
|
||||
|
@ -214,13 +226,23 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
height = 256;
|
||||
}
|
||||
|
||||
if (width != dev->Width || height != dev->Height)
|
||||
{
|
||||
Service.PluginLog.Info($"Changing graphics resolution from {dev->Width} x {dev->Height} to {width} x {height}");
|
||||
dev->NewWidth = width;
|
||||
dev->NewHeight = height;
|
||||
dev->RequestResolutionChange = 1;
|
||||
Service.PluginLog.Info($"Changing game window from {win->WindowWidth} x {win->WindowHeight} to {width} x {height}");
|
||||
win->WindowWidth = (int) width;
|
||||
win->WindowHeight = (int) height;
|
||||
}
|
||||
|
||||
// TODO: This isn't accurate! Figure out how to read the game's settings instead.
|
||||
CurrentBorderlessFullscreen = (GetWindowLong(_currentHwnd, GWL.GWL_STYLE) & WS.WS_SYSMENU) == 0;
|
||||
//Service.PluginLog.Debug($"NewWidth 0x{(long) (IntPtr) (&dev->NewWidth):X16}");
|
||||
//Service.PluginLog.Debug($"GameWindow->Width 0x{(long) (IntPtr) (&win->WindowWidth):X16}");
|
||||
|
||||
//Service.PluginLog.Info($"Game window at {win->WindowWidth} x {win->WindowHeight}");
|
||||
|
||||
CurrentBorderlessFullscreen = win->Borderless;
|
||||
|
||||
if (Service.Config.DXVKDWMHackMode != DXVKDWMHackMode.Off && !_unloading)
|
||||
{
|
||||
|
@ -338,25 +360,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
|||
Service.Config.Save();
|
||||
}
|
||||
|
||||
var dev = Device.Instance();
|
||||
|
||||
_currentHwnd = (HWND) (IntPtr) dev->hWnd;
|
||||
|
||||
fixed (RECT* currentClientRectPtr = &_currentClientRect)
|
||||
fixed (RECT* currentWindowRectPtr = &_currentWindowRect)
|
||||
{
|
||||
GetClientRect(_currentHwnd, currentClientRectPtr);
|
||||
GetWindowRect(_currentHwnd, currentWindowRectPtr);
|
||||
}
|
||||
|
||||
if (_tickCount++ >= 2)
|
||||
{
|
||||
_tickCount = 0;
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
_tickCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ public sealed class Service
|
|||
|
||||
public static WndProcHook WndProcHook { get; internal set; } = null!;
|
||||
public static CursorPosHooks CursorPosHooks { get; internal set; } = null!;
|
||||
public static WindowRectHooks WindowRectHooks { get; internal set; } = null!;
|
||||
|
||||
[PluginService]
|
||||
public static IDalamudPluginInterface PluginInterface { get; private set; } = null!;
|
||||
|
|
Loading…
Add table
Reference in a new issue