Merge remote-tracking branch 'origin/master' into api14-rollup
Some checks are pending
Build Dalamud / Build on Windows (push) Waiting to run
Build Dalamud / Check API Compatibility (push) Blocked by required conditions
Build Dalamud / Deploy dalamud-distrib staging (push) Blocked by required conditions

This commit is contained in:
github-actions[bot] 2025-12-11 23:58:03 +00:00
commit 6821eac353
8 changed files with 63 additions and 15 deletions

View file

@ -6,7 +6,7 @@
<PropertyGroup Label="Feature"> <PropertyGroup Label="Feature">
<Description>XIV Launcher addon framework</Description> <Description>XIV Launcher addon framework</Description>
<DalamudVersion>13.0.0.13</DalamudVersion> <DalamudVersion>13.0.0.16</DalamudVersion>
<AssemblyVersion>$(DalamudVersion)</AssemblyVersion> <AssemblyVersion>$(DalamudVersion)</AssemblyVersion>
<Version>$(DalamudVersion)</Version> <Version>$(DalamudVersion)</Version>
<FileVersion>$(DalamudVersion)</FileVersion> <FileVersion>$(DalamudVersion)</FileVersion>

View file

@ -84,8 +84,11 @@ internal sealed class DataManager : IInternalDisposableService, IDataManager
dalamud.StartInfo.TroubleshootingPackData); dalamud.StartInfo.TroubleshootingPackData);
// Don't fail for IndexIntegrityResult.Exception, since the check during launch has a very small timeout // Don't fail for IndexIntegrityResult.Exception, since the check during launch has a very small timeout
this.HasModifiedGameDataFiles = // this.HasModifiedGameDataFiles =
tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed; // tsInfo?.IndexIntegrity is LauncherTroubleshootingInfo.IndexIntegrityResult.Failed;
// TODO: Put above back when check in XL is fixed
this.HasModifiedGameDataFiles = false;
if (this.HasModifiedGameDataFiles) if (this.HasModifiedGameDataFiles)
Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData); Log.Verbose("Game data integrity check failed!\n{TsData}", dalamud.StartInfo.TroubleshootingPackData);

View file

