feat(window): wire inactive opacity to main window focus state
This commit is contained in:
@@ -373,6 +373,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
new SelfTests.HoverSheenAllocStep(this),
|
new SelfTests.HoverSheenAllocStep(this),
|
||||||
new SelfTests.HonorificHeaderRenderStep(this),
|
new SelfTests.HonorificHeaderRenderStep(this),
|
||||||
new SelfTests.PerformanceBaselineStep(this),
|
new SelfTests.PerformanceBaselineStep(this),
|
||||||
|
new SelfTests.MainWindowFocusOpacityStep(this),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Re-surface the wizard for existing users when a major UX
|
// Re-surface the wizard for existing users when a major UX
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Plugin.SelfTest;
|
||||||
|
|
||||||
|
namespace HellionChat.SelfTests;
|
||||||
|
|
||||||
|
// UI-12 focus opacity. Pins the pure ResolveBgAlpha contract (focused →
|
||||||
|
// WindowOpacity, unfocused → WindowOpacityInactive). The PreDraw wiring
|
||||||
|
// (BgAlpha = ResolveBgAlpha(IsFocused) behind the main-viewport/!docked guard)
|
||||||
|
// is NOT headless-deterministic — the guard may leave BgAlpha null when
|
||||||
|
// LastViewport is stale on a /xlperf frame — so the wiring is verified by the
|
||||||
|
// reviewer grep (ResolveBgAlpha has a non-test caller: MainWindow.PreDraw) and
|
||||||
|
// the visible transparency by in-game smoke, not by driving PreDraw here.
|
||||||
|
internal sealed class MainWindowFocusOpacityStep : ISelfTestStep
|
||||||
|
{
|
||||||
|
private readonly Plugin plugin;
|
||||||
|
|
||||||
|
public MainWindowFocusOpacityStep(Plugin plugin)
|
||||||
|
{
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name => "Hellion Chat - MainWindow focus opacity";
|
||||||
|
|
||||||
|
public SelfTestStepResult RunStep()
|
||||||
|
{
|
||||||
|
var window = this.plugin.MainWindow;
|
||||||
|
if (window is null)
|
||||||
|
{
|
||||||
|
ImGui.Text("Plugin.MainWindow is null");
|
||||||
|
return SelfTestStepResult.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contract: focused returns the focused opacity, unfocused the inactive one.
|
||||||
|
if (window.ResolveBgAlpha(true) != Plugin.Config.WindowOpacity)
|
||||||
|
{
|
||||||
|
ImGui.Text(
|
||||||
|
$"ResolveBgAlpha(true) = {window.ResolveBgAlpha(true)}, expected {Plugin.Config.WindowOpacity}"
|
||||||
|
);
|
||||||
|
return SelfTestStepResult.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.ResolveBgAlpha(false) != Plugin.Config.WindowOpacityInactive)
|
||||||
|
{
|
||||||
|
ImGui.Text(
|
||||||
|
$"ResolveBgAlpha(false) = {window.ResolveBgAlpha(false)}, expected {Plugin.Config.WindowOpacityInactive}"
|
||||||
|
);
|
||||||
|
return SelfTestStepResult.Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SelfTestStepResult.Pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanUp() { }
|
||||||
|
}
|
||||||
@@ -37,6 +37,9 @@ internal sealed class MainWindow : Window
|
|||||||
public Vector2 LastWindowSize { get; private set; } = Vector2.Zero;
|
public Vector2 LastWindowSize { get; private set; } = Vector2.Zero;
|
||||||
internal unsafe ImGuiViewport* LastViewport;
|
internal unsafe ImGuiViewport* LastViewport;
|
||||||
|
|
||||||
|
// 1.5.6 viewport-guard input: tracked in Draw, read by PreDraw next frame.
|
||||||
|
private bool _wasDocked;
|
||||||
|
|
||||||
public MainWindow(
|
public MainWindow(
|
||||||
Components.HonorificHeader honorific,
|
Components.HonorificHeader honorific,
|
||||||
Components.Sidebar sidebar,
|
Components.Sidebar sidebar,
|
||||||
@@ -70,6 +73,35 @@ internal sealed class MainWindow : Window
|
|||||||
RespectCloseHotkey = false;
|
RespectCloseHotkey = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UI-12: per-window focus-dependent opacity. ResolveBgAlpha stays guard-free
|
||||||
|
// and pure so the self-test can drive it directly; PreDraw owns the guard +
|
||||||
|
// wiring. 1.5.6 parity (focused → WindowOpacity, unfocused →
|
||||||
|
// WindowOpacityInactive, ChatLogWindow.PreOpenCheck 1d3b429:724).
|
||||||
|
internal float ResolveBgAlpha(bool isFocused) =>
|
||||||
|
isFocused ? Plugin.Config.WindowOpacity : Plugin.Config.WindowOpacityInactive;
|
||||||
|
|
||||||
|
public override void PreDraw()
|
||||||
|
{
|
||||||
|
// Dalamud's WindowHost turns Window.BgAlpha into SetNextWindowBgAlpha
|
||||||
|
// (WindowHost.cs:650-652), which REPLACES this one window's WindowBg
|
||||||
|
// alpha (imgui.cpp:7229). The global GlobalStyleScope clamp is left
|
||||||
|
// untouched, so Settings/DbViewer/popouts/wizard keep today's opacity.
|
||||||
|
// Viewport guard (1.5.6 parity, ChatLogWindow.PreOpenCheck 1d3b429:718):
|
||||||
|
// only drive BgAlpha while the window is on the main viewport and not
|
||||||
|
// docked. On a floated own-viewport (Dalamud multi-viewport mode) the
|
||||||
|
// WindowBg alpha would compose against the OS-layer alpha (double
|
||||||
|
// transparency), so leave BgAlpha null there and let the global scope
|
||||||
|
// govern. LastViewport/_wasDocked are last frame's values from Draw
|
||||||
|
// (one-frame latency, accepted, matches 1.5.6).
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
if (LastViewport == ImGuiHelpers.MainViewport.Handle && !_wasDocked)
|
||||||
|
BgAlpha = ResolveBgAlpha(IsFocused);
|
||||||
|
else
|
||||||
|
BgAlpha = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Tab? ActiveTab => _activeTab;
|
public Tab? ActiveTab => _activeTab;
|
||||||
|
|
||||||
// Internal accessors for self-tests so the probes can reach the live
|
// Internal accessors for self-tests so the probes can reach the live
|
||||||
@@ -99,6 +131,7 @@ internal sealed class MainWindow : Window
|
|||||||
{
|
{
|
||||||
LastViewport = ImGui.GetWindowViewport().Handle;
|
LastViewport = ImGui.GetWindowViewport().Handle;
|
||||||
}
|
}
|
||||||
|
_wasDocked = ImGui.IsWindowDocked();
|
||||||
|
|
||||||
// Primary pool-reset path; InputPreview has a defensive fallback for the MainWindow-closed edge case.
|
// Primary pool-reset path; InputPreview has a defensive fallback for the MainWindow-closed edge case.
|
||||||
_handlerLender.ResetCounter();
|
_handlerLender.ResetCounter();
|
||||||
|
|||||||
Reference in New Issue
Block a user