Merge pull request #2346 from Soreepeong/fix/imgui

Fix/imgui
This commit is contained in:
goat 2025-08-07 02:11:38 +02:00 committed by GitHub
commit 0ca890ebca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 63 additions and 24 deletions

View file

@ -68,7 +68,7 @@
<PackageReference Include="goatcorp.Reloaded.Assembler" Version="1.0.14-goatcorp3" /> <PackageReference Include="goatcorp.Reloaded.Assembler" Version="1.0.14-goatcorp3" />
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" /> <PackageReference Include="JetBrains.Annotations" Version="2024.2.0" />
<PackageReference Include="Lumina" Version="$(LuminaVersion)" /> <PackageReference Include="Lumina" Version="$(LuminaVersion)" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0-preview.1.24081.5" /> <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.7" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183"> <PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.183">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>

View file

@ -245,6 +245,9 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
return default(LRESULT); return default(LRESULT);
} }
if (ImGui.IsAnyItemActive())
ImGui.ClearWindowFocus();
break; break;
} }
@ -531,7 +534,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
// We still want to return MA_NOACTIVATE // We still want to return MA_NOACTIVATE
// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mouseactivate // https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-mouseactivate
return 0x3; return MA.MA_NOACTIVATE;
case WM.WM_NCHITTEST: case WM.WM_NCHITTEST:
// Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL). // Let mouse pass-through the window. This will allow the backend to set io.MouseHoveredViewport properly (which is OPTIONAL).
// The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging. // The ImGuiViewportFlags_NoInputs flag is set while dragging a viewport, as want to detect the window behind the one we are dragging.
@ -539,8 +542,7 @@ internal sealed unsafe partial class Win32InputHandler : IImGuiInputHandler
// your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system. // your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system.
if (viewport.Flags.HasFlag(ImGuiViewportFlags.NoInputs)) if (viewport.Flags.HasFlag(ImGuiViewportFlags.NoInputs))
{ {
// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest return HTTRANSPARENT;
return -1;
} }
break; break;

View file

@ -575,16 +575,6 @@ internal class DalamudInterface : IInternalDisposableService
if (this.isCreditsDarkening) if (this.isCreditsDarkening)
this.DrawCreditsDarkeningAnimation(); this.DrawCreditsDarkeningAnimation();
// Release focus of any ImGui window if we click into the game.
var io = ImGui.GetIO();
if (!io.WantCaptureMouse && (global::Windows.Win32.PInvoke.GetKeyState((int)VirtualKey.LBUTTON) & 0x8000) != 0)
{
unsafe
{
ImGui.SetWindowFocus((byte*)null);
}
}
} }
catch (Exception ex) catch (Exception ex)
{ {

File diff suppressed because one or more lines are too long

View file

@ -9,6 +9,7 @@ using System.Reflection.Emit;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
@ -27,6 +28,8 @@ using Windows.Win32.System.Memory;
using Windows.Win32.System.Ole; using Windows.Win32.System.Ole;
using Windows.Win32.UI.WindowsAndMessaging; using Windows.Win32.UI.WindowsAndMessaging;
using Dalamud.Interface.Internal;
using FLASHWINFO = Windows.Win32.UI.WindowsAndMessaging.FLASHWINFO; using FLASHWINFO = Windows.Win32.UI.WindowsAndMessaging.FLASHWINFO;
using HWND = Windows.Win32.Foundation.HWND; using HWND = Windows.Win32.Foundation.HWND;
using MEMORY_BASIC_INFORMATION = Windows.Win32.System.Memory.MEMORY_BASIC_INFORMATION; using MEMORY_BASIC_INFORMATION = Windows.Win32.System.Memory.MEMORY_BASIC_INFORMATION;
@ -522,17 +525,36 @@ public static partial class Util
public static bool IsWindows11() => Environment.OSVersion.Version.Build >= 22000; public static bool IsWindows11() => Environment.OSVersion.Version.Build >= 22000;
/// <summary> /// <summary>
/// Open a link in the default browser. /// Open a link in the default browser, and attempts to focus the newly launched application.
/// </summary> /// </summary>
/// <param name="url">The link to open.</param> /// <param name="url">The link to open.</param>
public static void OpenLink(string url) public static void OpenLink(string url) => new Thread(
{ static url =>
var process = new ProcessStartInfo(url)
{ {
UseShellExecute = true, try
}; {
Process.Start(process); var psi = new ProcessStartInfo((string)url!)
} {
UseShellExecute = true,
ErrorDialogParentHandle = Service<InterfaceManager>.GetNullable() is { } im
? im.GameWindowHandle
: 0,
Verb = "open",
};
if (Process.Start(psi) is not { } process)
return;
if (process.Id != 0)
TerraFX.Interop.Windows.Windows.AllowSetForegroundWindow((uint)process.Id);
process.WaitForInputIdle();
TerraFX.Interop.Windows.Windows.SetForegroundWindow(
(TerraFX.Interop.Windows.HWND)process.MainWindowHandle);
}
catch (Exception e)
{
Log.Error(e, "{fn}: failed to open {url}", nameof(OpenLink), url);
}
}).Start(url);
/// <summary> /// <summary>
/// Perform a "zipper merge" (A, 1, B, 2, C, 3) of multiple enumerables, allowing for lists to end early. /// Perform a "zipper merge" (A, 1, B, 2, C, 3) of multiple enumerables, allowing for lists to end early.

View file

@ -564,8 +564,12 @@ public static unsafe partial class ImGui
name.Dispose(); name.Dispose();
} }
/// <summary>Sets the current window to be focused / top-most.</summary>
/// <remarks>Prefer using <see cref="SetNextWindowFocus"/>.</remarks>
public static void SetWindowFocus() => ImGuiNative.SetWindowFocus(); public static void SetWindowFocus() => ImGuiNative.SetWindowFocus();
/// <summary>Sets a named window to be focused / top-most.</summary>
/// <param name="name">Name of the window to focus. Use <c>default</c> to remove focus.</param>
public static void SetWindowFocus(ImU8String name) public static void SetWindowFocus(ImU8String name)
{ {
fixed (byte* namePtr = &name.GetPinnableNullTerminatedReference()) fixed (byte* namePtr = &name.GetPinnableNullTerminatedReference())
@ -573,6 +577,9 @@ public static unsafe partial class ImGui
name.Dispose(); name.Dispose();
} }
/// <summary>Removes focus from any window.</summary>
public static void ClearWindowFocus() => ImGuiNative.SetWindowFocus(null);
public static void SetWindowPos(Vector2 pos, ImGuiCond cond = ImGuiCond.None) => public static void SetWindowPos(Vector2 pos, ImGuiCond cond = ImGuiCond.None) =>
ImGuiNative.SetWindowPos(pos, cond); ImGuiNative.SetWindowPos(pos, cond);