@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Console;
using Dalamud.Memory; using Dalamud.Memory;
using Dalamud.Utility; using Dalamud.Utility;
@ -37,6 +38,8 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
private readonly WndProcDelegate wndProcDelegate; private readonly WndProcDelegate wndProcDelegate;
private readonly nint platformNamePtr; private readonly nint platformNamePtr;
private readonly IConsoleVariable<bool> cvLogMouseEvents;
private ViewportHandler viewportHandler; private ViewportHandler viewportHandler;
private int mouseButtonsDown; private int mouseButtonsDown;
@ -87,6 +90,11 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
this.cursors[(int)ImGuiMouseCursor.ResizeNwse] = LoadCursorW(default, IDC.IDC_SIZENWSE); this.cursors[(int)ImGuiMouseCursor.ResizeNwse] = LoadCursorW(default, IDC.IDC_SIZENWSE);
this.cursors[(int)ImGuiMouseCursor.Hand] = LoadCursorW(default, IDC.IDC_HAND); this.cursors[(int)ImGuiMouseCursor.Hand] = LoadCursorW(default, IDC.IDC_HAND);
this.cursors[(int)ImGuiMouseCursor.NotAllowed] = LoadCursorW(default, IDC.IDC_NO); this.cursors[(int)ImGuiMouseCursor.NotAllowed] = LoadCursorW(default, IDC.IDC_NO);
this.cvLogMouseEvents = Service<ConsoleManager>.Get().AddVariable(
"imgui.log_mouse_events",
"Log mouse events to console for debugging",
false);
} }
/// <summary> /// <summary>
@ -267,11 +275,23 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
case WM.WM_XBUTTONDOWN: case WM.WM_XBUTTONDOWN:
case WM.WM_XBUTTONDBLCLK: case WM.WM_XBUTTONDBLCLK:
{ {
if (this.cvLogMouseEvents.Value)
{
Log.Verbose(
"Handle MouseDown {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}",
GetButton(msg, wParam),
io.WantCaptureMouse,
this.mouseButtonsDown);
}
var button = GetButton(msg, wParam); var button = GetButton(msg, wParam);
if (io.WantCaptureMouse) if (io.WantCaptureMouse)
{ {
if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero) if (this.mouseButtonsDown == 0 && GetCapture() == nint.Zero)
{
SetCapture(hWndCurrent); SetCapture(hWndCurrent);
}
this.mouseButtonsDown |= 1 << button; this.mouseButtonsDown |= 1 << button;
io.AddMouseButtonEvent(button, true); io.AddMouseButtonEvent(button, true);
return default(LRESULT); return default(LRESULT);
@ -288,12 +308,28 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
case WM.WM_MBUTTONUP: case WM.WM_MBUTTONUP:
case WM.WM_XBUTTONUP: case WM.WM_XBUTTONUP:
{ {
if (this.cvLogMouseEvents.Value)
{
Log.Verbose(
"Handle MouseUp {Btn} WantCaptureMouse: {Want} mouseButtonsDown: {Down}",
GetButton(msg, wParam),
io.WantCaptureMouse,
this.mouseButtonsDown);
}
var button = GetButton(msg, wParam); var button = GetButton(msg, wParam);
if (io.WantCaptureMouse)
// Need to check if we captured the button event away from the game here, otherwise the game might get
// a down event but no up event, causing the cursor to get stuck.
// Can happen if WantCaptureMouse becomes true in between down and up
if (io.WantCaptureMouse && (this.mouseButtonsDown & (1 << button)) != 0)
{ {
this.mouseButtonsDown &= ~(1 << button); this.mouseButtonsDown &= ~(1 << button);
if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent) if (this.mouseButtonsDown == 0 && GetCapture() == hWndCurrent)
{
ReleaseCapture(); ReleaseCapture();
}
io.AddMouseButtonEvent(button, false); io.AddMouseButtonEvent(button, false);
return default(LRESULT); return default(LRESULT);
} }
@ -458,7 +494,12 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
// (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.) // (This is the position you can get with ::GetCursorPos() or WM_MOUSEMOVE + ::ClientToScreen(). In theory adding viewport->Pos to a client position would also be the same.)
var mousePos = mouseScreenPos; var mousePos = mouseScreenPos;
if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0) if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) == 0)
ClientToScreen(focusedWindow, &mousePos); {
// Use game window, otherwise, positions are calculated based on the focused window which might not be the game.
// Leads to offsets.
ClientToScreen(this.hWnd, &mousePos);
}
io.AddMousePosEvent(mousePos.x, mousePos.y); io.AddMousePosEvent(mousePos.x, mousePos.y);
} }

View file

