mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-03 14:23:40 +01:00
Merge pull request #1699 from Soreepeong/fix/ime-perf
Fix Chinese IME lagging
This commit is contained in:
commit
7ee20272de
6 changed files with 620 additions and 531 deletions
|
|
@ -96,12 +96,6 @@ internal class DalamudCommands : IServiceType
|
|||
ShowInHelp = false,
|
||||
});
|
||||
|
||||
commandManager.AddHandler("/xlime", new CommandInfo(this.OnDebugDrawIMEPanel)
|
||||
{
|
||||
HelpMessage = Loc.Localize("DalamudIMEPanelHelp", "Draw IME panel"),
|
||||
ShowInHelp = false,
|
||||
});
|
||||
|
||||
commandManager.AddHandler("/xllog", new CommandInfo(this.OnOpenLog)
|
||||
{
|
||||
HelpMessage = Loc.Localize("DalamudDevLogHelp", "Open dev log DEBUG"),
|
||||
|
|
@ -308,11 +302,6 @@ internal class DalamudCommands : IServiceType
|
|||
dalamudInterface.ToggleDataWindow(arguments);
|
||||
}
|
||||
|
||||
private void OnDebugDrawIMEPanel(string command, string arguments)
|
||||
{
|
||||
Service<DalamudInterface>.Get().OpenImeWindow();
|
||||
}
|
||||
|
||||
private void OnOpenLog(string command, string arguments)
|
||||
{
|
||||
Service<DalamudInterface>.Get().ToggleLogWindow();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -61,7 +61,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
private readonly ComponentDemoWindow componentDemoWindow;
|
||||
private readonly DataWindow dataWindow;
|
||||
private readonly GamepadModeNotifierWindow gamepadModeNotifierWindow;
|
||||
private readonly DalamudImeWindow imeWindow;
|
||||
private readonly ConsoleWindow consoleWindow;
|
||||
private readonly PluginStatWindow pluginStatWindow;
|
||||
private readonly PluginInstallerWindow pluginWindow;
|
||||
|
|
@ -114,7 +113,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
this.componentDemoWindow = new ComponentDemoWindow() { IsOpen = false };
|
||||
this.dataWindow = new DataWindow() { IsOpen = false };
|
||||
this.gamepadModeNotifierWindow = new GamepadModeNotifierWindow() { IsOpen = false };
|
||||
this.imeWindow = new DalamudImeWindow() { IsOpen = false };
|
||||
this.consoleWindow = new ConsoleWindow(configuration) { IsOpen = configuration.LogOpenAtStartup };
|
||||
this.pluginStatWindow = new PluginStatWindow() { IsOpen = false };
|
||||
this.pluginWindow = new PluginInstallerWindow(pluginImageCache, configuration) { IsOpen = false };
|
||||
|
|
@ -142,7 +140,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
this.WindowSystem.AddWindow(this.componentDemoWindow);
|
||||
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);
|
||||
|
|
@ -265,11 +262,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
/// </summary>
|
||||
public void OpenGamepadModeNotifierWindow() => this.gamepadModeNotifierWindow.IsOpen = true;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the <see cref="DalamudImeWindow"/>.
|
||||
/// </summary>
|
||||
public void OpenImeWindow() => this.imeWindow.IsOpen = true;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the <see cref="ConsoleWindow"/>.
|
||||
/// </summary>
|
||||
|
|
@ -365,11 +357,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
|
||||
#region Close
|
||||
|
||||
/// <summary>
|
||||
/// Closes the <see cref="DalamudImeWindow"/>.
|
||||
/// </summary>
|
||||
public void CloseImeWindow() => this.imeWindow.IsOpen = false;
|
||||
|
||||
/// <summary>
|
||||
/// Closes the <see cref="GamepadModeNotifierWindow"/>.
|
||||
/// </summary>
|
||||
|
|
@ -417,11 +404,6 @@ internal class DalamudInterface : IDisposable, IServiceType
|
|||
/// </summary>
|
||||
public void ToggleGamepadModeNotifierWindow() => this.gamepadModeNotifierWindow.Toggle();
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the <see cref="DalamudImeWindow"/>.
|
||||
/// </summary>
|
||||
public void ToggleImeWindow() => this.imeWindow.Toggle();
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the <see cref="ConsoleWindow"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -67,9 +67,6 @@ internal class InterfaceManager : IDisposable, IServiceType
|
|||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly WndProcHookManager wndProcHookManager = Service<WndProcHookManager>.Get();
|
||||
|
||||
[ServiceManager.ServiceDependency]
|
||||
private readonly DalamudIme dalamudIme = Service<DalamudIme>.Get();
|
||||
|
||||
private readonly SwapChainVtableResolver address = new();
|
||||
private readonly Hook<SetCursorDelegate> setCursorHook;
|
||||
|
|
@ -627,8 +624,6 @@ internal class InterfaceManager : IDisposable, IServiceType
|
|||
var r = this.scene?.ProcessWndProcW(args.Hwnd, (User32.WindowMessage)args.Message, args.WParam, args.LParam);
|
||||
if (r is not null)
|
||||
args.SuppressWithValue(r.Value);
|
||||
|
||||
this.dalamudIme.ProcessImeMessage(args);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,266 +0,0 @@
|
|||
using System.Numerics;
|
||||
|
||||
using Dalamud.Interface.Windowing;
|
||||
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Dalamud.Interface.Internal.Windows;
|
||||
|
||||
/// <summary>
|
||||
/// A window for displaying IME details.
|
||||
/// </summary>
|
||||
internal unsafe class DalamudImeWindow : Window
|
||||
{
|
||||
private const int ImePageSize = 9;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DalamudImeWindow"/> class.
|
||||
/// </summary>
|
||||
public DalamudImeWindow()
|
||||
: base(
|
||||
"Dalamud IME",
|
||||
ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoBackground)
|
||||
{
|
||||
this.Size = default(Vector2);
|
||||
|
||||
this.RespectCloseHotkey = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Draw()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void PostDraw()
|
||||
{
|
||||
if (Service<DalamudIme>.GetNullable() is not { } ime)
|
||||
return;
|
||||
|
||||
var viewport = ime.AssociatedViewport;
|
||||
if (viewport.NativePtr is null)
|
||||
return;
|
||||
|
||||
var drawCand = ime.ImmCand.Count != 0;
|
||||
var drawConv = drawCand || ime.ShowPartialConversion;
|
||||
var drawIme = ime.InputModeIcon != 0;
|
||||
var imeIconFont = InterfaceManager.DefaultFont;
|
||||
|
||||
var pad = ImGui.GetStyle().WindowPadding;
|
||||
var candTextSize = ImGui.CalcTextSize(ime.ImmComp == string.Empty ? " " : ime.ImmComp);
|
||||
|
||||
var native = ime.ImmCandNative;
|
||||
var totalIndex = native.dwSelection + 1;
|
||||
var totalSize = native.dwCount;
|
||||
|
||||
var pageStart = native.dwPageStart;
|
||||
var pageIndex = (pageStart / ImePageSize) + 1;
|
||||
var pageCount = (totalSize / ImePageSize) + 1;
|
||||
var pageInfo = $"{totalIndex}/{totalSize} ({pageIndex}/{pageCount})";
|
||||
|
||||
// Calc the window size.
|
||||
var maxTextWidth = 0f;
|
||||
for (var i = 0; i < ime.ImmCand.Count; i++)
|
||||
{
|
||||
var textSize = ImGui.CalcTextSize($"{i + 1}. {ime.ImmCand[i]}");
|
||||
maxTextWidth = maxTextWidth > textSize.X ? maxTextWidth : textSize.X;
|
||||
}
|
||||
|
||||
maxTextWidth = maxTextWidth > ImGui.CalcTextSize(pageInfo).X ? maxTextWidth : ImGui.CalcTextSize(pageInfo).X;
|
||||
maxTextWidth = maxTextWidth > ImGui.CalcTextSize(ime.ImmComp).X
|
||||
? maxTextWidth
|
||||
: ImGui.CalcTextSize(ime.ImmComp).X;
|
||||
|
||||
var numEntries = (drawCand ? ime.ImmCand.Count + 1 : 0) + 1 + (drawIme ? 1 : 0);
|
||||
var spaceY = ImGui.GetStyle().ItemSpacing.Y;
|
||||
var imeWindowHeight = (spaceY * (numEntries - 1)) + (candTextSize.Y * numEntries);
|
||||
var windowSize = new Vector2(maxTextWidth, imeWindowHeight) + (pad * 2);
|
||||
|
||||
// 1. Figure out the expanding direction.
|
||||
var expandUpward = ime.CursorPos.Y + windowSize.Y > viewport.WorkPos.Y + viewport.WorkSize.Y;
|
||||
var windowPos = ime.CursorPos - pad;
|
||||
if (expandUpward)
|
||||
{
|
||||
windowPos.Y -= windowSize.Y - candTextSize.Y - (pad.Y * 2);
|
||||
if (drawIme)
|
||||
windowPos.Y += candTextSize.Y + spaceY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (drawIme)
|
||||
windowPos.Y -= candTextSize.Y + spaceY;
|
||||
}
|
||||
|
||||
// 2. Contain within the viewport. Do not use clamp, as the target window might be too small.
|
||||
if (windowPos.X < viewport.WorkPos.X)
|
||||
windowPos.X = viewport.WorkPos.X;
|
||||
else if (windowPos.X + windowSize.X > viewport.WorkPos.X + viewport.WorkSize.X)
|
||||
windowPos.X = (viewport.WorkPos.X + viewport.WorkSize.X) - windowSize.X;
|
||||
if (windowPos.Y < viewport.WorkPos.Y)
|
||||
windowPos.Y = viewport.WorkPos.Y;
|
||||
else if (windowPos.Y + windowSize.Y > viewport.WorkPos.Y + viewport.WorkSize.Y)
|
||||
windowPos.Y = (viewport.WorkPos.Y + viewport.WorkSize.Y) - windowSize.Y;
|
||||
|
||||
var cursor = windowPos + pad;
|
||||
|
||||
// Draw the ime window.
|
||||
var drawList = ImGui.GetForegroundDrawList(viewport);
|
||||
|
||||
// Draw the background rect for candidates.
|
||||
if (drawCand)
|
||||
{
|
||||
Vector2 candRectLt, candRectRb;
|
||||
if (!expandUpward)
|
||||
{
|
||||
candRectLt = windowPos + candTextSize with { X = 0 } + pad with { X = 0 };
|
||||
candRectRb = windowPos + windowSize;
|
||||
if (drawIme)
|
||||
candRectLt.Y += spaceY + candTextSize.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
candRectLt = windowPos;
|
||||
candRectRb = windowPos + (windowSize - candTextSize with { X = 0 } - pad with { X = 0 });
|
||||
if (drawIme)
|
||||
candRectRb.Y -= spaceY + candTextSize.Y;
|
||||
}
|
||||
|
||||
drawList.AddRectFilled(
|
||||
candRectLt,
|
||||
candRectRb,
|
||||
ImGui.GetColorU32(ImGuiCol.WindowBg),
|
||||
ImGui.GetStyle().WindowRounding);
|
||||
}
|
||||
|
||||
if (!expandUpward && drawIme)
|
||||
{
|
||||
for (var dx = -2; dx <= 2; dx++)
|
||||
{
|
||||
for (var dy = -2; dy <= 2; dy++)
|
||||
{
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
imeIconFont.RenderChar(
|
||||
drawList,
|
||||
imeIconFont.FontSize,
|
||||
cursor + new Vector2(dx, dy),
|
||||
ImGui.GetColorU32(ImGuiCol.WindowBg),
|
||||
ime.InputModeIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imeIconFont.RenderChar(
|
||||
drawList,
|
||||
imeIconFont.FontSize,
|
||||
cursor,
|
||||
ImGui.GetColorU32(ImGuiCol.Text),
|
||||
ime.InputModeIcon);
|
||||
cursor.Y += candTextSize.Y + spaceY;
|
||||
}
|
||||
|
||||
if (!expandUpward && drawConv)
|
||||
{
|
||||
DrawTextBeingConverted();
|
||||
cursor.Y += candTextSize.Y + spaceY;
|
||||
|
||||
// Add a separator.
|
||||
drawList.AddLine(cursor, cursor + new Vector2(maxTextWidth, 0), ImGui.GetColorU32(ImGuiCol.Separator));
|
||||
}
|
||||
|
||||
if (drawCand)
|
||||
{
|
||||
// Add the candidate words.
|
||||
for (var i = 0; i < ime.ImmCand.Count; i++)
|
||||
{
|
||||
var selected = i == (native.dwSelection % ImePageSize);
|
||||
var color = ImGui.GetColorU32(ImGuiCol.Text);
|
||||
if (selected)
|
||||
color = ImGui.GetColorU32(ImGuiCol.NavHighlight);
|
||||
|
||||
drawList.AddText(cursor, color, $"{i + 1}. {ime.ImmCand[i]}");
|
||||
cursor.Y += candTextSize.Y + spaceY;
|
||||
}
|
||||
|
||||
// Add a separator
|
||||
drawList.AddLine(cursor, cursor + new Vector2(maxTextWidth, 0), ImGui.GetColorU32(ImGuiCol.Separator));
|
||||
|
||||
// Add the pages infomation.
|
||||
drawList.AddText(cursor, ImGui.GetColorU32(ImGuiCol.Text), pageInfo);
|
||||
cursor.Y += candTextSize.Y + spaceY;
|
||||
}
|
||||
|
||||
if (expandUpward && drawConv)
|
||||
{
|
||||
// Add a separator.
|
||||
drawList.AddLine(cursor, cursor + new Vector2(maxTextWidth, 0), ImGui.GetColorU32(ImGuiCol.Separator));
|
||||
|
||||
DrawTextBeingConverted();
|
||||
cursor.Y += candTextSize.Y + spaceY;
|
||||
}
|
||||
|
||||
if (expandUpward && drawIme)
|
||||
{
|
||||
for (var dx = -2; dx <= 2; dx++)
|
||||
{
|
||||
for (var dy = -2; dy <= 2; dy++)
|
||||
{
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
imeIconFont.RenderChar(
|
||||
drawList,
|
||||
imeIconFont.FontSize,
|
||||
cursor + new Vector2(dx, dy),
|
||||
ImGui.GetColorU32(ImGuiCol.WindowBg),
|
||||
ime.InputModeIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imeIconFont.RenderChar(
|
||||
drawList,
|
||||
imeIconFont.FontSize,
|
||||
cursor,
|
||||
ImGui.GetColorU32(ImGuiCol.Text),
|
||||
ime.InputModeIcon);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
void DrawTextBeingConverted()
|
||||
{
|
||||
// Draw the text background.
|
||||
drawList.AddRectFilled(
|
||||
cursor - (pad / 2),
|
||||
cursor + candTextSize + (pad / 2),
|
||||
ImGui.GetColorU32(ImGuiCol.WindowBg));
|
||||
|
||||
// If only a part of the full text is marked for conversion, then draw background for the part being edited.
|
||||
if (ime.PartialConversionFrom != 0 || ime.PartialConversionTo != ime.ImmComp.Length)
|
||||
{
|
||||
var part1 = ime.ImmComp[..ime.PartialConversionFrom];
|
||||
var part2 = ime.ImmComp[..ime.PartialConversionTo];
|
||||
var size1 = ImGui.CalcTextSize(part1);
|
||||
var size2 = ImGui.CalcTextSize(part2);
|
||||
drawList.AddRectFilled(
|
||||
cursor + size1 with { Y = 0 },
|
||||
cursor + size2,
|
||||
ImGui.GetColorU32(ImGuiCol.TextSelectedBg));
|
||||
}
|
||||
|
||||
// Add the text being converted.
|
||||
drawList.AddText(cursor, ImGui.GetColorU32(ImGuiCol.Text), ime.ImmComp);
|
||||
|
||||
// Draw the caret inside the composition string.
|
||||
if (DalamudIme.ShowCursorInInputText)
|
||||
{
|
||||
var partBeforeCaret = ime.ImmComp[..ime.CompositionCursorOffset];
|
||||
var sizeBeforeCaret = ImGui.CalcTextSize(partBeforeCaret);
|
||||
drawList.AddLine(
|
||||
cursor + sizeBeforeCaret with { Y = 0 },
|
||||
cursor + sizeBeforeCaret,
|
||||
ImGui.GetColorU32(ImGuiCol.Text));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -165,6 +165,7 @@ internal static class ServiceManager
|
|||
|
||||
var earlyLoadingServices = new HashSet<Type>();
|
||||
var blockingEarlyLoadingServices = new HashSet<Type>();
|
||||
var providedServices = new HashSet<Type>();
|
||||
|
||||
var dependencyServicesMap = new Dictionary<Type, List<Type>>();
|
||||
var getAsyncTaskMap = new Dictionary<Type, Task>();
|
||||
|
|
@ -197,7 +198,10 @@ internal static class ServiceManager
|
|||
|
||||
// We don't actually need to load provided services, something else does
|
||||
if (serviceKind.HasFlag(ServiceKind.ProvidedService))
|
||||
{
|
||||
providedServices.Add(serviceType);
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(
|
||||
serviceKind.HasFlag(ServiceKind.EarlyLoadedService) ||
|
||||
|
|
@ -340,7 +344,16 @@ internal static class ServiceManager
|
|||
}
|
||||
|
||||
if (!tasks.Any())
|
||||
throw new InvalidOperationException("Unresolvable dependency cycle detected");
|
||||
{
|
||||
// No more services we can start loading for now.
|
||||
// Either we're waiting for provided services, or there's a dependency cycle.
|
||||
providedServices.RemoveWhere(x => getAsyncTaskMap[x].IsCompleted);
|
||||
if (providedServices.Any())
|
||||
await Task.WhenAny(providedServices.Select(x => getAsyncTaskMap[x]));
|
||||
else
|
||||
throw new InvalidOperationException("Unresolvable dependency cycle detected");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (servicesToLoad.Any())
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue