diff --git a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs index a667be01a..2e1ec8ed0 100644 --- a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs +++ b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs @@ -437,6 +437,13 @@ namespace Robust.Client.Graphics.Clyde _windowing!.WindowSetVisible(reg, visible); } + public void RunOnWindowThread(Action a) + { + DebugTools.AssertNotNull(_windowing); + + _windowing!.RunOnWindowThread(a); + } + private abstract class WindowReg { public bool IsDisposed; diff --git a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs index 8d6cb28bf..aaa45bf6f 100644 --- a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs +++ b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs @@ -251,6 +251,11 @@ namespace Robust.Client.Graphics.Clyde // Nada. } + public void RunOnWindowThread(Action action) + { + action(); + } + private sealed class DummyCursor : ICursor { public void Dispose() diff --git a/Robust.Client/Graphics/Clyde/Windowing/Glfw.WindowThread.cs b/Robust.Client/Graphics/Clyde/Windowing/Glfw.WindowThread.cs index 15e9e5844..1572d5108 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Glfw.WindowThread.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Glfw.WindowThread.cs @@ -118,6 +118,10 @@ namespace Robust.Client.Graphics.Clyde case CmdWinCursorSet cmd: WinThreadWinCursorSet(cmd); break; + + case CmdRunAction cmd: + cmd.Action(); + break; } } @@ -169,6 +173,11 @@ namespace Robust.Client.Graphics.Clyde } } + public void RunOnWindowThread(Action action) + { + SendCmd(new CmdRunAction(action)); + } + private abstract record CmdBase; private sealed record CmdTerminate : CmdBase; @@ -245,6 +254,10 @@ namespace Robust.Client.Graphics.Clyde private sealed record CmdCursorDestroy( ClydeHandle Cursor ) : CmdBase; + + private sealed record CmdRunAction( + Action Action + ) : CmdBase; } } } diff --git a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs index 1cf8addbb..090731bdb 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Robust.Client.Input; using Robust.Shared.Maths; using SixLabors.ImageSharp; @@ -58,6 +59,9 @@ namespace Robust.Client.Graphics.Clyde void GLMakeContextCurrent(WindowReg? reg); void GLSwapInterval(int interval); unsafe void* GLGetProcAddress(string procName); + + // Misc + void RunOnWindowThread(Action a); } } } diff --git a/Robust.Client/Graphics/IClydeInternal.cs b/Robust.Client/Graphics/IClydeInternal.cs index da64db4af..ace25eb9c 100644 --- a/Robust.Client/Graphics/IClydeInternal.cs +++ b/Robust.Client/Graphics/IClydeInternal.cs @@ -63,5 +63,7 @@ namespace Robust.Client.Graphics uint? GetX11WindowId(); void RegisterGridEcsEvents(); + + void RunOnWindowThread(Action action); } } diff --git a/Robust.Client/UserInterface/FileDialogManager.cs b/Robust.Client/UserInterface/FileDialogManager.cs index 3716895c0..5b7ae9af2 100644 --- a/Robust.Client/UserInterface/FileDialogManager.cs +++ b/Robust.Client/UserInterface/FileDialogManager.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; using Robust.Client.Graphics; using Robust.Shared; +using Robust.Shared.Console; using Robust.Shared.Asynchronous; using Robust.Shared.IoC; using Robust.Shared.Log; @@ -164,12 +165,11 @@ namespace Robust.Client.UserInterface { if (OperatingSystem.IsMacOS()) { - // macOS seems pretty annoying about having the file dialog opened from the main thread. - // So we are forced to execute this synchronously on the main thread. - // Also I'm calling RunOnMainThread here to provide safety in case this is ran from a different thread. - // nativefiledialog doesn't provide any form of async API, so this WILL lock up the client. + // macOS seems pretty annoying about having the file dialog opened from the main windowing thread. + // So we are forced to execute this synchronously on the main windowing thread. + // nativefiledialog doesn't provide any form of async API, so this WILL lock up half the client. var tcs = new TaskCompletionSource(); - _taskManager.RunOnMainThread(() => tcs.SetResult(action())); + _clyde.RunOnWindowThread(() => tcs.SetResult(action())); return tcs.Task; } @@ -388,4 +388,17 @@ namespace Robust.Client.UserInterface SW_NFD_CANCEL, } } + + public sealed class OpenFileCommand : IConsoleCommand + { + public string Command => "testopenfile"; + public string Description => ""; + public string Help => ""; + + public async void Execute(IConsoleShell shell, string argStr, string[] args) + { + var stream = await IoCManager.Resolve().OpenFile(); + stream?.Dispose(); + } + } }