@ -170,7 +170,7 @@ internal class SeStringRenderer : IServiceType
// This also does argument validation for drawParams. Do it here. // This also does argument validation for drawParams. Do it here.
// `using var` makes a struct read-only, but we do want to modify it. // `using var` makes a struct read-only, but we do want to modify it.
var stateStorage = new SeStringDrawState( using var stateStorage = new SeStringDrawState(
sss, sss,
drawParams, drawParams,
ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes), ThreadSafety.IsMainThread ? this.colorStackSetMainThread : new(this.colorStackSetMainThread.ColorTypes),

View file

@ -10,6 +10,7 @@ using Dalamud.Interface.Utility;
using Dalamud.Utility; using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using Lumina.Text.Payloads; using Lumina.Text.Payloads;
using Lumina.Text.ReadOnly; using Lumina.Text.ReadOnly;
@ -17,7 +18,7 @@ namespace Dalamud.Interface.ImGuiSeStringRenderer;
/// <summary>Calculated values from <see cref="SeStringDrawParams"/> using ImGui styles.</summary> /// <summary>Calculated values from <see cref="SeStringDrawParams"/> using ImGui styles.</summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe ref struct SeStringDrawState public unsafe ref struct SeStringDrawState : IDisposable
{ {
private static readonly int ChannelCount = Enum.GetValues<SeStringDrawChannel>().Length; private static readonly int ChannelCount = Enum.GetValues<SeStringDrawChannel>().Length;
@ -194,6 +195,9 @@ public unsafe ref struct SeStringDrawState
/// <summary>Gets the text fragments.</summary> /// <summary>Gets the text fragments.</summary>
internal List<TextFragment> Fragments { get; } internal List<TextFragment> Fragments { get; }
/// <inheritdoc/>
public void Dispose() => this.splitter.ClearFreeMemory();
/// <summary>Sets the current channel in the ImGui draw list splitter.</summary> /// <summary>Sets the current channel in the ImGui draw list splitter.</summary>
/// <param name="channelIndex">Channel to switch to.</param> /// <param name="channelIndex">Channel to switch to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -669,6 +669,8 @@ internal class DalamudInterface : IInternalDisposableService
{ {
using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f)); using var barColor = ImRaii.PushColor(ImGuiCol.WindowBg, new Vector4(0.060f, 0.060f, 0.060f, 0.773f));
barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero); barColor.Push(ImGuiCol.MenuBarBg, Vector4.Zero);
barColor.Push(ImGuiCol.Border, Vector4.Zero);
barColor.Push(ImGuiCol.BorderShadow, Vector4.Zero);
if (ImGui.BeginMainMenuBar()) if (ImGui.BeginMainMenuBar())
{ {
var pluginManager = Service<PluginManager>.Get(); var pluginManager = Service<PluginManager>.Get();

View file

@ -53,6 +53,7 @@ internal class PresetModel
/// <summary> /// <summary>
/// Gets a value indicating whether this preset is in the default state. /// Gets a value indicating whether this preset is in the default state.
/// </summary> /// </summary>
[JsonIgnore]
public bool IsDefault => public bool IsDefault =>
!this.IsPinned && !this.IsPinned &&
!this.IsClickThrough && !this.IsClickThrough &&

View file

@ -84,7 +84,7 @@ public abstract class Window
Click = _ => Click = _ =>
{ {
this.internalIsClickthrough = false; this.internalIsClickthrough = false;
this.presetDirty = false; this.presetDirty = true;
ImGui.OpenPopup(AdditionsPopupName); ImGui.OpenPopup(AdditionsPopupName);
}, },
Priority = int.MinValue, Priority = int.MinValue,
@ -672,16 +672,13 @@ public abstract class Window
Task.FromResult<IDalamudTextureWrap>(tex)); Task.FromResult<IDalamudTextureWrap>(tex));
} }
if (!this.hasError) if (isErrorStylePushed)
{ {
this.PostDraw(); Style.StyleModelV1.DalamudStandard.Pop();
} }
else else
{ {
if (isErrorStylePushed) this.PostDraw();
{
Style.StyleModelV1.DalamudStandard.Pop();
}
} }
this.PostHandlePreset(persistence); this.PostHandlePreset(persistence);
@ -864,7 +861,7 @@ public abstract class Window
foreach (var button in this.allButtons) foreach (var button in this.allButtons)
{ {
if (this.internalIsClickthrough && !button.AvailableClickthrough) if (this.internalIsClickthrough && !button.AvailableClickthrough)
return; continue;
Vector2 position = new(titleBarRect.Max.X - padR - buttonSize, titleBarRect.Min.Y + style.FramePadding.Y); Vector2 position = new(titleBarRect.Max.X - padR - buttonSize, titleBarRect.Min.Y + style.FramePadding.Y);
padR += buttonSize + style.ItemInnerSpacing.X; padR += buttonSize + style.ItemInnerSpacing.X;