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);
|
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;
|
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)
|
private void Invoke(WndProcEventArgs args)
|
||||||
{
|
{
|
||||||
if (Service.Plugin is not { } plugin)
|
if (Service.Plugin is not { } plugin)
|
||||||
|
@ -78,6 +93,14 @@ public sealed unsafe class WndProcHook : IDisposable
|
||||||
return;
|
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)
|
if (WM.WM_MOUSEFIRST <= args.Message && args.Message <= WM.WM_MOUSELAST)
|
||||||
{
|
{
|
||||||
ParamToCoords(args.LParam, out int x, out int y);
|
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.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.System.Framework;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Common.Lua;
|
using FFXIVClientStructs.FFXIV.Common.Lua;
|
||||||
using FFXIVClientStructs.Interop;
|
using FFXIVClientStructs.Interop;
|
||||||
|
@ -11,6 +13,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
using static Dalamud.Interface.Utility.Raii.ImRaii;
|
||||||
using static TerraFX.Interop.Windows.Windows;
|
using static TerraFX.Interop.Windows.Windows;
|
||||||
|
|
||||||
namespace CustomResolution;
|
namespace CustomResolution;
|
||||||
|
@ -23,10 +26,9 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
|
|
||||||
private readonly List<Cmd> _cmds;
|
private readonly List<Cmd> _cmds;
|
||||||
private bool _unloading = false;
|
private bool _unloading = false;
|
||||||
private int _tickCount = 0;
|
private bool _wasEnabled = false;
|
||||||
private HWND _currentHwnd;
|
private HWND _currentHwnd;
|
||||||
private RECT _currentClientRect;
|
private RECT _currentClientRect;
|
||||||
private RECT _currentWindowRect;
|
|
||||||
private DXVKDWMHackMode _currentDXVKDWMHackMode = DXVKDWMHackMode.Off;
|
private DXVKDWMHackMode _currentDXVKDWMHackMode = DXVKDWMHackMode.Off;
|
||||||
|
|
||||||
public Plugin(IDalamudPluginInterface pluginInterface)
|
public Plugin(IDalamudPluginInterface pluginInterface)
|
||||||
|
@ -44,6 +46,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
|
|
||||||
Service.WndProcHook = new();
|
Service.WndProcHook = new();
|
||||||
Service.CursorPosHooks = new();
|
Service.CursorPosHooks = new();
|
||||||
|
Service.WindowRectHooks = new();
|
||||||
|
|
||||||
_cmds = typeof(Plugin).Assembly.GetTypes()
|
_cmds = typeof(Plugin).Assembly.GetTypes()
|
||||||
.Where(t => !t.IsAbstract && typeof(Cmd).IsAssignableFrom(t))
|
.Where(t => !t.IsAbstract && typeof(Cmd).IsAssignableFrom(t))
|
||||||
|
@ -77,8 +80,6 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
|
|
||||||
lock (_disposeLock)
|
lock (_disposeLock)
|
||||||
{
|
{
|
||||||
_tickCount = 0;
|
|
||||||
|
|
||||||
Service.Framework.Update -= OnFrameworkUpdate;
|
Service.Framework.Update -= OnFrameworkUpdate;
|
||||||
|
|
||||||
Service.Framework.RunOnFrameworkThread(Update);
|
Service.Framework.RunOnFrameworkThread(Update);
|
||||||
|
@ -89,6 +90,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
cmd.Dispose();
|
cmd.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Service.WindowRectHooks.Dispose();
|
||||||
Service.CursorPosHooks.Dispose();
|
Service.CursorPosHooks.Dispose();
|
||||||
Service.WndProcHook.Dispose();
|
Service.WndProcHook.Dispose();
|
||||||
|
|
||||||
|
@ -99,7 +101,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
|
|
||||||
public void ConvertCoordsWinToGame(ref int x, ref int y)
|
public void ConvertCoordsWinToGame(ref int x, ref int y)
|
||||||
{
|
{
|
||||||
if (CurrentWidth == CurrentWindowWidth && CurrentHeight == CurrentWindowHeight)
|
if (CurrentWidth == CurrentWindowWidth && CurrentHeight == CurrentWindowHeight)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -174,6 +176,15 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
var dev = Device.Instance();
|
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 rectWidth = _currentClientRect.right - _currentClientRect.left;
|
||||||
int rectHeight = _currentClientRect.bottom - _currentClientRect.top;
|
int rectHeight = _currentClientRect.bottom - _currentClientRect.top;
|
||||||
|
@ -185,11 +196,16 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
|
|
||||||
uint width, height;
|
uint width, height;
|
||||||
|
|
||||||
bool disabled = _unloading || !Service.Config.IsEnabled;
|
bool enabled = !_unloading && Service.Config.IsEnabled;
|
||||||
|
if (_wasEnabled != enabled)
|
||||||
if (Service.Config.IsScale || disabled)
|
|
||||||
{
|
{
|
||||||
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);
|
width = (uint) Math.Round(rectWidth * scale);
|
||||||
height = (uint) Math.Round(rectHeight * scale);
|
height = (uint) Math.Round(rectHeight * scale);
|
||||||
|
@ -200,27 +216,33 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
height = Service.Config.Height;
|
height = Service.Config.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (width < 256)
|
||||||
|
{
|
||||||
|
width = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height < 256)
|
||||||
|
{
|
||||||
|
height = 256;
|
||||||
|
}
|
||||||
|
|
||||||
if (width != dev->Width || height != dev->Height)
|
if (width != dev->Width || height != dev->Height)
|
||||||
{
|
{
|
||||||
Service.PluginLog.Info($"Changing resolution to {width} x {height}");
|
Service.PluginLog.Info($"Changing graphics resolution from {dev->Width} x {dev->Height} to {width} x {height}");
|
||||||
|
|
||||||
if (width < 256)
|
|
||||||
{
|
|
||||||
width = 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height < 256)
|
|
||||||
{
|
|
||||||
height = 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->NewWidth = width;
|
dev->NewWidth = width;
|
||||||
dev->NewHeight = height;
|
dev->NewHeight = height;
|
||||||
dev->RequestResolutionChange = 1;
|
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.
|
//Service.PluginLog.Debug($"NewWidth 0x{(long) (IntPtr) (&dev->NewWidth):X16}");
|
||||||
CurrentBorderlessFullscreen = (GetWindowLong(_currentHwnd, GWL.GWL_STYLE) & WS.WS_SYSMENU) == 0;
|
//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)
|
if (Service.Config.DXVKDWMHackMode != DXVKDWMHackMode.Off && !_unloading)
|
||||||
{
|
{
|
||||||
|
@ -338,25 +360,7 @@ public sealed unsafe class Plugin : IDalamudPlugin
|
||||||
Service.Config.Save();
|
Service.Config.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dev = Device.Instance();
|
Update();
|
||||||
|
|
||||||
_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 WndProcHook WndProcHook { get; internal set; } = null!;
|
||||||
public static CursorPosHooks CursorPosHooks { get; internal set; } = null!;
|
public static CursorPosHooks CursorPosHooks { get; internal set; } = null!;
|
||||||
|
public static WindowRectHooks WindowRectHooks { get; internal set; } = null!;
|
||||||
|
|
||||||
[PluginService]
|
[PluginService]
|
||||||
public static IDalamudPluginInterface PluginInterface { get; private set; } = null!;
|
public static IDalamudPluginInterface PluginInterface { get; private set; } = null!;
|
||||||
|
|
Loading…
Add table
Reference in a new issue