View file

@ -35,7 +35,7 @@ public ref struct ImU8String : IDisposable
} }
public ImU8String(int literalLength, int formattedCount) public ImU8String(int literalLength, int formattedCount)
: this(ReadOnlySpan<byte>.Empty) : this(""u8)
{ {
this.state |= State.Interpolation; this.state |= State.Interpolation;
literalLength += formattedCount * 4; literalLength += formattedCount * 4;
@ -51,6 +51,12 @@ public ref struct ImU8String : IDisposable
public ImU8String(ReadOnlySpan<byte> text, bool ensureNullTermination = false) public ImU8String(ReadOnlySpan<byte> text, bool ensureNullTermination = false)
: this() : this()
{ {
if (Unsafe.IsNullRef(in MemoryMarshal.GetReference(text)))
{
this.state = State.None;
return;
}
this.state = State.Initialized; this.state = State.Initialized;
if (text.IsEmpty) if (text.IsEmpty)
{ {
@ -82,6 +88,12 @@ public ref struct ImU8String : IDisposable
public ImU8String(ReadOnlySpan<char> text) public ImU8String(ReadOnlySpan<char> text)
: this() : this()
{ {
if (Unsafe.IsNullRef(in MemoryMarshal.GetReference(text)))
{
this.state = State.None;
return;
}
this.state = State.Initialized | State.NullTerminated; this.state = State.Initialized | State.NullTerminated;
this.Length = Encoding.UTF8.GetByteCount(text); this.Length = Encoding.UTF8.GetByteCount(text);
if (this.Length + 1 < AllocFreeBufferSize) if (this.Length + 1 < AllocFreeBufferSize)
@ -313,6 +325,12 @@ public ref struct ImU8String : IDisposable
FixAlignment(startingPos, alignment); FixAlignment(startingPos, alignment);
} }
public void AppendFormatted(object? value) => this.AppendFormatted<object>(value!);
public void AppendFormatted(object? value, string? format) => this.AppendFormatted<object>(value!, format);
public void AppendFormatted(object? value, int alignment) => this.AppendFormatted<object>(value!, alignment);
public void AppendFormatted(object? value, int alignment, string? format) =>
this.AppendFormatted<object>(value!, alignment, format);
public void AppendFormatted<T>(T value) => this.AppendFormatted(value, null); public void AppendFormatted<T>(T value) => this.AppendFormatted(value, null);
public void AppendFormatted<T>(T value, string? format) public void AppendFormatted<T>(T value, string? format)