Reported by Carla: a tell arriving while you are typing pulls the focus away. The interruption is the visible half. The sharp half is that the input buffer belongs to the WINDOW while the send target is read off whatever tab is active at Enter -- so a line typed at one person could leave addressed to whoever just wrote, and in this game losing the keyboard means the next sentence walks the character around. Nothing is revealed now while any chat surface is mid-sentence, in any mode. The tab still appears and still carries its unread mark. The check lives in its own file because the answer has to be identical everywhere: it started inside the reveal plan, and a second pop-out path walked straight past it -- AutoTellTabsService opened windows off its own flag, at tab creation, a tick before the router was ever asked. Those two paths are one now. AutoTellTabsOpenAsPopout and TellAutoOpenMode were two settings for one decision, and the older one won every race, which is why the other looked inert. Config schema 28 carries the old flag forward so nobody's behaviour changes. "Off" went with it: it never stopped the tab from being created -- that is the auto-tell switch -- it only stopped the jump to it, which is what the switch below it does. Also in here, all from the same corner of the code: - Closing a tab was lost in the v2.0.0 rebuild. The trash entry lived in the retired ChatLogWindow menu, and the rebuilt one restored rename, sound, pop-out and pinning but not this. For tell tabs that left no way out at all: IsEditable keeps them out of the settings editor on purpose and points at the context menu, which could not close them either. Pinned tell tabs stay disabled with a tooltip rather than absent. - Re-anchoring the active tab used an unconditional Tabs[0] in three places, and Tabs[0] can be popped out -- so it ran OnTabActivated over a tab live in its own window and stripped its tell binding. With every tab popped, the seed and the re-anchor also fought each other every frame. - PinTab_LimitReached still pointed at "Promote to permanent", removed in May. Spanish said "Desija", which is not a word; Greek left "tell tabs" untranslated; pt-PT broke its own unpin verb. - Pop Out was a hardcoded English literal despite the key existing in all 25 languages since v1.5.6, and the tell-open modes were the last English display names in the plugin. - Segmented setting rows measured 200px flat, which cut German labels in half. They size to their longest label now. - Metrics.Scale still called GlobalScaleSafe. It is an alias for GlobalScale in current Dalamud, and dropping it clears the last compiler warning in the project.
117 lines
5.4 KiB
C#
117 lines
5.4 KiB
C#
using Dalamud.Bindings.ImGui;
|
|
using Dalamud.Interface.Utility;
|
|
using HellionChat.Util;
|
|
|
|
namespace HellionChat.Ui.StyleEngine;
|
|
|
|
// Layout values, authored at 100% display scaling. Draw code reads the scaled
|
|
// properties; the Raw constants exist only for the few places that must store or
|
|
// compare an unscaled value (Sidebar.GetWidth, the width slider bounds).
|
|
//
|
|
// Deliberately NOT part of ThemeLayout: that record is serialised into theme
|
|
// JSON, and layout customisation is deliberately out of scope.
|
|
internal static class Metrics
|
|
{
|
|
// --- Sidebar ---
|
|
internal const float SidebarIconOnlyWidthRaw = 38f;
|
|
internal const float SidebarMinWidthRaw = 40f;
|
|
internal const float SidebarMaxWidthRaw = 300f;
|
|
internal const float SidebarRowHeightRaw = 32f;
|
|
internal const float SidebarPopOutHitWidthRaw = 22f;
|
|
internal const float SidebarGreetedHitWidthRaw = 22f;
|
|
internal const float SidebarHitSlackRaw = 4f;
|
|
internal const float SidebarMinDrawWidthRaw = 2f;
|
|
internal const float SidebarUnreadRadiusRaw = 4f;
|
|
internal const float SidebarGlyphInsetRaw = 4f;
|
|
|
|
// --- Input bar ---
|
|
internal const float InputBarHeightRaw = 32f;
|
|
|
|
// Two ghost buttons since v1.14.0 -- symbols and the more-menu. Everything
|
|
// else moved into the menu, and the hundred-odd pixels went back to the
|
|
// input field.
|
|
internal const float InputQuickButtonsReserveRaw = 62f;
|
|
|
|
// --- Honorific header ---
|
|
internal const float HonorificHeightRaw = 30f;
|
|
internal const float HonorificInsetRaw = 8f;
|
|
internal const float HonorificBracketGapRaw = 6f;
|
|
|
|
// --- Top tab bar ---
|
|
internal const float TopTabUnreadInsetRaw = 4f;
|
|
internal const float TopTabPaddingXRaw = 10f;
|
|
internal const float TopTabUnderlineRaw = 2f;
|
|
|
|
// --- Status bar ---
|
|
internal const float StatusBorderThicknessRaw = 1f;
|
|
internal const float StatusTopSpacerRaw = 2f;
|
|
|
|
// --- Message list ---
|
|
internal const float MessageDummyWidthRaw = 10f;
|
|
|
|
private static float _cachedScale = 1f;
|
|
private static int _cachedFrame = -1;
|
|
|
|
// GlobalScale resolves to ImGui.GetIO().FontGlobalScale, which the Dalamud
|
|
// settings slider moves on every frame while it is dragged. Pinning it once
|
|
// per frame keeps a CalcSize and its matching Draw on the same value, and
|
|
// saves three native calls per access.
|
|
internal static float Scale
|
|
{
|
|
get
|
|
{
|
|
var frame = ImGui.GetFrameCount();
|
|
if (frame == _cachedFrame)
|
|
return _cachedScale;
|
|
|
|
// GlobalScale is what the retired GlobalScaleSafe alias forwarded to;
|
|
// it falls back to the Dalamud config scale when ImGui is not up yet.
|
|
// That does not make this property pre-init safe on its own -- the
|
|
// GetFrameCount above would fault first -- but every Metrics caller
|
|
// sits under Ui/ and only runs while drawing.
|
|
_cachedScale = ImGuiHelpers.GlobalScale;
|
|
_cachedFrame = frame;
|
|
return _cachedScale;
|
|
}
|
|
}
|
|
|
|
internal static float SidebarIconOnlyWidth => MetricsMath.Scale(SidebarIconOnlyWidthRaw, Scale);
|
|
internal static float SidebarRowHeight => MetricsMath.Scale(SidebarRowHeightRaw, Scale);
|
|
internal static float SidebarPopOutHitWidth =>
|
|
MetricsMath.Scale(SidebarPopOutHitWidthRaw, Scale);
|
|
internal static float SidebarGreetedHitWidth =>
|
|
MetricsMath.Scale(SidebarGreetedHitWidthRaw, Scale);
|
|
internal static float SidebarHitSlack => MetricsMath.Scale(SidebarHitSlackRaw, Scale);
|
|
internal static float SidebarMinDrawWidth => MetricsMath.Scale(SidebarMinDrawWidthRaw, Scale);
|
|
internal static float SidebarUnreadRadius => MetricsMath.Scale(SidebarUnreadRadiusRaw, Scale);
|
|
internal static float SidebarGlyphInset => MetricsMath.Scale(SidebarGlyphInsetRaw, Scale);
|
|
|
|
internal static float InputBarHeight => MetricsMath.Scale(InputBarHeightRaw, Scale);
|
|
internal static float InputQuickButtonsReserve =>
|
|
MetricsMath.Scale(InputQuickButtonsReserveRaw, Scale);
|
|
|
|
internal static float HonorificHeight => MetricsMath.Scale(HonorificHeightRaw, Scale);
|
|
internal static float HonorificInset => MetricsMath.Scale(HonorificInsetRaw, Scale);
|
|
internal static float HonorificBracketGap => MetricsMath.Scale(HonorificBracketGapRaw, Scale);
|
|
|
|
internal static float TopTabUnreadInset => MetricsMath.Scale(TopTabUnreadInsetRaw, Scale);
|
|
internal static float TopTabPaddingX => MetricsMath.Scale(TopTabPaddingXRaw, Scale);
|
|
internal static float TopTabUnderline => MetricsMath.Scale(TopTabUnderlineRaw, Scale);
|
|
|
|
// Measured, not scaled: the tab has to fit the text, and the font comes from
|
|
// Config.FontSizeV2 which display scaling does not feed into.
|
|
internal static float TopTabHeight => ImGui.GetTextLineHeight() + MathF.Round(10f * Scale);
|
|
|
|
internal static float StatusBorderThickness =>
|
|
MetricsMath.Scale(StatusBorderThicknessRaw, Scale);
|
|
internal static float StatusTopSpacer => MathF.Round(StatusTopSpacerRaw * Scale);
|
|
|
|
internal static float MessageDummyWidth => MetricsMath.Scale(MessageDummyWidthRaw, Scale);
|
|
|
|
// Text-dependent heights are measured, never scaled: the font is built from
|
|
// Config.FontSizeV2, which GlobalScale does not feed into. StatusBar.Height
|
|
// has done it this way since 1.8.x.
|
|
internal static float CenterY(float rowHeight) =>
|
|
MetricsMath.CenterY(rowHeight, ImGui.GetTextLineHeight());
|
|
}
|