diff --git a/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs b/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs index 1746fb1c4..bbf665405 100644 --- a/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs +++ b/Dalamud/Interface/Internal/ImGuiClipboardFunctionProvider.cs @@ -52,7 +52,6 @@ internal sealed unsafe class ImGuiClipboardFunctionProvider : IServiceType, IDis private ImGuiClipboardFunctionProvider(InterfaceManager.InterfaceManagerWithScene imws) { // Effectively waiting for ImGui to become available. - _ = imws; Debug.Assert(ImGuiHelpers.IsImGuiInitialized, "IMWS initialized but IsImGuiInitialized is false?"); var io = ImGui.GetIO(); diff --git a/Dalamud/Interface/ManagedFontAtlas/Internals/ImGuiDockNodeUpdateForceFont.cs b/Dalamud/Interface/ManagedFontAtlas/Internals/ImGuiDockNodeUpdateForceFont.cs new file mode 100644 index 000000000..a2a30429a --- /dev/null +++ b/Dalamud/Interface/ManagedFontAtlas/Internals/ImGuiDockNodeUpdateForceFont.cs @@ -0,0 +1,78 @@ +using System.Diagnostics; +using System.Linq; + +using Dalamud.Hooking; +using Dalamud.Interface.Internal; +using Dalamud.Interface.Utility; + +namespace Dalamud.Interface.ManagedFontAtlas.Internals; + +/// +/// Forces ImGui::RenderWindowDecorations to use the default font. +/// Fixes dock node draw using shared data across different draw lists. +/// TODO: figure out how to synchronize ImDrawList::_Data and ImDrawList::Push/PopTextureID across different instances. +/// It might be better to just special-case that particular function, +/// as no other code touches ImDrawList that is irrelevant to the global shared state, +/// with the exception of Dock... functions which are called from ImGui::NewFrame, +/// which are guaranteed to use the global default font. +/// +[ServiceManager.EarlyLoadedService] +internal class ImGuiRenderWindowDecorationsForceFont : IServiceType, IDisposable +{ + private const int CImGuiRenderWindowDecorationsOffset = 0x461B0; + private const int CImGuiWindowDockIsActiveOffset = 0x401; + + private readonly Hook hook; + + [ServiceManager.ServiceConstructor] + private ImGuiRenderWindowDecorationsForceFont(InterfaceManager.InterfaceManagerWithScene imws) + { + // Effectively waiting for ImGui to become available. + Debug.Assert(ImGuiHelpers.IsImGuiInitialized, "IMWS initialized but IsImGuiInitialized is false?"); + + var cimgui = Process.GetCurrentProcess().Modules.Cast() + .First(x => x.ModuleName == "cimgui.dll") + .BaseAddress; + this.hook = Hook.FromAddress( + cimgui + CImGuiRenderWindowDecorationsOffset, + this.ImGuiRenderWindowDecorationsDetour); + this.hook.Enable(); + } + + private delegate void ImGuiRenderWindowDecorationsDelegate( + nint window, + nint titleBarRectPtr, + byte titleBarIsHighlight, + byte handleBordersAndResizeGrips, + int resizeGripCount, + nint resizeGripColPtr, + float resizeGripDrawSize); + + /// + public void Dispose() => this.hook.Dispose(); + + private unsafe void ImGuiRenderWindowDecorationsDetour( + nint window, + nint titleBarRectPtr, + byte titleBarIsHighlight, + byte handleBordersAndResizeGrips, + int resizeGripCount, + nint resizeGripColPtr, + float resizeGripDrawSize) + { + using ( + ((byte*)window)![CImGuiWindowDockIsActiveOffset] != 0 + ? Service.Get().DefaultFontHandle?.Push() + : null) + { + this.hook.Original( + window, + titleBarRectPtr, + titleBarIsHighlight, + handleBordersAndResizeGrips, + resizeGripCount, + resizeGripColPtr, + resizeGripDrawSize); + } + } +}