diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index c966fc27a..abe671d67 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -216,7 +216,7 @@ namespace Dalamud clientState.Enable(); Log.Information("[T2] CS ENABLE!"); - Service.Set().Enable(); + Service.Set().Enable(); this.IsReady = true; } @@ -339,7 +339,7 @@ namespace Dalamud Service.GetNullable()?.Dispose(); Service.GetNullable()?.Dispose(); Service.GetNullable()?.Dispose(); - Service.GetNullable()?.Dispose(); + Service.GetNullable()?.Dispose(); Service.GetNullable()?.Dispose(); Service.GetNullable()?.Dispose(); diff --git a/Dalamud/Game/Internal/DalamudSystemMenu.cs b/Dalamud/Game/Internal/DalamudAtkTweaks.cs similarity index 83% rename from Dalamud/Game/Internal/DalamudSystemMenu.cs rename to Dalamud/Game/Internal/DalamudAtkTweaks.cs index 8e7bc475c..7379cfc13 100644 --- a/Dalamud/Game/Internal/DalamudSystemMenu.cs +++ b/Dalamud/Game/Internal/DalamudAtkTweaks.cs @@ -7,6 +7,7 @@ using Dalamud.Configuration.Internal; using Dalamud.Hooking; using Dalamud.Interface.Internal; using FFXIVClientStructs.FFXIV.Component.GUI; +using Serilog; using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; @@ -15,7 +16,7 @@ namespace Dalamud.Game.Internal /// /// This class implements in-game Dalamud options in the in-game System menu. /// - internal sealed unsafe partial class DalamudSystemMenu + internal sealed unsafe partial class DalamudAtkTweaks { private readonly AtkValueChangeType atkValueChangeType; private readonly AtkValueSetString atkValueSetString; @@ -24,10 +25,12 @@ namespace Dalamud.Game.Internal // TODO: Make this into events in Framework.Gui private readonly Hook hookUiModuleRequestMainCommand; + private readonly Hook hookAtkUnitBaseReceiveGlobalEvent; + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public DalamudSystemMenu() + public DalamudAtkTweaks() { var sigScanner = Service.Get(); @@ -43,6 +46,11 @@ namespace Dalamud.Game.Internal var uiModuleRequestMainCommandAddress = sigScanner.ScanText("40 53 56 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B 01 8B DA 48 8B F1 FF 90 ?? ?? ?? ??"); this.hookUiModuleRequestMainCommand = new Hook(uiModuleRequestMainCommandAddress, this.UiModuleRequestMainCommandDetour); + + var atkUnitBaseReceiveGlobalEventAddress = + sigScanner.ScanText("48 89 5C 24 ?? 48 89 7C 24 ?? 55 41 56 41 57 48 8B EC 48 83 EC 50 44 0F B7 F2 "); + this.hookAtkUnitBaseReceiveGlobalEvent = + new Hook(atkUnitBaseReceiveGlobalEventAddress, this.AtkUnitBaseReceiveGlobalEventDetour); } private delegate void AgentHudOpenSystemMenuPrototype(void* thisPtr, AtkValue* atkValueArgs, uint menuSize); @@ -53,13 +61,28 @@ namespace Dalamud.Game.Internal private delegate void UiModuleRequestMainCommand(void* thisPtr, int commandId); + private delegate IntPtr AtkUnitBaseReceiveGlobalEvent(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5); + /// - /// Enables the . + /// Enables the . /// public void Enable() { this.hookAgentHudOpenSystemMenu.Enable(); this.hookUiModuleRequestMainCommand.Enable(); + this.hookAtkUnitBaseReceiveGlobalEvent.Enable(); + } + + private IntPtr AtkUnitBaseReceiveGlobalEventDetour(AtkUnitBase* thisPtr, ushort cmd, uint a3, IntPtr a4, uint* a5) + { + Log.Information($"cmd:{cmd} a3:{a3} a4:{a4:x} a5:{*a5}"); + + var di = Service.Get(); + // "Close Addon" + if (cmd == 12 && di.WindowSystem.HasAnyFocus) + return IntPtr.Zero; + + return this.hookAtkUnitBaseReceiveGlobalEvent.Original(thisPtr, cmd, a3, a4, a5); } private void AgentHudOpenSystemMenuDetour(void* thisPtr, AtkValue* atkValueArgs, uint menuSize) @@ -157,14 +180,14 @@ namespace Dalamud.Game.Internal /// /// Implements IDisposable. /// - internal sealed partial class DalamudSystemMenu : IDisposable + internal sealed partial class DalamudAtkTweaks : IDisposable { private bool disposed = false; /// - /// Finalizes an instance of the class. + /// Finalizes an instance of the class. /// - ~DalamudSystemMenu() => this.Dispose(false); + ~DalamudAtkTweaks() => this.Dispose(false); /// /// Dispose of managed and unmanaged resources. @@ -187,6 +210,7 @@ namespace Dalamud.Game.Internal { this.hookAgentHudOpenSystemMenu.Dispose(); this.hookUiModuleRequestMainCommand.Dispose(); + this.hookAtkUnitBaseReceiveGlobalEvent.Dispose(); } this.disposed = true; diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs index fd899f99a..b6a971a99 100644 --- a/Dalamud/Interface/Internal/DalamudInterface.cs +++ b/Dalamud/Interface/Internal/DalamudInterface.cs @@ -28,8 +28,6 @@ namespace Dalamud.Interface.Internal { private static readonly ModuleLog Log = new("DUI"); - private readonly WindowSystem windowSystem; - private readonly ChangelogWindow changelogWindow; private readonly ColorDemoWindow colorDemoWindow; private readonly ComponentDemoWindow componentDemoWindow; @@ -61,7 +59,7 @@ namespace Dalamud.Interface.Internal { var configuration = Service.Get(); - this.windowSystem = new WindowSystem("DalamudCore"); + this.WindowSystem = new WindowSystem("DalamudCore"); this.changelogWindow = new ChangelogWindow() { IsOpen = false }; this.colorDemoWindow = new ColorDemoWindow() { IsOpen = false }; @@ -77,19 +75,19 @@ namespace Dalamud.Interface.Internal this.settingsWindow = new SettingsWindow() { IsOpen = false }; this.selfTestWindow = new SelfTestWindow() { IsOpen = false }; - this.windowSystem.AddWindow(this.changelogWindow); - this.windowSystem.AddWindow(this.colorDemoWindow); - this.windowSystem.AddWindow(this.componentDemoWindow); - this.windowSystem.AddWindow(this.creditsWindow); - this.windowSystem.AddWindow(this.dataWindow); - this.windowSystem.AddWindow(this.gamepadModeNotifierWindow); - this.windowSystem.AddWindow(this.imeWindow); - this.windowSystem.AddWindow(this.consoleWindow); - this.windowSystem.AddWindow(this.pluginStatWindow); - this.windowSystem.AddWindow(this.pluginWindow); - this.windowSystem.AddWindow(this.scratchpadWindow); - this.windowSystem.AddWindow(this.settingsWindow); - this.windowSystem.AddWindow(this.selfTestWindow); + this.WindowSystem.AddWindow(this.changelogWindow); + this.WindowSystem.AddWindow(this.colorDemoWindow); + this.WindowSystem.AddWindow(this.componentDemoWindow); + this.WindowSystem.AddWindow(this.creditsWindow); + this.WindowSystem.AddWindow(this.dataWindow); + this.WindowSystem.AddWindow(this.gamepadModeNotifierWindow); + this.WindowSystem.AddWindow(this.imeWindow); + this.WindowSystem.AddWindow(this.consoleWindow); + this.WindowSystem.AddWindow(this.pluginStatWindow); + this.WindowSystem.AddWindow(this.pluginWindow); + this.WindowSystem.AddWindow(this.scratchpadWindow); + this.WindowSystem.AddWindow(this.settingsWindow); + this.WindowSystem.AddWindow(this.selfTestWindow); ImGuiManagedAsserts.EnableAsserts = true; @@ -98,6 +96,11 @@ namespace Dalamud.Interface.Internal Log.Information("Windows added"); } + /// + /// Gets the controlling all Dalamud-internal windows. + /// + public WindowSystem WindowSystem { get; init; } + /// /// Gets or sets a value indicating whether the /xldev menu is open. /// @@ -117,7 +120,7 @@ namespace Dalamud.Interface.Internal { Service.Get().Draw -= this.OnDraw; - this.windowSystem.RemoveAllWindows(); + this.WindowSystem.RemoveAllWindows(); this.creditsWindow.Dispose(); this.consoleWindow.Dispose(); @@ -309,7 +312,7 @@ namespace Dalamud.Interface.Internal if (Service.Get().GameUiHidden) return; - this.windowSystem.Draw(); + this.WindowSystem.Draw(); if (this.isImGuiDrawDemoWindow) ImGui.ShowDemoWindow(); diff --git a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs index 62caca3af..3d756ca1d 100644 --- a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs +++ b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs @@ -57,6 +57,8 @@ namespace Dalamud.Interface.Internal.Windows this.Size = new Vector2(500, 400); this.SizeCondition = ImGuiCond.FirstUseEver; + + this.RespectCloseHotkey = false; } private List LogEntries => this.isFiltered ? this.filteredLogText : this.logText; diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs index b506ffcb1..713e91444 100644 --- a/Dalamud/Interface/Windowing/Window.cs +++ b/Dalamud/Interface/Windowing/Window.cs @@ -49,7 +49,7 @@ namespace Dalamud.Interface.Windowing public bool IsFocused { get; private set; } /// - /// Allow this window to be closed with a hotkey, like Escape, and keep game addons open in turn if it is closed. + /// Gets or sets a value indicating whether this window is to be closed with a hotkey, like Escape, and keep game addons open in turn if it is closed. /// public bool RespectCloseHotkey { get; set; } = true; @@ -112,6 +112,9 @@ namespace Dalamud.Interface.Windowing set { this.internalIsOpen = value; + + if (value == false) + this.IsFocused = false; } } diff --git a/Dalamud/Interface/Windowing/WindowSystem.cs b/Dalamud/Interface/Windowing/WindowSystem.cs index 608cd3c15..a87a6b2fa 100644 --- a/Dalamud/Interface/Windowing/WindowSystem.cs +++ b/Dalamud/Interface/Windowing/WindowSystem.cs @@ -22,6 +22,12 @@ namespace Dalamud.Interface.Windowing this.Namespace = imNamespace; } + /// + /// Gets a value indicating whether any window in this has focus and is + /// not marked to be excluded from consideration. + /// + public bool HasAnyFocus { get; private set; } + /// /// Gets or sets the name/ID-space of this . /// @@ -75,6 +81,8 @@ namespace Dalamud.Interface.Windowing window.DrawInternal(); } + this.HasAnyFocus = this.windows.Any(x => x.IsFocused && x.RespectCloseHotkey); + if (hasNamespace) ImGui.PopID(); }