From 5c7a5295d119c65510f9cc0b3fb4b8c4e418ea20 Mon Sep 17 00:00:00 2001
From: MidoriKami <9083275+MidoriKami@users.noreply.github.com>
Date: Tue, 27 Jan 2026 13:49:35 -0800
Subject: [PATCH] Misc Fixes (#2584)
* Disable default logging, remove log message
* Add IDtrBarEntry.MinimumWidth
* Fix Addon/Agent Lifecycle Register/Unregister
* Rename Agent.ReceiveEvent2
* Add to IReadOnlyDtrBarEntry
* Fix autoformat being terrible
* More style fixes
* Add focused changed lifecycle event
* Fix for obsolete renames
---
.../AddonArgTypes/AddonFocusChangedArgs.cs | 22 ++++
Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs | 5 +
Dalamud/Game/Addon/Lifecycle/AddonEvent.cs | 10 ++
.../Game/Addon/Lifecycle/AddonLifecycle.cs | 97 ++++++++++------
.../Game/Addon/Lifecycle/AddonVirtualTable.cs | 34 ++++++
Dalamud/Game/Agent/AgentEvent.cs | 4 +-
Dalamud/Game/Agent/AgentLifecycle.cs | 105 +++++++++++-------
Dalamud/Game/Agent/AgentVirtualTable.cs | 20 ++--
Dalamud/Game/Gui/Dtr/DtrBar.cs | 10 +-
Dalamud/Game/Gui/Dtr/DtrBarEntry.cs | 29 +++++
10 files changed, 245 insertions(+), 91 deletions(-)
create mode 100644 Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFocusChangedArgs.cs
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFocusChangedArgs.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFocusChangedArgs.cs
new file mode 100644
index 000000000..8936a233b
--- /dev/null
+++ b/Dalamud/Game/Addon/Lifecycle/AddonArgTypes/AddonFocusChangedArgs.cs
@@ -0,0 +1,22 @@
+namespace Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
+
+///
+/// Addon argument data for OnFocusChanged events.
+///
+public class AddonFocusChangedArgs : AddonArgs
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal AddonFocusChangedArgs()
+ {
+ }
+
+ ///
+ public override AddonArgsType Type => AddonArgsType.FocusChanged;
+
+ ///
+ /// Gets or sets a value indicating whether the window is being focused or unfocused.
+ ///
+ public bool ShouldFocus { get; set; }
+}
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs b/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs
index 46ee479ac..bc48eeed0 100644
--- a/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs
+++ b/Dalamud/Game/Addon/Lifecycle/AddonArgsType.cs
@@ -44,4 +44,9 @@ public enum AddonArgsType
/// Contains argument data for Close.
///
Close,
+
+ ///
+ /// Contains argument data for OnFocusChanged.
+ ///
+ FocusChanged,
}
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs b/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs
index 3b9c6e867..74c84d754 100644
--- a/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs
+++ b/Dalamud/Game/Addon/Lifecycle/AddonEvent.cs
@@ -203,4 +203,14 @@ public enum AddonEvent
/// Be aware this is only called for certain popup windows, it is not triggered when clicking on windows.
///
PostFocus,
+
+ ///
+ /// An event that is fired before an addon processes its FocusChanged method.
+ ///
+ PreFocusChanged,
+
+ ///
+ /// An event that is fired after a addon processes its FocusChanged method.
+ ///
+ PostFocusChanged,
}
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs
index c70c0c10f..6520ee4cf 100644
--- a/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs
+++ b/Dalamud/Game/Addon/Lifecycle/AddonLifecycle.cs
@@ -31,7 +31,7 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
private readonly Framework framework = Service.Get();
private Hook? onInitializeAddonHook;
- private bool isInvokingListeners = false;
+ private bool isInvokingListeners;
[ServiceManager.ServiceConstructor]
private AddonLifecycle()
@@ -56,29 +56,36 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
AllocatedTables.Clear();
}
+ ///
+ /// Resolves a virtual table address to the original virtual table address.
+ ///
+ /// The modified address to resolve.
+ /// The original address.
+ internal static AtkUnitBase.AtkUnitBaseVirtualTable* GetOriginalVirtualTable(AtkUnitBase.AtkUnitBaseVirtualTable* tableAddress)
+ {
+ var matchedTable = AllocatedTables.FirstOrDefault(table => table.ModifiedVirtualTable == tableAddress);
+ if (matchedTable == null)
+ {
+ return null;
+ }
+
+ return matchedTable.OriginalVirtualTable;
+ }
+
///
/// Register a listener for the target event and addon.
///
/// The listener to register.
internal void RegisterListener(AddonLifecycleEventListener listener)
{
- this.framework.RunOnTick(() =>
+ if (this.isInvokingListeners)
{
- if (!this.EventListeners.ContainsKey(listener.EventType))
- {
- if (!this.EventListeners.TryAdd(listener.EventType, []))
- return;
- }
-
- // Note: string.Empty is a valid addon name, as that will trigger on any addon for this event type
- if (!this.EventListeners[listener.EventType].ContainsKey(listener.AddonName))
- {
- if (!this.EventListeners[listener.EventType].TryAdd(listener.AddonName, []))
- return;
- }
-
- this.EventListeners[listener.EventType][listener.AddonName].Add(listener);
- }, delayTicks: this.isInvokingListeners ? 1 : 0);
+ this.framework.RunOnTick(() => this.RegisterListenerMethod(listener));
+ }
+ else
+ {
+ this.framework.RunOnFrameworkThread(() => this.RegisterListenerMethod(listener));
+ }
}
///
@@ -87,16 +94,14 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
/// The listener to unregister.
internal void UnregisterListener(AddonLifecycleEventListener listener)
{
- this.framework.RunOnTick(() =>
+ if (this.isInvokingListeners)
{
- if (this.EventListeners.TryGetValue(listener.EventType, out var addonListeners))
- {
- if (addonListeners.TryGetValue(listener.AddonName, out var addonListener))
- {
- addonListener.Remove(listener);
- }
- }
- }, delayTicks: this.isInvokingListeners ? 1 : 0);
+ this.framework.RunOnTick(() => this.UnregisterListenerMethod(listener));
+ }
+ else
+ {
+ this.framework.RunOnFrameworkThread(() => this.UnregisterListenerMethod(listener));
+ }
}
///
@@ -147,17 +152,37 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
this.isInvokingListeners = false;
}
- ///
- /// Resolves a virtual table address to the original virtual table address.
- ///
- /// The modified address to resolve.
- /// The original address.
- internal AtkUnitBase.AtkUnitBaseVirtualTable* GetOriginalVirtualTable(AtkUnitBase.AtkUnitBaseVirtualTable* tableAddress)
+ private void RegisterListenerMethod(AddonLifecycleEventListener listener)
{
- var matchedTable = AllocatedTables.FirstOrDefault(table => table.ModifiedVirtualTable == tableAddress);
- if (matchedTable == null) return null;
+ if (!this.EventListeners.ContainsKey(listener.EventType))
+ {
+ if (!this.EventListeners.TryAdd(listener.EventType, []))
+ {
+ return;
+ }
+ }
- return matchedTable.OriginalVirtualTable;
+ // Note: string.Empty is a valid addon name, as that will trigger on any addon for this event type
+ if (!this.EventListeners[listener.EventType].ContainsKey(listener.AddonName))
+ {
+ if (!this.EventListeners[listener.EventType].TryAdd(listener.AddonName, []))
+ {
+ return;
+ }
+ }
+
+ this.EventListeners[listener.EventType][listener.AddonName].Add(listener);
+ }
+
+ private void UnregisterListenerMethod(AddonLifecycleEventListener listener)
+ {
+ if (this.EventListeners.TryGetValue(listener.EventType, out var addonListeners))
+ {
+ if (addonListeners.TryGetValue(listener.AddonName, out var addonListener))
+ {
+ addonListener.Remove(listener);
+ }
+ }
}
private void OnAddonInitialize(AtkUnitBase* addon)
@@ -277,5 +302,5 @@ internal class AddonLifecyclePluginScoped : IInternalDisposableService, IAddonLi
///
public unsafe nint GetOriginalVirtualTable(nint virtualTableAddress)
- => (nint)this.addonLifecycleService.GetOriginalVirtualTable((AtkUnitBase.AtkUnitBaseVirtualTable*)virtualTableAddress);
+ => (nint)AddonLifecycle.GetOriginalVirtualTable((AtkUnitBase.AtkUnitBaseVirtualTable*)virtualTableAddress);
}
diff --git a/Dalamud/Game/Addon/Lifecycle/AddonVirtualTable.cs b/Dalamud/Game/Addon/Lifecycle/AddonVirtualTable.cs
index 736415738..1b2c828f8 100644
--- a/Dalamud/Game/Addon/Lifecycle/AddonVirtualTable.cs
+++ b/Dalamud/Game/Addon/Lifecycle/AddonVirtualTable.cs
@@ -42,6 +42,7 @@ internal unsafe class AddonVirtualTable : IDisposable
private readonly AddonArgs onMouseOverArgs = new();
private readonly AddonArgs onMouseOutArgs = new();
private readonly AddonArgs focusArgs = new();
+ private readonly AddonFocusChangedArgs focusChangedArgs = new();
private readonly AtkUnitBase* atkUnitBase;
@@ -63,6 +64,7 @@ internal unsafe class AddonVirtualTable : IDisposable
private readonly AtkUnitBase.Delegates.OnMouseOver onMouseOverFunction;
private readonly AtkUnitBase.Delegates.OnMouseOut onMouseOutFunction;
private readonly AtkUnitBase.Delegates.Focus focusFunction;
+ private readonly AtkUnitBase.Delegates.OnFocusChange onFocusChangeFunction;
///
/// Initializes a new instance of the class.
@@ -103,6 +105,7 @@ internal unsafe class AddonVirtualTable : IDisposable
this.onMouseOverFunction = this.OnAddonMouseOver;
this.onMouseOutFunction = this.OnAddonMouseOut;
this.focusFunction = this.OnAddonFocus;
+ this.onFocusChangeFunction = this.OnAddonFocusChange;
// Overwrite specific virtual table entries
this.ModifiedVirtualTable->Dtor = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.destructorFunction);
@@ -121,6 +124,7 @@ internal unsafe class AddonVirtualTable : IDisposable
this.ModifiedVirtualTable->OnMouseOver = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.onMouseOverFunction);
this.ModifiedVirtualTable->OnMouseOut = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.onMouseOutFunction);
this.ModifiedVirtualTable->Focus = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.focusFunction);
+ this.ModifiedVirtualTable->OnFocusChange = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.onFocusChangeFunction);
}
///
@@ -630,6 +634,36 @@ internal unsafe class AddonVirtualTable : IDisposable
}
}
+ private void OnAddonFocusChange(AtkUnitBase* thisPtr, bool isFocused)
+ {
+ try
+ {
+ this.LogEvent(EnableLogging);
+
+ this.focusChangedArgs.Addon = thisPtr;
+ this.focusChangedArgs.ShouldFocus = isFocused;
+
+ this.lifecycleService.InvokeListenersSafely(AddonEvent.PreFocusChanged, this.focusChangedArgs);
+
+ isFocused = this.focusChangedArgs.ShouldFocus;
+
+ try
+ {
+ this.OriginalVirtualTable->OnFocusChange(thisPtr, isFocused);
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Caught exception when calling original Addon OnFocusChanged. This may be a bug in the game or another plugin hooking this method.");
+ }
+
+ this.lifecycleService.InvokeListenersSafely(AddonEvent.PostFocusChanged, this.focusChangedArgs);
+ }
+ catch (Exception e)
+ {
+ Log.Error(e, "Caught exception from Dalamud when attempting to process OnAddonFocusChange.");
+ }
+ }
+
[Conditional("DEBUG")]
private void LogEvent(bool loggingEnabled, [CallerMemberName] string caller = "")
{
diff --git a/Dalamud/Game/Agent/AgentEvent.cs b/Dalamud/Game/Agent/AgentEvent.cs
index 2a3002daa..e9c9a1b85 100644
--- a/Dalamud/Game/Agent/AgentEvent.cs
+++ b/Dalamud/Game/Agent/AgentEvent.cs
@@ -18,12 +18,12 @@ public enum AgentEvent
///
/// An event that is fired before the agent processes its Filtered Receive Event Function.
///
- PreReceiveFilteredEvent,
+ PreReceiveEventWithResult,
///
/// An event that is fired after the agent has processed its Filtered Receive Event Function.
///
- PostReceiveFilteredEvent,
+ PostReceiveEventWithResult,
///
/// An event that is fired before the agent processes its Show Function.
diff --git a/Dalamud/Game/Agent/AgentLifecycle.cs b/Dalamud/Game/Agent/AgentLifecycle.cs
index 75ed47d86..45f0dec5c 100644
--- a/Dalamud/Game/Agent/AgentLifecycle.cs
+++ b/Dalamud/Game/Agent/AgentLifecycle.cs
@@ -69,30 +69,36 @@ internal unsafe class AgentLifecycle : IInternalDisposableService
AllocatedTables.Clear();
}
+ ///
+ /// Resolves a virtual table address to the original virtual table address.
+ ///
+ /// The modified address to resolve.
+ /// The original address.
+ internal static AgentInterface.AgentInterfaceVirtualTable* GetOriginalVirtualTable(AgentInterface.AgentInterfaceVirtualTable* tableAddress)
+ {
+ var matchedTable = AllocatedTables.FirstOrDefault(table => table.ModifiedVirtualTable == tableAddress);
+ if (matchedTable == null)
+ {
+ return null;
+ }
+
+ return matchedTable.OriginalVirtualTable;
+ }
+
///
/// Register a listener for the target event and agent.
///
/// The listener to register.
internal void RegisterListener(AgentLifecycleEventListener listener)
{
- this.framework.RunOnTick(() =>
+ if (this.isInvokingListeners)
{
- if (!this.EventListeners.ContainsKey(listener.EventType))
- {
- if (!this.EventListeners.TryAdd(listener.EventType, []))
- return;
- }
-
- // Note: uint.MaxValue is a valid agent id, as that will trigger on any agent for this event type
- if (!this.EventListeners[listener.EventType].ContainsKey(listener.AgentId))
- {
- if (!this.EventListeners[listener.EventType].TryAdd(listener.AgentId, []))
- return;
- }
-
- this.EventListeners[listener.EventType][listener.AgentId].Add(listener);
- },
- delayTicks: this.isInvokingListeners ? 1 : 0);
+ this.framework.RunOnTick(() => this.RegisterListenerMethod(listener));
+ }
+ else
+ {
+ this.framework.RunOnFrameworkThread(() => this.RegisterListenerMethod(listener));
+ }
}
///
@@ -101,17 +107,14 @@ internal unsafe class AgentLifecycle : IInternalDisposableService
/// The listener to unregister.
internal void UnregisterListener(AgentLifecycleEventListener listener)
{
- this.framework.RunOnTick(() =>
+ if (this.isInvokingListeners)
{
- if (this.EventListeners.TryGetValue(listener.EventType, out var agentListeners))
- {
- if (agentListeners.TryGetValue(listener.AgentId, out var agentListener))
- {
- agentListener.Remove(listener);
- }
- }
- },
- delayTicks: this.isInvokingListeners ? 1 : 0);
+ this.framework.RunOnTick(() => this.UnregisterListenerMethod(listener));
+ }
+ else
+ {
+ this.framework.RunOnFrameworkThread(() => this.UnregisterListenerMethod(listener));
+ }
}
///
@@ -162,19 +165,6 @@ internal unsafe class AgentLifecycle : IInternalDisposableService
this.isInvokingListeners = false;
}
- ///
- /// Resolves a virtual table address to the original virtual table address.
- ///
- /// The modified address to resolve.
- /// The original address.
- internal AgentInterface.AgentInterfaceVirtualTable* GetOriginalVirtualTable(AgentInterface.AgentInterfaceVirtualTable* tableAddress)
- {
- var matchedTable = AllocatedTables.FirstOrDefault(table => table.ModifiedVirtualTable == tableAddress);
- if (matchedTable == null) return null;
-
- return matchedTable.OriginalVirtualTable;
- }
-
private void OnAgentModuleInitialize(AgentModule* thisPtr, UIModule* uiModule)
{
this.onInitializeAgentsHook!.Original(thisPtr, uiModule);
@@ -193,6 +183,39 @@ internal unsafe class AgentLifecycle : IInternalDisposableService
}
}
+ private void RegisterListenerMethod(AgentLifecycleEventListener listener)
+ {
+ if (!this.EventListeners.ContainsKey(listener.EventType))
+ {
+ if (!this.EventListeners.TryAdd(listener.EventType, []))
+ {
+ return;
+ }
+ }
+
+ // Note: uint.MaxValue is a valid agent id, as that will trigger on any agent for this event type
+ if (!this.EventListeners[listener.EventType].ContainsKey(listener.AgentId))
+ {
+ if (!this.EventListeners[listener.EventType].TryAdd(listener.AgentId, []))
+ {
+ return;
+ }
+ }
+
+ this.EventListeners[listener.EventType][listener.AgentId].Add(listener);
+ }
+
+ private void UnregisterListenerMethod(AgentLifecycleEventListener listener)
+ {
+ if (this.EventListeners.TryGetValue(listener.EventType, out var agentListeners))
+ {
+ if (agentListeners.TryGetValue(listener.AgentId, out var agentListener))
+ {
+ agentListener.Remove(listener);
+ }
+ }
+ }
+
private void ReplaceVirtualTables(AgentModule* agentModule)
{
foreach (uint index in Enumerable.Range(0, agentModule->Agents.Length))
@@ -311,5 +334,5 @@ internal class AgentLifecyclePluginScoped : IInternalDisposableService, IAgentLi
///
public unsafe nint GetOriginalVirtualTable(nint virtualTableAddress)
- => (nint)this.agentLifecycleService.GetOriginalVirtualTable((AgentInterface.AgentInterfaceVirtualTable*)virtualTableAddress);
+ => (nint)AgentLifecycle.GetOriginalVirtualTable((AgentInterface.AgentInterfaceVirtualTable*)virtualTableAddress);
}
diff --git a/Dalamud/Game/Agent/AgentVirtualTable.cs b/Dalamud/Game/Agent/AgentVirtualTable.cs
index e7f9a2f6e..99f613137 100644
--- a/Dalamud/Game/Agent/AgentVirtualTable.cs
+++ b/Dalamud/Game/Agent/AgentVirtualTable.cs
@@ -21,7 +21,7 @@ internal unsafe class AgentVirtualTable : IDisposable
// Copying extra entries is not problematic, and is considered safe.
private const int VirtualTableEntryCount = 60;
- private const bool EnableLogging = true;
+ private const bool EnableLogging = false;
private static readonly ModuleLog Log = new("AgentVT");
@@ -44,7 +44,7 @@ internal unsafe class AgentVirtualTable : IDisposable
// Pinned Function Delegates, as these functions get assigned to an unmanaged virtual table,
// the CLR needs to know they are in use, or it will invalidate them causing random crashing.
private readonly AgentInterface.Delegates.ReceiveEvent receiveEventFunction;
- private readonly AgentInterface.Delegates.ReceiveEvent2 filteredReceiveEventFunction;
+ private readonly AgentInterface.Delegates.ReceiveEventWithResult receiveEventWithResultFunction;
private readonly AgentInterface.Delegates.Show showFunction;
private readonly AgentInterface.Delegates.Hide hideFunction;
private readonly AgentInterface.Delegates.Update updateFunction;
@@ -60,8 +60,6 @@ internal unsafe class AgentVirtualTable : IDisposable
/// Reference to AgentLifecycle service to callback and invoke listeners.
internal AgentVirtualTable(AgentInterface* agent, AgentId agentId, AgentLifecycle lifecycleService)
{
- Log.Debug($"Initializing AgentVirtualTable for {agentId}, Address: {(nint)agent:X}");
-
this.agentInterface = agent;
this.agentId = agentId;
this.lifecycleService = lifecycleService;
@@ -80,7 +78,7 @@ internal unsafe class AgentVirtualTable : IDisposable
// Pin each of our listener functions
this.receiveEventFunction = this.OnAgentReceiveEvent;
- this.filteredReceiveEventFunction = this.OnAgentFilteredReceiveEvent;
+ this.receiveEventWithResultFunction = this.OnAgentReceiveEventWithResult;
this.showFunction = this.OnAgentShow;
this.hideFunction = this.OnAgentHide;
this.updateFunction = this.OnAgentUpdate;
@@ -90,7 +88,7 @@ internal unsafe class AgentVirtualTable : IDisposable
// Overwrite specific virtual table entries
this.ModifiedVirtualTable->ReceiveEvent = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.receiveEventFunction);
- this.ModifiedVirtualTable->ReceiveEvent2 = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.filteredReceiveEventFunction);
+ this.ModifiedVirtualTable->ReceiveEventWithResult = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.receiveEventWithResultFunction);
this.ModifiedVirtualTable->Show = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.showFunction);
this.ModifiedVirtualTable->Hide = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.hideFunction);
this.ModifiedVirtualTable->Update = (delegate* unmanaged)Marshal.GetFunctionPointerForDelegate(this.updateFunction);
@@ -158,7 +156,7 @@ internal unsafe class AgentVirtualTable : IDisposable
return result;
}
- private AtkValue* OnAgentFilteredReceiveEvent(AgentInterface* thisPtr, AtkValue* returnValue, AtkValue* values, uint valueCount, ulong eventKind)
+ private AtkValue* OnAgentReceiveEventWithResult(AgentInterface* thisPtr, AtkValue* returnValue, AtkValue* values, uint valueCount, ulong eventKind)
{
AtkValue* result = null;
@@ -173,7 +171,7 @@ internal unsafe class AgentVirtualTable : IDisposable
this.filteredReceiveEventArgs.ValueCount = valueCount;
this.filteredReceiveEventArgs.EventKind = eventKind;
- this.lifecycleService.InvokeListenersSafely(AgentEvent.PreReceiveFilteredEvent, this.filteredReceiveEventArgs);
+ this.lifecycleService.InvokeListenersSafely(AgentEvent.PreReceiveEventWithResult, this.filteredReceiveEventArgs);
returnValue = (AtkValue*)this.filteredReceiveEventArgs.ReturnValue;
values = (AtkValue*)this.filteredReceiveEventArgs.AtkValues;
@@ -182,18 +180,18 @@ internal unsafe class AgentVirtualTable : IDisposable
try
{
- result = this.OriginalVirtualTable->ReceiveEvent2(thisPtr, returnValue, values, valueCount, eventKind);
+ result = this.OriginalVirtualTable->ReceiveEventWithResult(thisPtr, returnValue, values, valueCount, eventKind);
}
catch (Exception e)
{
Log.Error(e, "Caught exception when calling original Agent FilteredReceiveEvent. This may be a bug in the game or another plugin hooking this method.");
}
- this.lifecycleService.InvokeListenersSafely(AgentEvent.PostReceiveFilteredEvent, this.filteredReceiveEventArgs);
+ this.lifecycleService.InvokeListenersSafely(AgentEvent.PostReceiveEventWithResult, this.filteredReceiveEventArgs);
}
catch (Exception e)
{
- Log.Error(e, "Caught exception from Dalamud when attempting to process OnAgentFilteredReceiveEvent.");
+ Log.Error(e, "Caught exception from Dalamud when attempting to process OnAgentReceiveEventWithResult.");
}
return result;
diff --git a/Dalamud/Game/Gui/Dtr/DtrBar.cs b/Dalamud/Game/Gui/Dtr/DtrBar.cs
index 5663d0748..e5de6b2bd 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBar.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBar.cs
@@ -397,7 +397,15 @@ internal sealed unsafe class DtrBar : IInternalDisposableService, IDtrBar
ushort w = 0, h = 0;
node->GetTextDrawSize(&w, &h, node->NodeText.StringPtr);
- node->SetWidth(w);
+
+ if (data.MinimumWidth > 0)
+ {
+ node->SetWidth(Math.Max(data.MinimumWidth, w));
+ }
+ else
+ {
+ node->SetWidth(w);
+ }
}
var elementWidth = data.TextNode->Width + this.configuration.DtrSpacing;
diff --git a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
index e0bd8fd49..47e86fde1 100644
--- a/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
+++ b/Dalamud/Game/Gui/Dtr/DtrBarEntry.cs
@@ -40,6 +40,11 @@ public interface IReadOnlyDtrBarEntry
///
public bool Shown { get; }
+ ///
+ /// Gets a value indicating this entry's minimum width.
+ ///
+ public ushort MinimumWidth { get; }
+
///
/// Gets a value indicating whether the user has hidden this entry from view through the Dalamud settings.
///
@@ -76,6 +81,11 @@ public interface IDtrBarEntry : IReadOnlyDtrBarEntry
///
public new bool Shown { get; set; }
+ ///
+ /// Gets or sets a value specifying the requested minimum width to make this entry.
+ ///
+ public new ushort MinimumWidth { get; set; }
+
///
/// Gets or sets an action to be invoked when the user clicks on the dtr entry.
///
@@ -128,6 +138,25 @@ internal sealed unsafe class DtrBarEntry : IDisposable, IDtrBarEntry
///
public SeString? Tooltip { get; set; }
+ ///
+ public ushort MinimumWidth
+ {
+ get;
+ set
+ {
+ field = value;
+ if (this.TextNode is not null)
+ {
+ if (this.TextNode->GetWidth() < value)
+ {
+ this.TextNode->SetWidth(value);
+ }
+ }
+
+ this.Dirty = true;
+ }
+ }
+
///
public Action? OnClick { get; set; }